1 /* 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.webrtc.voiceengine; 12 13 import android.content.Context; 14 import android.content.pm.PackageManager; 15 import android.os.Build; 16 import android.os.Process; 17 import java.lang.Thread; 18 import java.util.Arrays; 19 import java.util.List; 20 import org.webrtc.Logging; 21 22 public final class WebRtcAudioUtils { 23 private static final String TAG = "WebRtcAudioUtils"; 24 25 // List of devices where we have seen issues (e.g. bad audio quality) using 26 // the low latency output mode in combination with OpenSL ES. 27 // The device name is given by Build.MODEL. 28 private static final String[] BLACKLISTED_OPEN_SL_ES_MODELS = new String[] { 29 // It is recommended to maintain a list of blacklisted models outside 30 // this package and instead call 31 // WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true) 32 // from the client for devices where OpenSL ES shall be disabled. 33 }; 34 35 // List of devices where it has been verified that the built-in effect 36 // bad and where it makes sense to avoid using it and instead rely on the 37 // native WebRTC version instead. The device name is given by Build.MODEL. 38 private static final String[] BLACKLISTED_AEC_MODELS = new String[] { 39 // It is recommended to maintain a list of blacklisted models outside 40 // this package and instead call setWebRtcBasedAcousticEchoCanceler(true) 41 // from the client for devices where the built-in AEC shall be disabled. 42 }; 43 private static final String[] BLACKLISTED_NS_MODELS = new String[] { 44 // It is recommended to maintain a list of blacklisted models outside 45 // this package and instead call setWebRtcBasedNoiseSuppressor(true) 46 // from the client for devices where the built-in NS shall be disabled. 47 }; 48 49 // Use 16kHz as the default sample rate. A higher sample rate might prevent 50 // us from supporting communication mode on some older (e.g. ICS) devices. 51 private static final int DEFAULT_SAMPLE_RATE_HZ = 16000; 52 private static int defaultSampleRateHz = DEFAULT_SAMPLE_RATE_HZ; 53 // Set to true if setDefaultSampleRateHz() has been called. 54 private static boolean isDefaultSampleRateOverridden = false; 55 56 // By default, utilize hardware based audio effects for AEC and NS when 57 // available. 58 private static boolean useWebRtcBasedAcousticEchoCanceler = false; 59 private static boolean useWebRtcBasedNoiseSuppressor = false; 60 61 // Call these methods if any hardware based effect shall be replaced by a 62 // software based version provided by the WebRTC stack instead. 63 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 64 @SuppressWarnings("NoSynchronizedMethodCheck") setWebRtcBasedAcousticEchoCanceler(boolean enable)65 public static synchronized void setWebRtcBasedAcousticEchoCanceler(boolean enable) { 66 useWebRtcBasedAcousticEchoCanceler = enable; 67 } 68 69 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 70 @SuppressWarnings("NoSynchronizedMethodCheck") setWebRtcBasedNoiseSuppressor(boolean enable)71 public static synchronized void setWebRtcBasedNoiseSuppressor(boolean enable) { 72 useWebRtcBasedNoiseSuppressor = enable; 73 } 74 75 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 76 @SuppressWarnings("NoSynchronizedMethodCheck") setWebRtcBasedAutomaticGainControl(boolean enable)77 public static synchronized void setWebRtcBasedAutomaticGainControl(boolean enable) { 78 // TODO(henrika): deprecated; remove when no longer used by any client. 79 Logging.w(TAG, "setWebRtcBasedAutomaticGainControl() is deprecated"); 80 } 81 82 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 83 @SuppressWarnings("NoSynchronizedMethodCheck") useWebRtcBasedAcousticEchoCanceler()84 public static synchronized boolean useWebRtcBasedAcousticEchoCanceler() { 85 if (useWebRtcBasedAcousticEchoCanceler) { 86 Logging.w(TAG, "Overriding default behavior; now using WebRTC AEC!"); 87 } 88 return useWebRtcBasedAcousticEchoCanceler; 89 } 90 91 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 92 @SuppressWarnings("NoSynchronizedMethodCheck") useWebRtcBasedNoiseSuppressor()93 public static synchronized boolean useWebRtcBasedNoiseSuppressor() { 94 if (useWebRtcBasedNoiseSuppressor) { 95 Logging.w(TAG, "Overriding default behavior; now using WebRTC NS!"); 96 } 97 return useWebRtcBasedNoiseSuppressor; 98 } 99 100 // TODO(henrika): deprecated; remove when no longer used by any client. 101 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 102 @SuppressWarnings("NoSynchronizedMethodCheck") useWebRtcBasedAutomaticGainControl()103 public static synchronized boolean useWebRtcBasedAutomaticGainControl() { 104 // Always return true here to avoid trying to use any built-in AGC. 105 return true; 106 } 107 108 // Returns true if the device supports an audio effect (AEC or NS). 109 // Four conditions must be fulfilled if functions are to return true: 110 // 1) the platform must support the built-in (HW) effect, 111 // 2) explicit use (override) of a WebRTC based version must not be set, 112 // 3) the device must not be blacklisted for use of the effect, and 113 // 4) the UUID of the effect must be approved (some UUIDs can be excluded). isAcousticEchoCancelerSupported()114 public static boolean isAcousticEchoCancelerSupported() { 115 return WebRtcAudioEffects.canUseAcousticEchoCanceler(); 116 } isNoiseSuppressorSupported()117 public static boolean isNoiseSuppressorSupported() { 118 return WebRtcAudioEffects.canUseNoiseSuppressor(); 119 } 120 // TODO(henrika): deprecated; remove when no longer used by any client. isAutomaticGainControlSupported()121 public static boolean isAutomaticGainControlSupported() { 122 // Always return false here to avoid trying to use any built-in AGC. 123 return false; 124 } 125 126 // Call this method if the default handling of querying the native sample 127 // rate shall be overridden. Can be useful on some devices where the 128 // available Android APIs are known to return invalid results. 129 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 130 @SuppressWarnings("NoSynchronizedMethodCheck") setDefaultSampleRateHz(int sampleRateHz)131 public static synchronized void setDefaultSampleRateHz(int sampleRateHz) { 132 isDefaultSampleRateOverridden = true; 133 defaultSampleRateHz = sampleRateHz; 134 } 135 136 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 137 @SuppressWarnings("NoSynchronizedMethodCheck") isDefaultSampleRateOverridden()138 public static synchronized boolean isDefaultSampleRateOverridden() { 139 return isDefaultSampleRateOverridden; 140 } 141 142 // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression. 143 @SuppressWarnings("NoSynchronizedMethodCheck") getDefaultSampleRateHz()144 public static synchronized int getDefaultSampleRateHz() { 145 return defaultSampleRateHz; 146 } 147 getBlackListedModelsForAecUsage()148 public static List<String> getBlackListedModelsForAecUsage() { 149 return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AEC_MODELS); 150 } 151 getBlackListedModelsForNsUsage()152 public static List<String> getBlackListedModelsForNsUsage() { 153 return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_NS_MODELS); 154 } 155 runningOnJellyBeanMR1OrHigher()156 public static boolean runningOnJellyBeanMR1OrHigher() { 157 // November 2012: Android 4.2. API Level 17. 158 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; 159 } 160 runningOnJellyBeanMR2OrHigher()161 public static boolean runningOnJellyBeanMR2OrHigher() { 162 // July 24, 2013: Android 4.3. API Level 18. 163 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; 164 } 165 runningOnLollipopOrHigher()166 public static boolean runningOnLollipopOrHigher() { 167 // API Level 21. 168 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 169 } 170 runningOnMarshmallowOrHigher()171 public static boolean runningOnMarshmallowOrHigher() { 172 // API Level 23. 173 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; 174 } 175 runningOnNougatOrHigher()176 public static boolean runningOnNougatOrHigher() { 177 // API Level 24. 178 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; 179 } 180 181 // Helper method for building a string of thread information. getThreadInfo()182 public static String getThreadInfo() { 183 return "@[name=" + Thread.currentThread().getName() + ", id=" + Thread.currentThread().getId() 184 + "]"; 185 } 186 187 // Returns true if we're running on emulator. runningOnEmulator()188 public static boolean runningOnEmulator() { 189 return Build.HARDWARE.equals("goldfish") && Build.BRAND.startsWith("generic_"); 190 } 191 192 // Returns true if the device is blacklisted for OpenSL ES usage. deviceIsBlacklistedForOpenSLESUsage()193 public static boolean deviceIsBlacklistedForOpenSLESUsage() { 194 List<String> blackListedModels = Arrays.asList(BLACKLISTED_OPEN_SL_ES_MODELS); 195 return blackListedModels.contains(Build.MODEL); 196 } 197 198 // Information about the current build, taken from system properties. logDeviceInfo(String tag)199 public static void logDeviceInfo(String tag) { 200 Logging.d(tag, "Android SDK: " + Build.VERSION.SDK_INT + ", " 201 + "Release: " + Build.VERSION.RELEASE + ", " 202 + "Brand: " + Build.BRAND + ", " 203 + "Device: " + Build.DEVICE + ", " 204 + "Id: " + Build.ID + ", " 205 + "Hardware: " + Build.HARDWARE + ", " 206 + "Manufacturer: " + Build.MANUFACTURER + ", " 207 + "Model: " + Build.MODEL + ", " 208 + "Product: " + Build.PRODUCT); 209 } 210 } 211