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