Home | History | Annotate | Download | only in android
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/audio/android/audio_manager_android.h"
      6 
      7 #include "base/android/build_info.h"
      8 #include "base/android/jni_array.h"
      9 #include "base/android/jni_string.h"
     10 #include "base/android/scoped_java_ref.h"
     11 #include "base/logging.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/strings/string_number_conversions.h"
     14 #include "jni/AudioManagerAndroid_jni.h"
     15 #include "media/audio/android/audio_record_input.h"
     16 #include "media/audio/android/opensles_input.h"
     17 #include "media/audio/android/opensles_output.h"
     18 #include "media/audio/audio_manager.h"
     19 #include "media/audio/audio_parameters.h"
     20 #include "media/audio/fake_audio_input_stream.h"
     21 #include "media/base/channel_layout.h"
     22 
     23 using base::android::AppendJavaStringArrayToStringVector;
     24 using base::android::AttachCurrentThread;
     25 using base::android::ConvertJavaStringToUTF8;
     26 using base::android::ConvertUTF8ToJavaString;
     27 using base::android::ScopedJavaLocalRef;
     28 
     29 namespace media {
     30 
     31 static void AddDefaultDevice(AudioDeviceNames* device_names) {
     32   DCHECK(device_names->empty());
     33   device_names->push_front(
     34       AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
     35                       AudioManagerBase::kDefaultDeviceId));
     36 }
     37 
     38 // Maximum number of output streams that can be open simultaneously.
     39 static const int kMaxOutputStreams = 10;
     40 
     41 static const int kDefaultInputBufferSize = 1024;
     42 static const int kDefaultOutputBufferSize = 2048;
     43 
     44 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
     45   return new AudioManagerAndroid(audio_log_factory);
     46 }
     47 
     48 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory)
     49     : AudioManagerBase(audio_log_factory),
     50       communication_mode_is_on_(false) {
     51   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
     52 
     53   // WARNING: This is executed on the UI loop, do not add any code here which
     54   // loads libraries or attempts to call out into the OS.  Instead add such code
     55   // to the InitializeOnAudioThread() method below.
     56 
     57   // Task must be posted last to avoid races from handing out "this" to the
     58   // audio thread.
     59   GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
     60       &AudioManagerAndroid::InitializeOnAudioThread,
     61       base::Unretained(this)));
     62 }
     63 
     64 AudioManagerAndroid::~AudioManagerAndroid() {
     65   // It's safe to post a task here since Shutdown() will wait for all tasks to
     66   // complete before returning.
     67   GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
     68       &AudioManagerAndroid::ShutdownOnAudioThread, base::Unretained(this)));
     69   Shutdown();
     70 }
     71 
     72 bool AudioManagerAndroid::HasAudioOutputDevices() {
     73   return true;
     74 }
     75 
     76 bool AudioManagerAndroid::HasAudioInputDevices() {
     77   return true;
     78 }
     79 
     80 void AudioManagerAndroid::GetAudioInputDeviceNames(
     81     AudioDeviceNames* device_names) {
     82   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
     83 
     84   // Always add default device parameters as first element.
     85   DCHECK(device_names->empty());
     86   AddDefaultDevice(device_names);
     87 
     88   // Get list of available audio devices.
     89   JNIEnv* env = AttachCurrentThread();
     90   ScopedJavaLocalRef<jobjectArray> j_device_array =
     91       Java_AudioManagerAndroid_getAudioInputDeviceNames(
     92           env, j_audio_manager_.obj());
     93   if (j_device_array.is_null()) {
     94     // Most probable reason for a NULL result here is that the process lacks
     95     // MODIFY_AUDIO_SETTINGS or RECORD_AUDIO permissions.
     96     return;
     97   }
     98   jsize len = env->GetArrayLength(j_device_array.obj());
     99   AudioDeviceName device;
    100   for (jsize i = 0; i < len; ++i) {
    101     ScopedJavaLocalRef<jobject> j_device(
    102         env, env->GetObjectArrayElement(j_device_array.obj(), i));
    103     ScopedJavaLocalRef<jstring> j_device_name =
    104         Java_AudioDeviceName_name(env, j_device.obj());
    105     ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name);
    106     ScopedJavaLocalRef<jstring> j_device_id =
    107         Java_AudioDeviceName_id(env, j_device.obj());
    108     ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id);
    109     device_names->push_back(device);
    110   }
    111 }
    112 
    113 void AudioManagerAndroid::GetAudioOutputDeviceNames(
    114     AudioDeviceNames* device_names) {
    115   // TODO(henrika): enumerate using GetAudioInputDeviceNames().
    116   AddDefaultDevice(device_names);
    117 }
    118 
    119 AudioParameters AudioManagerAndroid::GetInputStreamParameters(
    120     const std::string& device_id) {
    121   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    122 
    123   // Use mono as preferred number of input channels on Android to save
    124   // resources. Using mono also avoids a driver issue seen on Samsung
    125   // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details.
    126   JNIEnv* env = AttachCurrentThread();
    127   ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
    128   int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize(
    129       env, GetNativeOutputSampleRate(),
    130       ChannelLayoutToChannelCount(channel_layout));
    131   buffer_size = buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size;
    132   int effects = AudioParameters::NO_EFFECTS;
    133   effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ?
    134       AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS;
    135 
    136   int user_buffer_size = GetUserBufferSize();
    137   if (user_buffer_size)
    138     buffer_size = user_buffer_size;
    139 
    140   AudioParameters params(
    141       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
    142       GetNativeOutputSampleRate(), 16, buffer_size, effects);
    143   return params;
    144 }
    145 
    146 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
    147     const AudioParameters& params,
    148     const std::string& device_id) {
    149   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    150   AudioOutputStream* stream =
    151       AudioManagerBase::MakeAudioOutputStream(params, std::string());
    152   streams_.insert(static_cast<OpenSLESOutputStream*>(stream));
    153   return stream;
    154 }
    155 
    156 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream(
    157     const AudioParameters& params, const std::string& device_id) {
    158   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    159   bool has_no_input_streams = HasNoAudioInputStreams();
    160   AudioInputStream* stream =
    161       AudioManagerBase::MakeAudioInputStream(params, device_id);
    162 
    163   // The audio manager for Android creates streams intended for real-time
    164   // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION.
    165   // If a Bluetooth headset is used, the audio stream will use the SCO
    166   // channel and therefore have a limited bandwidth (8kHz).
    167   if (stream && has_no_input_streams) {
    168     communication_mode_is_on_ = true;
    169     SetCommunicationAudioModeOn(true);
    170   }
    171   return stream;
    172 }
    173 
    174 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) {
    175   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    176   AudioManagerBase::ReleaseOutputStream(stream);
    177   streams_.erase(static_cast<OpenSLESOutputStream*>(stream));
    178 }
    179 
    180 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) {
    181   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    182   DCHECK(!j_audio_manager_.is_null());
    183   AudioManagerBase::ReleaseInputStream(stream);
    184 
    185   // Restore the audio mode which was used before the first communication-
    186   // mode stream was created.
    187   if (HasNoAudioInputStreams()) {
    188     communication_mode_is_on_ = false;
    189     SetCommunicationAudioModeOn(false);
    190   }
    191 }
    192 
    193 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
    194     const AudioParameters& params) {
    195   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    196   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    197   return new OpenSLESOutputStream(this, params, SL_ANDROID_STREAM_MEDIA);
    198 }
    199 
    200 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
    201     const AudioParameters& params,
    202     const std::string& device_id) {
    203   DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
    204   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    205 
    206   // Set stream type which matches the current system-wide audio mode used by
    207   // the Android audio manager.
    208   const SLint32 stream_type = communication_mode_is_on_ ?
    209       SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA;
    210   return new OpenSLESOutputStream(this, params, stream_type);
    211 }
    212 
    213 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream(
    214     const AudioParameters& params, const std::string& device_id) {
    215   // TODO(henrika): add support for device selection if/when any client
    216   // needs it.
    217   DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
    218   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    219   return new OpenSLESInputStream(this, params);
    220 }
    221 
    222 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
    223     const AudioParameters& params, const std::string& device_id) {
    224   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    225   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    226   DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!";
    227 
    228   // Use the device ID to select the correct input device.
    229   // Note that the input device is always associated with a certain output
    230   // device, i.e., this selection does also switch the output device.
    231   // All input and output streams will be affected by the device selection.
    232   if (!SetAudioDevice(device_id)) {
    233     LOG(ERROR) << "Unable to select audio device!";
    234     return NULL;
    235   }
    236 
    237   if (params.effects() != AudioParameters::NO_EFFECTS) {
    238     // Platform effects can only be enabled through the AudioRecord path.
    239     // An effect should only have been requested here if recommended by
    240     // AudioManagerAndroid.shouldUse<Effect>.
    241     //
    242     // Creating this class requires Jelly Bean, which is already guaranteed by
    243     // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use
    244     // the effect settings as a way to select the input path.
    245     DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16);
    246     DVLOG(1) << "Creating AudioRecordInputStream";
    247     return new AudioRecordInputStream(this, params);
    248   }
    249   DVLOG(1) << "Creating OpenSLESInputStream";
    250   return new OpenSLESInputStream(this, params);
    251 }
    252 
    253 // static
    254 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) {
    255   return RegisterNativesImpl(env);
    256 }
    257 
    258 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) {
    259   GetTaskRunner()->PostTask(
    260       FROM_HERE,
    261       base::Bind(
    262           &AudioManagerAndroid::DoSetMuteOnAudioThread,
    263           base::Unretained(this),
    264           muted));
    265 }
    266 
    267 AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters(
    268     const std::string& output_device_id,
    269     const AudioParameters& input_params) {
    270   // TODO(tommi): Support |output_device_id|.
    271   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    272   DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
    273   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
    274   int sample_rate = GetNativeOutputSampleRate();
    275   int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2);
    276   int bits_per_sample = 16;
    277   if (input_params.IsValid()) {
    278     // Use the client's input parameters if they are valid.
    279     sample_rate = input_params.sample_rate();
    280     bits_per_sample = input_params.bits_per_sample();
    281     channel_layout = input_params.channel_layout();
    282     buffer_size = GetOptimalOutputFrameSize(
    283         sample_rate, ChannelLayoutToChannelCount(channel_layout));
    284   }
    285 
    286   int user_buffer_size = GetUserBufferSize();
    287   if (user_buffer_size)
    288     buffer_size = user_buffer_size;
    289 
    290   return AudioParameters(
    291       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
    292       sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
    293 }
    294 
    295 bool AudioManagerAndroid::HasNoAudioInputStreams() {
    296   return input_stream_count() == 0;
    297 }
    298 
    299 void AudioManagerAndroid::InitializeOnAudioThread() {
    300   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    301 
    302   // Create the Android audio manager on the audio thread.
    303   DVLOG(2) << "Creating Java part of the audio manager";
    304   j_audio_manager_.Reset(
    305       Java_AudioManagerAndroid_createAudioManagerAndroid(
    306           base::android::AttachCurrentThread(),
    307           base::android::GetApplicationContext(),
    308           reinterpret_cast<intptr_t>(this)));
    309 
    310   // Prepare the list of audio devices and register receivers for device
    311   // notifications.
    312   Java_AudioManagerAndroid_init(
    313       base::android::AttachCurrentThread(),
    314       j_audio_manager_.obj());
    315 }
    316 
    317 void AudioManagerAndroid::ShutdownOnAudioThread() {
    318   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    319   DVLOG(2) << "Destroying Java part of the audio manager";
    320   Java_AudioManagerAndroid_close(
    321       base::android::AttachCurrentThread(),
    322       j_audio_manager_.obj());
    323   j_audio_manager_.Reset();
    324 }
    325 
    326 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) {
    327   Java_AudioManagerAndroid_setCommunicationAudioModeOn(
    328       base::android::AttachCurrentThread(),
    329       j_audio_manager_.obj(), on);
    330 }
    331 
    332 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) {
    333   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    334 
    335   // Send the unique device ID to the Java audio manager and make the
    336   // device switch. Provide an empty string to the Java audio manager
    337   // if the default device is selected.
    338   JNIEnv* env = AttachCurrentThread();
    339   ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString(
    340       env,
    341       device_id == AudioManagerBase::kDefaultDeviceId ?
    342           std::string() : device_id);
    343   return Java_AudioManagerAndroid_setDevice(
    344       env, j_audio_manager_.obj(), j_device_id.obj());
    345 }
    346 
    347 int AudioManagerAndroid::GetNativeOutputSampleRate() {
    348   return Java_AudioManagerAndroid_getNativeOutputSampleRate(
    349       base::android::AttachCurrentThread(),
    350       j_audio_manager_.obj());
    351 }
    352 
    353 bool AudioManagerAndroid::IsAudioLowLatencySupported() {
    354   return Java_AudioManagerAndroid_isAudioLowLatencySupported(
    355       base::android::AttachCurrentThread(),
    356       j_audio_manager_.obj());
    357 }
    358 
    359 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() {
    360   return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize(
    361       base::android::AttachCurrentThread(),
    362       j_audio_manager_.obj());
    363 }
    364 
    365 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate,
    366                                                    int channels) {
    367   if (IsAudioLowLatencySupported())
    368     return GetAudioLowLatencyOutputFrameSize();
    369 
    370   return std::max(kDefaultOutputBufferSize,
    371                   Java_AudioManagerAndroid_getMinOutputFrameSize(
    372                       base::android::AttachCurrentThread(),
    373                       sample_rate, channels));
    374 }
    375 
    376 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) {
    377   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
    378   for (OutputStreams::iterator it = streams_.begin();
    379        it != streams_.end(); ++it) {
    380     (*it)->SetMute(muted);
    381   }
    382 }
    383 
    384 }  // namespace media
    385