/*
 *  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 static android.media.AudioManager.MODE_IN_CALL;
import static android.media.AudioManager.MODE_IN_COMMUNICATION;
import static android.media.AudioManager.MODE_NORMAL;
import static android.media.AudioManager.MODE_RINGTONE;

import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.AudioRecordingConfiguration;
import android.media.MediaRecorder.AudioSource;
import android.os.Build;
import android.os.Process;
import java.lang.Thread;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.webrtc.ContextUtils;
import org.webrtc.Logging;

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[] {
      // It is recommended to maintain a list of blacklisted models outside
      // this package and instead call
      // WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
      // from the client for devices where OpenSL ES shall be disabled.
  };

  // 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[] {
      // It is recommended to maintain a list of blacklisted models outside
      // this package and instead call setWebRtcBasedAcousticEchoCanceler(true)
      // from the client for devices where the built-in AEC shall be disabled.
  };
  private static final String[] BLACKLISTED_NS_MODELS = new String[] {
    // It is recommended to maintain a list of blacklisted models outside
    // this package and instead call setWebRtcBasedNoiseSuppressor(true)
    // from the client for devices where the built-in NS shall be disabled.
  };

  // 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;

  // By default, utilize hardware based audio effects for AEC and NS when
  // available.
  private static boolean useWebRtcBasedAcousticEchoCanceler;
  private static boolean useWebRtcBasedNoiseSuppressor;

  // Call these methods if any hardware based effect shall be replaced by a
  // software based version provided by the WebRTC stack instead.
  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized void setWebRtcBasedAcousticEchoCanceler(boolean enable) {
    useWebRtcBasedAcousticEchoCanceler = enable;
  }

    // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized void setWebRtcBasedNoiseSuppressor(boolean enable) {
    useWebRtcBasedNoiseSuppressor = enable;
  }

  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized void setWebRtcBasedAutomaticGainControl(boolean enable) {
    // TODO(henrika): deprecated; remove when no longer used by any client.
    Logging.w(TAG, "setWebRtcBasedAutomaticGainControl() is deprecated");
  }

  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized boolean useWebRtcBasedAcousticEchoCanceler() {
    if (useWebRtcBasedAcousticEchoCanceler) {
      Logging.w(TAG, "Overriding default behavior; now using WebRTC AEC!");
    }
    return useWebRtcBasedAcousticEchoCanceler;
  }

  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized boolean useWebRtcBasedNoiseSuppressor() {
    if (useWebRtcBasedNoiseSuppressor) {
      Logging.w(TAG, "Overriding default behavior; now using WebRTC NS!");
    }
    return useWebRtcBasedNoiseSuppressor;
  }

  // TODO(henrika): deprecated; remove when no longer used by any client.
  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized boolean useWebRtcBasedAutomaticGainControl() {
    // Always return true here to avoid trying to use any built-in AGC.
    return true;
  }

  // Returns true if the device supports an audio effect (AEC or NS).
  // Four conditions must be fulfilled if functions are to return true:
  // 1) the platform must support the built-in (HW) effect,
  // 2) explicit use (override) of a WebRTC based version must not be set,
  // 3) the device must not be blacklisted for use of the effect, and
  // 4) the UUID of the effect must be approved (some UUIDs can be excluded).
  public static boolean isAcousticEchoCancelerSupported() {
    return WebRtcAudioEffects.canUseAcousticEchoCanceler();
  }
  public static boolean isNoiseSuppressorSupported() {
    return WebRtcAudioEffects.canUseNoiseSuppressor();
  }
  // TODO(henrika): deprecated; remove when no longer used by any client.
  public static boolean isAutomaticGainControlSupported() {
    // Always return false here to avoid trying to use any built-in AGC.
    return false;
  }

  // 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.
  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized void setDefaultSampleRateHz(int sampleRateHz) {
    isDefaultSampleRateOverridden = true;
    defaultSampleRateHz = sampleRateHz;
  }

  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized boolean isDefaultSampleRateOverridden() {
    return isDefaultSampleRateOverridden;
  }

  // TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
  @SuppressWarnings("NoSynchronizedMethodCheck")
  public static synchronized int getDefaultSampleRateHz() {
    return defaultSampleRateHz;
  }

  public static List<String> getBlackListedModelsForAecUsage() {
    return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_AEC_MODELS);
  }

  public static List<String> getBlackListedModelsForNsUsage() {
    return Arrays.asList(WebRtcAudioUtils.BLACKLISTED_NS_MODELS);
  }

  // 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<String> blackListedModels = Arrays.asList(BLACKLISTED_OPEN_SL_ES_MODELS);
    return blackListedModels.contains(Build.MODEL);
  }

  // Information about the current build, taken from system properties.
  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);
  }

  // Logs information about the current audio state. The idea is to call this
  // method when errors are detected to log under what conditions the error
  // occurred. Hopefully it will provide clues to what might be the root cause.
  static void logAudioState(String tag) {
    logDeviceInfo(tag);
    final Context context = ContextUtils.getApplicationContext();
    final AudioManager audioManager =
        (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    logAudioStateBasic(tag, audioManager);
    logAudioStateVolume(tag, audioManager);
    logAudioDeviceInfo(tag, audioManager);
  }

  // Reports basic audio statistics.
  private static void logAudioStateBasic(String tag, AudioManager audioManager) {
    Logging.d(tag, "Audio State: "
            + "audio mode: " + modeToString(audioManager.getMode()) + ", "
            + "has mic: " + hasMicrophone() + ", "
            + "mic muted: " + audioManager.isMicrophoneMute() + ", "
            + "music active: " + audioManager.isMusicActive() + ", "
            + "speakerphone: " + audioManager.isSpeakerphoneOn() + ", "
            + "BT SCO: " + audioManager.isBluetoothScoOn());
  }

  private static boolean isVolumeFixed(AudioManager audioManager) {
    if (Build.VERSION.SDK_INT < 21) {
      return false;
    }
    return audioManager.isVolumeFixed();
  }

  // Adds volume information for all possible stream types.
  private static void logAudioStateVolume(String tag, AudioManager audioManager) {
    final int[] streams = {
        AudioManager.STREAM_VOICE_CALL,
        AudioManager.STREAM_MUSIC,
        AudioManager.STREAM_RING,
        AudioManager.STREAM_ALARM,
        AudioManager.STREAM_NOTIFICATION,
        AudioManager.STREAM_SYSTEM
    };
    Logging.d(tag, "Audio State: ");
    // Some devices may not have volume controls and might use a fixed volume.
    boolean fixedVolume = isVolumeFixed(audioManager);
    Logging.d(tag, "  fixed volume=" + fixedVolume);
    if (!fixedVolume) {
      for (int stream : streams) {
        StringBuilder info = new StringBuilder();
        info.append("  " + streamTypeToString(stream) + ": ");
        info.append("volume=").append(audioManager.getStreamVolume(stream));
        info.append(", max=").append(audioManager.getStreamMaxVolume(stream));
        logIsStreamMute(tag, audioManager, stream, info);
        Logging.d(tag, info.toString());
      }
    }
  }

  private static void logIsStreamMute(
      String tag, AudioManager audioManager, int stream, StringBuilder info) {
    if (Build.VERSION.SDK_INT >= 23) {
      info.append(", muted=").append(audioManager.isStreamMute(stream));
    }
  }

  private static void logAudioDeviceInfo(String tag, AudioManager audioManager) {
    if (Build.VERSION.SDK_INT < 23) {
      return;
    }
    final AudioDeviceInfo[] devices =
        audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
    if (devices.length == 0) {
      return;
    }
    Logging.d(tag, "Audio Devices: ");
    for (AudioDeviceInfo device : devices) {
      StringBuilder info = new StringBuilder();
      info.append("  ").append(deviceTypeToString(device.getType()));
      info.append(device.isSource() ? "(in): " : "(out): ");
      // An empty array indicates that the device supports arbitrary channel counts.
      if (device.getChannelCounts().length > 0) {
        info.append("channels=").append(Arrays.toString(device.getChannelCounts()));
        info.append(", ");
      }
      if (device.getEncodings().length > 0) {
        // Examples: ENCODING_PCM_16BIT = 2, ENCODING_PCM_FLOAT = 4.
        info.append("encodings=").append(Arrays.toString(device.getEncodings()));
        info.append(", ");
      }
      if (device.getSampleRates().length > 0) {
        info.append("sample rates=").append(Arrays.toString(device.getSampleRates()));
        info.append(", ");
      }
      info.append("id=").append(device.getId());
      Logging.d(tag, info.toString());
    }
  }

  // Converts media.AudioManager modes into local string representation.
  static String modeToString(int mode) {
    switch (mode) {
      case MODE_IN_CALL:
        return "MODE_IN_CALL";
      case MODE_IN_COMMUNICATION:
        return "MODE_IN_COMMUNICATION";
      case MODE_NORMAL:
        return "MODE_NORMAL";
      case MODE_RINGTONE:
        return "MODE_RINGTONE";
      default:
        return "MODE_INVALID";
    }
  }

  private static String streamTypeToString(int stream) {
    switch(stream) {
      case AudioManager.STREAM_VOICE_CALL:
        return "STREAM_VOICE_CALL";
      case AudioManager.STREAM_MUSIC:
        return "STREAM_MUSIC";
      case AudioManager.STREAM_RING:
        return "STREAM_RING";
      case AudioManager.STREAM_ALARM:
        return "STREAM_ALARM";
      case AudioManager.STREAM_NOTIFICATION:
        return "STREAM_NOTIFICATION";
      case AudioManager.STREAM_SYSTEM:
        return "STREAM_SYSTEM";
      default:
        return "STREAM_INVALID";
    }
  }

  // Converts AudioDeviceInfo types to local string representation.
  private static String deviceTypeToString(int type) {
    switch (type) {
      case AudioDeviceInfo.TYPE_UNKNOWN:
        return "TYPE_UNKNOWN";
      case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
        return "TYPE_BUILTIN_EARPIECE";
      case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
        return "TYPE_BUILTIN_SPEAKER";
      case AudioDeviceInfo.TYPE_WIRED_HEADSET:
        return "TYPE_WIRED_HEADSET";
      case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
        return "TYPE_WIRED_HEADPHONES";
      case AudioDeviceInfo.TYPE_LINE_ANALOG:
        return "TYPE_LINE_ANALOG";
      case AudioDeviceInfo.TYPE_LINE_DIGITAL:
        return "TYPE_LINE_DIGITAL";
      case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
        return "TYPE_BLUETOOTH_SCO";
      case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
        return "TYPE_BLUETOOTH_A2DP";
      case AudioDeviceInfo.TYPE_HDMI:
        return "TYPE_HDMI";
      case AudioDeviceInfo.TYPE_HDMI_ARC:
        return "TYPE_HDMI_ARC";
      case AudioDeviceInfo.TYPE_USB_DEVICE:
        return "TYPE_USB_DEVICE";
      case AudioDeviceInfo.TYPE_USB_ACCESSORY:
        return "TYPE_USB_ACCESSORY";
      case AudioDeviceInfo.TYPE_DOCK:
        return "TYPE_DOCK";
      case AudioDeviceInfo.TYPE_FM:
        return "TYPE_FM";
      case AudioDeviceInfo.TYPE_BUILTIN_MIC:
        return "TYPE_BUILTIN_MIC";
      case AudioDeviceInfo.TYPE_FM_TUNER:
        return "TYPE_FM_TUNER";
      case AudioDeviceInfo.TYPE_TV_TUNER:
        return "TYPE_TV_TUNER";
      case AudioDeviceInfo.TYPE_TELEPHONY:
        return "TYPE_TELEPHONY";
      case AudioDeviceInfo.TYPE_AUX_LINE:
        return "TYPE_AUX_LINE";
      case AudioDeviceInfo.TYPE_IP:
        return "TYPE_IP";
      case AudioDeviceInfo.TYPE_BUS:
        return "TYPE_BUS";
      case AudioDeviceInfo.TYPE_USB_HEADSET:
        return "TYPE_USB_HEADSET";
      default:
        return "TYPE_UNKNOWN";
    }
  }

  // Returns true if the device can record audio via a microphone.
  private static boolean hasMicrophone() {
    return ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_MICROPHONE);
  }
}
