text: /*
   *  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.
   */
  
  #ifndef MODULES_AUDIO_DEVICE_ANDROID_AUDIO_MANAGER_H_
  #define MODULES_AUDIO_DEVICE_ANDROID_AUDIO_MANAGER_H_
  
  #include <SLES/OpenSLES.h>
  #include <jni.h>
  
  #include <memory>
  
  #include "modules/audio_device/android/audio_common.h"
  #include "modules/audio_device/android/opensles_common.h"
  #include "modules/audio_device/audio_device_config.h"
  #include "modules/audio_device/audio_device_generic.h"
  #include "modules/audio_device/include/audio_device_defines.h"
  #include "modules/utility/include/helpers_android.h"
  #include "modules/utility/include/jvm_android.h"
  #include "rtc_base/thread_checker.h"
  
  namespace webrtc {
  
  // Implements support for functions in the WebRTC audio stack for Android that
  // relies on the AudioManager in android.media. It also populates an
  // AudioParameter structure with native audio parameters detected at
  // construction. This class does not make any audio-related modifications
  // unless Init() is called. Caching audio parameters makes no changes but only
  // reads data from the Java side.
  class AudioManager {
   public:
    // Wraps the Java specific parts of the AudioManager into one helper class.
    // Stores method IDs for all supported methods at construction and then
    // allows calls like JavaAudioManager::Close() while hiding the Java/JNI
    // parts that are associated with this call.
    class JavaAudioManager {
     public:
      JavaAudioManager(NativeRegistration* native_registration,
                       std::unique_ptr<GlobalRef> audio_manager);
      ~JavaAudioManager();
  
      bool Init();
      void Close();
      bool IsCommunicationModeEnabled();
      bool IsDeviceBlacklistedForOpenSLESUsage();
  
     private:
      std::unique_ptr<GlobalRef> audio_manager_;
      jmethodID init_;
      jmethodID dispose_;
      jmethodID is_communication_mode_enabled_;
      jmethodID is_device_blacklisted_for_open_sles_usage_;
    };
  
    AudioManager();
    ~AudioManager();
  
    // Sets the currently active audio layer combination. Must be called before
    // Init().
    void SetActiveAudioLayer(AudioDeviceModule::AudioLayer audio_layer);
  
    // Creates and realizes the main (global) Open SL engine object and returns
    // a reference to it. The engine object is only created at the first call
    // since OpenSL ES for Android only supports a single engine per application.
    // Subsequent calls returns the already created engine. The SL engine object
    // is destroyed when the AudioManager object is deleted. It means that the
    // engine object will be the first OpenSL ES object to be created and last
    // object to be destroyed.
    // Note that NULL will be returned unless the audio layer is specified as
    // AudioDeviceModule::kAndroidOpenSLESAudio or
    // AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio.
    SLObjectItf GetOpenSLEngine();
  
    // Initializes the audio manager and stores the current audio mode.
    bool Init();
    // Revert any setting done by Init().
    bool Close();
  
    // Returns true if current audio mode is AudioManager.MODE_IN_COMMUNICATION.
    bool IsCommunicationModeEnabled() const;
  
    // Native audio parameters stored during construction.
    const AudioParameters& GetPlayoutAudioParameters();
    const AudioParameters& GetRecordAudioParameters();
  
    // Returns true if the device supports built-in audio effects for AEC, AGC
    // and NS. Some devices can also be blacklisted for use in combination with
    // platform effects and these devices will return false.
    // Can currently only be used in combination with a Java based audio backend
    // for the recoring side (i.e. using the android.media.AudioRecord API).
    bool IsAcousticEchoCancelerSupported() const;
    bool IsAutomaticGainControlSupported() const;
    bool IsNoiseSuppressorSupported() const;
  
    // Returns true if the device supports the low-latency audio paths in
    // combination with OpenSL ES.
    bool IsLowLatencyPlayoutSupported() const;
    bool IsLowLatencyRecordSupported() const;
  
    // Returns true if the device supports (and has been configured for) stereo.
    // Call the Java API WebRtcAudioManager.setStereoOutput/Input() with true as
    // paramter to enable stereo. Default is mono in both directions and the
    // setting is set once and for all when the audio manager object is created.
    // TODO(henrika): stereo is not supported in combination with OpenSL ES.
    bool IsStereoPlayoutSupported() const;
    bool IsStereoRecordSupported() const;
  
    // Returns true if the device supports pro-audio features in combination with
    // OpenSL ES.
    bool IsProAudioSupported() const;
  
    // Returns true if the device supports AAudio.
    bool IsAAudioSupported() const;
  
    // Returns the estimated total delay of this device. Unit is in milliseconds.
    // The vaule is set once at construction and never changes after that.
    // Possible values are webrtc::kLowLatencyModeDelayEstimateInMilliseconds and
    // webrtc::kHighLatencyModeDelayEstimateInMilliseconds.
    int GetDelayEstimateInMilliseconds() const;
  
   private:
    // Called from Java side so we can cache the native audio parameters.
    // This method will be called by the WebRtcAudioManager constructor, i.e.
    // on the same thread that this object is created on.
    static void JNICALL CacheAudioParameters(JNIEnv* env,
                                             jobject obj,
                                             jint sample_rate,
                                             jint output_channels,
                                             jint input_channels,
                                             jboolean hardware_aec,
                                             jboolean hardware_agc,
                                             jboolean hardware_ns,
                                             jboolean low_latency_output,
                                             jboolean low_latency_input,
                                             jboolean pro_audio,
                                             jboolean a_audio,
                                             jint output_buffer_size,
                                             jint input_buffer_size,
                                             jlong native_audio_manager);
    void OnCacheAudioParameters(JNIEnv* env,
                                jint sample_rate,
                                jint output_channels,
                                jint input_channels,
                                jboolean hardware_aec,
                                jboolean hardware_agc,
                                jboolean hardware_ns,
                                jboolean low_latency_output,
                                jboolean low_latency_input,
                                jboolean pro_audio,
                                jboolean a_audio,
                                jint output_buffer_size,
                                jint input_buffer_size);
  
    // Stores thread ID in the constructor.
    // We can then use ThreadChecker::IsCurrent() to ensure that
    // other methods are called from the same thread.
    rtc::ThreadChecker thread_checker_;
  
    // Calls JavaVM::AttachCurrentThread() if this thread is not attached at
    // construction.
    // Also ensures that DetachCurrentThread() is called at destruction.
    JvmThreadConnector attach_thread_if_needed_;
  
    // Wraps the JNI interface pointer and methods associated with it.
    std::unique_ptr<JNIEnvironment> j_environment_;
  
    // Contains factory method for creating the Java object.
    std::unique_ptr<NativeRegistration> j_native_registration_;
  
    // Wraps the Java specific parts of the AudioManager.
    std::unique_ptr<AudioManager::JavaAudioManager> j_audio_manager_;
  
    // Contains the selected audio layer specified by the AudioLayer enumerator
    // in the AudioDeviceModule class.
    AudioDeviceModule::AudioLayer audio_layer_;
  
    // This object is the global entry point of the OpenSL ES API.
    // After creating the engine object, the application can obtain this object‘s
    // SLEngineItf interface. This interface contains creation methods for all
    // the other object types in the API. None of these interface are realized
    // by this class. It only provides access to the global engine object.
    webrtc::ScopedSLObjectItf engine_object_;
  
    // Set to true by Init() and false by Close().
    bool initialized_;
  
    // True if device supports hardware (or built-in) AEC.
    bool hardware_aec_;
    // True if device supports hardware (or built-in) AGC.
    bool hardware_agc_;
    // True if device supports hardware (or built-in) NS.
    bool hardware_ns_;
  
    // True if device supports the low-latency OpenSL ES audio path for output.
    bool low_latency_playout_;
  
    // True if device supports the low-latency OpenSL ES audio path for input.
    bool low_latency_record_;
  
    // True if device supports the low-latency OpenSL ES pro-audio path.
    bool pro_audio_;
  
    // True if device supports the low-latency AAudio audio path.
    bool a_audio_;
  
    // The delay estimate can take one of two fixed values depending on if the
    // device supports low-latency output or not.
    int delay_estimate_in_milliseconds_;
  
    // Contains native parameters (e.g. sample rate, channel configuration).
    // Set at construction in OnCacheAudioParameters() which is called from
    // Java on the same thread as this object is created on.
    AudioParameters playout_parameters_;
    AudioParameters record_parameters_;
  };
  
  }  // namespace webrtc
  
  #endif  // MODULES_AUDIO_DEVICE_ANDROID_AUDIO_MANAGER_H_
  