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