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.media.audiofx.AcousticEchoCanceler; 16 import android.media.audiofx.AudioEffect; 17 import android.media.audiofx.AudioEffect.Descriptor; 18 import android.media.AudioManager; 19 import android.os.Build; 20 import android.os.Process; 21 22 import org.webrtc.Logging; 23 24 import java.lang.Thread; 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.List; 28 29 public final class WebRtcAudioUtils { 30 private static final String TAG = "WebRtcAudioUtils"; 31 32 // List of devices where we have seen issues (e.g. bad audio quality) using 33 // the low latency output mode in combination with OpenSL ES. 34 // The device name is given by Build.MODEL. 35 private static final String[] BLACKLISTED_OPEN_SL_ES_MODELS = new String[] { 36 // This list is currently empty ;-) 37 }; 38 39 // List of devices where it has been verified that the built-in effect 40 // bad and where it makes sense to avoid using it and instead rely on the 41 // native WebRTC version instead. The device name is given by Build.MODEL. 42 private static final String[] BLACKLISTED_AEC_MODELS = new String[] { 43 "Nexus 5", 44 "D6503", // Sony Xperia Z2 D6503 45 "ONE A2005", // OnePlus 2 46 }; 47 private static final String[] BLACKLISTED_AGC_MODELS = new String[] { 48 "Nexus 10", 49 "Nexus 9", 50 }; 51 private static final String[] BLACKLISTED_NS_MODELS = new String[] { 52 "Nexus 10", 53 "Nexus 9", 54 "Nexus 5", 55 "ONE A2005", // OnePlus 2 56 }; 57 58 // Use 16kHz as the default sample rate. A higher sample rate might prevent 59 // us from supporting communication mode on some older (e.g. ICS) devices. 60 private static final int DEFAULT_SAMPLE_RATE_HZ = 16000; 61 private static int defaultSampleRateHz = DEFAULT_SAMPLE_RATE_HZ; 62 // Set to true if setDefaultSampleRateHz() has been called. 63 private static boolean isDefaultSampleRateOverridden = false; 64 65 // By default, utilize hardware based audio effects when available. 66 private static boolean useWebRtcBasedAcousticEchoCanceler = false; 67 private static boolean useWebRtcBasedAutomaticGainControl = false; 68 private static boolean useWebRtcBasedNoiseSuppressor = false; 69 70 // Call these methods if any hardware based effect shall be replaced by a 71 // software based version provided by the WebRTC stack instead. setWebRtcBasedAcousticEchoCanceler( boolean enable)72 public static synchronized void setWebRtcBasedAcousticEchoCanceler( 73 boolean enable) { 74 useWebRtcBasedAcousticEchoCanceler = enable; 75 } setWebRtcBasedAutomaticGainControl( boolean enable)76 public static synchronized void setWebRtcBasedAutomaticGainControl( 77 boolean enable) { 78 useWebRtcBasedAutomaticGainControl = enable; 79 } setWebRtcBasedNoiseSuppressor( boolean enable)80 public static synchronized void setWebRtcBasedNoiseSuppressor( 81 boolean enable) { 82 useWebRtcBasedNoiseSuppressor = enable; 83 } 84 useWebRtcBasedAcousticEchoCanceler()85 public static synchronized boolean useWebRtcBasedAcousticEchoCanceler() { 86 if (useWebRtcBasedAcousticEchoCanceler) { 87 Logging.w(TAG, "Overriding default behavior; now using WebRTC AEC!"); 88 } 89 return useWebRtcBasedAcousticEchoCanceler; 90 } useWebRtcBasedAutomaticGainControl()91 public static synchronized boolean useWebRtcBasedAutomaticGainControl() { 92 if (useWebRtcBasedAutomaticGainControl) { 93 Logging.w(TAG, "Overriding default behavior; now using WebRTC AGC!"); 94 } 95 return useWebRtcBasedAutomaticGainControl; 96 } useWebRtcBasedNoiseSuppressor()97 public static synchronized boolean useWebRtcBasedNoiseSuppressor() { 98 if (useWebRtcBasedNoiseSuppressor) { 99 Logging.w(TAG, "Overriding default behavior; now using WebRTC NS!"); 100 } 101 return useWebRtcBasedNoiseSuppressor; 102 } 103 104 // Call this method if the default handling of querying the native sample 105 // rate shall be overridden. Can be useful on some devices where the 106 // available Android APIs are known to return invalid results. setDefaultSampleRateHz(int sampleRateHz)107 public static synchronized void setDefaultSampleRateHz(int sampleRateHz) { 108 isDefaultSampleRateOverridden = true; 109 defaultSampleRateHz = sampleRateHz; 110 } 111 isDefaultSampleRateOverridden()112 public static synchronized boolean isDefaultSampleRateOverridden() { 113 return isDefaultSampleRateOverridden; 114 } 115 getDefaultSampleRateHz()116 public static synchronized int getDefaultSampleRateHz() { 117 return defaultSampleRateHz; 118 } 119 getBlackListedModelsForAecUsage()120 public static List<String> getBlackListedModelsForAecUsage() { 121 return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AEC_MODELS); 122 } 123 getBlackListedModelsForAgcUsage()124 public static List<String> getBlackListedModelsForAgcUsage() { 125 return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AGC_MODELS); 126 } 127 getBlackListedModelsForNsUsage()128 public static List<String> getBlackListedModelsForNsUsage() { 129 return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_NS_MODELS); 130 } 131 runningOnGingerBreadOrHigher()132 public static boolean runningOnGingerBreadOrHigher() { 133 // November 2010: Android 2.3, API Level 9. 134 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; 135 } 136 runningOnJellyBeanOrHigher()137 public static boolean runningOnJellyBeanOrHigher() { 138 // June 2012: Android 4.1. API Level 16. 139 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 140 } 141 runningOnJellyBeanMR1OrHigher()142 public static boolean runningOnJellyBeanMR1OrHigher() { 143 // November 2012: Android 4.2. API Level 17. 144 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; 145 } 146 runningOnJellyBeanMR2OrHigher()147 public static boolean runningOnJellyBeanMR2OrHigher() { 148 // July 24, 2013: Android 4.3. API Level 18. 149 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; 150 } 151 runningOnLollipopOrHigher()152 public static boolean runningOnLollipopOrHigher() { 153 // API Level 21. 154 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 155 } 156 157 // TODO(phoglund): enable when all downstream users use M. 158 // public static boolean runningOnMOrHigher() { 159 // API Level 23. 160 // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; 161 //} 162 163 // Helper method for building a string of thread information. getThreadInfo()164 public static String getThreadInfo() { 165 return "@[name=" + Thread.currentThread().getName() 166 + ", id=" + Thread.currentThread().getId() + "]"; 167 } 168 169 // Returns true if we're running on emulator. runningOnEmulator()170 public static boolean runningOnEmulator() { 171 return Build.HARDWARE.equals("goldfish") && 172 Build.BRAND.startsWith("generic_"); 173 } 174 175 // Returns true if the device is blacklisted for OpenSL ES usage. deviceIsBlacklistedForOpenSLESUsage()176 public static boolean deviceIsBlacklistedForOpenSLESUsage() { 177 List<String> blackListedModels = 178 Arrays.asList(BLACKLISTED_OPEN_SL_ES_MODELS); 179 return blackListedModels.contains(Build.MODEL); 180 } 181 182 // Information about the current build, taken from system properties. logDeviceInfo(String tag)183 public static void logDeviceInfo(String tag) { 184 Logging.d(tag, "Android SDK: " + Build.VERSION.SDK_INT + ", " 185 + "Release: " + Build.VERSION.RELEASE + ", " 186 + "Brand: " + Build.BRAND + ", " 187 + "Device: " + Build.DEVICE + ", " 188 + "Id: " + Build.ID + ", " 189 + "Hardware: " + Build.HARDWARE + ", " 190 + "Manufacturer: " + Build.MANUFACTURER + ", " 191 + "Model: " + Build.MODEL + ", " 192 + "Product: " + Build.PRODUCT); 193 } 194 195 // Checks if the process has as specified permission or not. hasPermission(Context context, String permission)196 public static boolean hasPermission(Context context, String permission) { 197 return context.checkPermission( 198 permission, 199 Process.myPid(), 200 Process.myUid()) == PackageManager.PERMISSION_GRANTED; 201 } 202 } 203