/* * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ package org.webrtc.voiceengine; import android.content.Context; import android.content.pm.PackageManager; import android.media.audiofx.AcousticEchoCanceler; import android.media.audiofx.AudioEffect; import android.media.audiofx.AudioEffect.Descriptor; import android.media.AudioManager; import android.os.Build; import android.os.Process; import org.webrtc.Logging; import java.lang.Thread; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public final class WebRtcAudioUtils { private static final String TAG = "WebRtcAudioUtils"; // List of devices where we have seen issues (e.g. bad audio quality) using // the low latency output mode in combination with OpenSL ES. // The device name is given by Build.MODEL. private static final String[] BLACKLISTED_OPEN_SL_ES_MODELS = new String[] { // This list is currently empty ;-) }; // List of devices where it has been verified that the built-in effect // bad and where it makes sense to avoid using it and instead rely on the // native WebRTC version instead. The device name is given by Build.MODEL. private static final String[] BLACKLISTED_AEC_MODELS = new String[] { "Nexus 5", "D6503", // Sony Xperia Z2 D6503 "ONE A2005", // OnePlus 2 }; private static final String[] BLACKLISTED_AGC_MODELS = new String[] { "Nexus 10", "Nexus 9", }; private static final String[] BLACKLISTED_NS_MODELS = new String[] { "Nexus 10", "Nexus 9", "Nexus 5", "ONE A2005", // OnePlus 2 }; // Use 16kHz as the default sample rate. A higher sample rate might prevent // us from supporting communication mode on some older (e.g. ICS) devices. private static final int DEFAULT_SAMPLE_RATE_HZ = 16000; private static int defaultSampleRateHz = DEFAULT_SAMPLE_RATE_HZ; // Set to true if setDefaultSampleRateHz() has been called. private static boolean isDefaultSampleRateOverridden = false; // By default, utilize hardware based audio effects when available. private static boolean useWebRtcBasedAcousticEchoCanceler = false; private static boolean useWebRtcBasedAutomaticGainControl = false; private static boolean useWebRtcBasedNoiseSuppressor = false; // Call these methods if any hardware based effect shall be replaced by a // software based version provided by the WebRTC stack instead. public static synchronized void setWebRtcBasedAcousticEchoCanceler( boolean enable) { useWebRtcBasedAcousticEchoCanceler = enable; } public static synchronized void setWebRtcBasedAutomaticGainControl( boolean enable) { useWebRtcBasedAutomaticGainControl = enable; } public static synchronized void setWebRtcBasedNoiseSuppressor( boolean enable) { useWebRtcBasedNoiseSuppressor = enable; } public static synchronized boolean useWebRtcBasedAcousticEchoCanceler() { if (useWebRtcBasedAcousticEchoCanceler) { Logging.w(TAG, "Overriding default behavior; now using WebRTC AEC!"); } return useWebRtcBasedAcousticEchoCanceler; } public static synchronized boolean useWebRtcBasedAutomaticGainControl() { if (useWebRtcBasedAutomaticGainControl) { Logging.w(TAG, "Overriding default behavior; now using WebRTC AGC!"); } return useWebRtcBasedAutomaticGainControl; } public static synchronized boolean useWebRtcBasedNoiseSuppressor() { if (useWebRtcBasedNoiseSuppressor) { Logging.w(TAG, "Overriding default behavior; now using WebRTC NS!"); } return useWebRtcBasedNoiseSuppressor; } // Call this method if the default handling of querying the native sample // rate shall be overridden. Can be useful on some devices where the // available Android APIs are known to return invalid results. public static synchronized void setDefaultSampleRateHz(int sampleRateHz) { isDefaultSampleRateOverridden = true; defaultSampleRateHz = sampleRateHz; } public static synchronized boolean isDefaultSampleRateOverridden() { return isDefaultSampleRateOverridden; } public static synchronized int getDefaultSampleRateHz() { return defaultSampleRateHz; } public static List getBlackListedModelsForAecUsage() { return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AEC_MODELS); } public static List getBlackListedModelsForAgcUsage() { return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AGC_MODELS); } public static List getBlackListedModelsForNsUsage() { return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_NS_MODELS); } public static boolean runningOnGingerBreadOrHigher() { // November 2010: Android 2.3, API Level 9. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; } public static boolean runningOnJellyBeanOrHigher() { // June 2012: Android 4.1. API Level 16. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; } public static boolean runningOnJellyBeanMR1OrHigher() { // November 2012: Android 4.2. API Level 17. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; } public static boolean runningOnJellyBeanMR2OrHigher() { // July 24, 2013: Android 4.3. API Level 18. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; } public static boolean runningOnLollipopOrHigher() { // API Level 21. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; } // TODO(phoglund): enable when all downstream users use M. // public static boolean runningOnMOrHigher() { // API Level 23. // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; //} // Helper method for building a string of thread information. public static String getThreadInfo() { return "@[name=" + Thread.currentThread().getName() + ", id=" + Thread.currentThread().getId() + "]"; } // Returns true if we're running on emulator. public static boolean runningOnEmulator() { return Build.HARDWARE.equals("goldfish") && Build.BRAND.startsWith("generic_"); } // Returns true if the device is blacklisted for OpenSL ES usage. public static boolean deviceIsBlacklistedForOpenSLESUsage() { List blackListedModels = Arrays.asList(BLACKLISTED_OPEN_SL_ES_MODELS); return blackListedModels.contains(Build.MODEL); } // Information about the current build, taken from system properties. public static void logDeviceInfo(String tag) { Logging.d(tag, "Android SDK: " + Build.VERSION.SDK_INT + ", " + "Release: " + Build.VERSION.RELEASE + ", " + "Brand: " + Build.BRAND + ", " + "Device: " + Build.DEVICE + ", " + "Id: " + Build.ID + ", " + "Hardware: " + Build.HARDWARE + ", " + "Manufacturer: " + Build.MANUFACTURER + ", " + "Model: " + Build.MODEL + ", " + "Product: " + Build.PRODUCT); } // Checks if the process has as specified permission or not. public static boolean hasPermission(Context context, String permission) { return context.checkPermission( permission, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED; } }