Home | History | Annotate | Download | only in voiceengine
      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.
     72   public static synchronized void setWebRtcBasedAcousticEchoCanceler(
     73       boolean enable) {
     74     useWebRtcBasedAcousticEchoCanceler = enable;
     75   }
     76   public static synchronized void setWebRtcBasedAutomaticGainControl(
     77       boolean enable) {
     78     useWebRtcBasedAutomaticGainControl = enable;
     79   }
     80   public static synchronized void setWebRtcBasedNoiseSuppressor(
     81       boolean enable) {
     82     useWebRtcBasedNoiseSuppressor = enable;
     83   }
     84 
     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   }
     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   }
     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.
    107   public static synchronized void setDefaultSampleRateHz(int sampleRateHz) {
    108     isDefaultSampleRateOverridden = true;
    109     defaultSampleRateHz = sampleRateHz;
    110   }
    111 
    112   public static synchronized boolean isDefaultSampleRateOverridden() {
    113     return isDefaultSampleRateOverridden;
    114   }
    115 
    116   public static synchronized int getDefaultSampleRateHz() {
    117     return defaultSampleRateHz;
    118   }
    119 
    120   public static List<String> getBlackListedModelsForAecUsage() {
    121     return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AEC_MODELS);
    122   }
    123 
    124   public static List<String> getBlackListedModelsForAgcUsage() {
    125     return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AGC_MODELS);
    126   }
    127 
    128   public static List<String> getBlackListedModelsForNsUsage() {
    129     return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_NS_MODELS);
    130   }
    131 
    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 
    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 
    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 
    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 
    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.
    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.
    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.
    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.
    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.
    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