Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1057)

Side by Side Diff: media/audio/android/audio_manager_android.cc

Issue 131503006: Initialization of audio manager for Android is now done on the audio thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added use of CreateAndInit in more methods Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/android/audio_manager_android.h" 5 #include "media/audio/android/audio_manager_android.h"
6 6
7 #include "base/android/build_info.h" 7 #include "base/android/build_info.h"
8 #include "base/android/jni_array.h" 8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h" 9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h" 10 #include "base/android/scoped_java_ref.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
13 #include "jni/AudioManagerAndroid_jni.h" 14 #include "jni/AudioManagerAndroid_jni.h"
14 #include "media/audio/android/audio_record_input.h" 15 #include "media/audio/android/audio_record_input.h"
15 #include "media/audio/android/opensles_input.h" 16 #include "media/audio/android/opensles_input.h"
16 #include "media/audio/android/opensles_output.h" 17 #include "media/audio/android/opensles_output.h"
17 #include "media/audio/audio_manager.h" 18 #include "media/audio/audio_manager.h"
18 #include "media/audio/audio_parameters.h" 19 #include "media/audio/audio_parameters.h"
19 #include "media/audio/fake_audio_input_stream.h" 20 #include "media/audio/fake_audio_input_stream.h"
20 #include "media/base/channel_layout.h" 21 #include "media/base/channel_layout.h"
21 22
(...skipping 18 matching lines...) Expand all
40 static const int kDefaultInputBufferSize = 1024; 41 static const int kDefaultInputBufferSize = 1024;
41 static const int kDefaultOutputBufferSize = 2048; 42 static const int kDefaultOutputBufferSize = 2048;
42 43
43 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { 44 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
44 return new AudioManagerAndroid(audio_log_factory); 45 return new AudioManagerAndroid(audio_log_factory);
45 } 46 }
46 47
47 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory) 48 AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory)
48 : AudioManagerBase(audio_log_factory) { 49 : AudioManagerBase(audio_log_factory) {
49 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 50 SetMaxOutputStreamsAllowed(kMaxOutputStreams);
50
51 j_audio_manager_.Reset(
tommi (sloooow) - chröme 2014/02/04 14:30:12 yay!
henrika (OOO until Aug 14) 2014/02/05 09:45:57 thx
52 Java_AudioManagerAndroid_createAudioManagerAndroid(
53 base::android::AttachCurrentThread(),
54 base::android::GetApplicationContext(),
55 reinterpret_cast<intptr_t>(this)));
56 Init();
57 } 51 }
58 52
59 AudioManagerAndroid::~AudioManagerAndroid() { 53 AudioManagerAndroid::~AudioManagerAndroid() {
60 Close();
61 Shutdown(); 54 Shutdown();
55 // Verify that WillDestroyCurrentMessageLoop() has been called.
56 DCHECK(j_audio_manager_.is_null());
62 } 57 }
63 58
64 bool AudioManagerAndroid::HasAudioOutputDevices() { 59 bool AudioManagerAndroid::HasAudioOutputDevices() {
65 return true; 60 return true;
66 } 61 }
67 62
68 bool AudioManagerAndroid::HasAudioInputDevices() { 63 bool AudioManagerAndroid::HasAudioInputDevices() {
69 return true; 64 return true;
70 } 65 }
71 66
72 void AudioManagerAndroid::GetAudioInputDeviceNames( 67 void AudioManagerAndroid::GetAudioInputDeviceNames(
73 AudioDeviceNames* device_names) { 68 AudioDeviceNames* device_names) {
74 // Always add default device parameters as first element. 69 CreateAndInitOnAudioThread();
75 DCHECK(device_names->empty());
76 AddDefaultDevice(device_names);
77 70
78 JNIEnv* env = AttachCurrentThread(); 71 // Get list of available audio devices and use the audio thread to reduce
79 ScopedJavaLocalRef<jobjectArray> j_device_array = 72 // the number of calling threads to the Java layer. Also, ensure that the
80 Java_AudioManagerAndroid_getAudioInputDeviceNames( 73 // calling thread sees this function call as synchronous.
81 env, j_audio_manager_.obj()); 74 scoped_refptr<base::SingleThreadTaskRunner> task_runner(GetTaskRunner());
82 jsize len = env->GetArrayLength(j_device_array.obj()); 75 if (task_runner->BelongsToCurrentThread()) {
83 AudioDeviceName device; 76 GetAudioInputDeviceNamesOnAudioThread(NULL, device_names);
84 for (jsize i = 0; i < len; ++i) { 77 } else {
85 ScopedJavaLocalRef<jobject> j_device( 78 base::WaitableEvent event(false, false);
86 env, env->GetObjectArrayElement(j_device_array.obj(), i)); 79 task_runner->PostTask(
87 ScopedJavaLocalRef<jstring> j_device_name = 80 FROM_HERE,
88 Java_AudioDeviceName_name(env, j_device.obj()); 81 base::Bind(
89 ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name); 82 &AudioManagerAndroid::GetAudioInputDeviceNamesOnAudioThread,
90 ScopedJavaLocalRef<jstring> j_device_id = 83 base::Unretained(this),
91 Java_AudioDeviceName_id(env, j_device.obj()); 84 &event,
92 ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id); 85 device_names));
93 device_names->push_back(device); 86 event.Wait();
94 } 87 }
95 } 88 }
96 89
97 void AudioManagerAndroid::GetAudioOutputDeviceNames( 90 void AudioManagerAndroid::GetAudioOutputDeviceNames(
98 AudioDeviceNames* device_names) { 91 AudioDeviceNames* device_names) {
99 // TODO(henrika): enumerate using GetAudioInputDeviceNames(). 92 // TODO(henrika): enumerate using GetAudioInputDeviceNames().
100 AddDefaultDevice(device_names); 93 AddDefaultDevice(device_names);
101 } 94 }
102 95
103 AudioParameters AudioManagerAndroid::GetInputStreamParameters( 96 AudioParameters AudioManagerAndroid::GetInputStreamParameters(
104 const std::string& device_id) { 97 const std::string& device_id) {
105 JNIEnv* env = AttachCurrentThread(); 98 CreateAndInitOnAudioThread();
99
106 // Use mono as preferred number of input channels on Android to save 100 // Use mono as preferred number of input channels on Android to save
107 // resources. Using mono also avoids a driver issue seen on Samsung 101 // resources. Using mono also avoids a driver issue seen on Samsung
108 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details. 102 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details.
103 // TODO(henrika): do we nee a requirement to call the rest of this method
tommi (sloooow) - chröme 2014/02/04 14:30:12 typo I assume this with regards to Dale's questio
henrika (OOO until Aug 14) 2014/02/05 09:45:57 Done.
104 // on the audio thread?
105 JNIEnv* env = AttachCurrentThread();
106 CHECK(env);
109 ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO; 107 ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
110 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize( 108 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize(
111 env, GetNativeOutputSampleRate(), 109 env, GetNativeOutputSampleRate(),
112 ChannelLayoutToChannelCount(channel_layout)); 110 ChannelLayoutToChannelCount(channel_layout));
113 int effects = AudioParameters::NO_EFFECTS; 111 int effects = AudioParameters::NO_EFFECTS;
114 effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ? 112 effects |= Java_AudioManagerAndroid_shouldUseAcousticEchoCanceler(env) ?
115 AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS; 113 AudioParameters::ECHO_CANCELLER : AudioParameters::NO_EFFECTS;
116 AudioParameters params( 114 AudioParameters params(
117 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, 115 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0,
118 GetNativeOutputSampleRate(), 16, 116 GetNativeOutputSampleRate(), 16,
(...skipping 20 matching lines...) Expand all
139 { 137 {
140 base::AutoLock lock(streams_lock_); 138 base::AutoLock lock(streams_lock_);
141 streams_.insert(static_cast<OpenSLESOutputStream*>(stream)); 139 streams_.insert(static_cast<OpenSLESOutputStream*>(stream));
142 } 140 }
143 141
144 return stream; 142 return stream;
145 } 143 }
146 144
147 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( 145 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream(
148 const AudioParameters& params, const std::string& device_id) { 146 const AudioParameters& params, const std::string& device_id) {
147 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
148 CreateAndInitOnAudioThread();
149 bool had_no_streams = HadNoAudioStreams(); 149 bool had_no_streams = HadNoAudioStreams();
150 AudioInputStream* stream = 150 AudioInputStream* stream =
151 AudioManagerBase::MakeAudioInputStream(params, device_id); 151 AudioManagerBase::MakeAudioInputStream(params, device_id);
152 152
153 // The audio manager for Android creates streams intended for real-time 153 // The audio manager for Android creates streams intended for real-time
154 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION. 154 // VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION.
155 // If a Bluetooth headset is used, the audio stream will use the SCO 155 // If a Bluetooth headset is used, the audio stream will use the SCO
156 // channel and therefore have a limited bandwidth (8kHz). 156 // channel and therefore have a limited bandwidth (8kHz).
157 if (stream && had_no_streams) 157 if (stream && had_no_streams)
158 SetCommunicationAudioModeOn(true); 158 SetCommunicationAudioModeOn(true);
159 return stream; 159 return stream;
160 } 160 }
161 161
162 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { 162 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) {
163 AudioManagerBase::ReleaseOutputStream(stream); 163 AudioManagerBase::ReleaseOutputStream(stream);
164 164
165 // Restore the audio mode which was used before the first communication- 165 // Restore the audio mode which was used before the first communication-
166 // mode stream was created. 166 // mode stream was created.
167 if (HadNoAudioStreams()) 167 if (HadNoAudioStreams())
168 SetCommunicationAudioModeOn(false); 168 SetCommunicationAudioModeOn(false);
169 base::AutoLock lock(streams_lock_); 169 base::AutoLock lock(streams_lock_);
170 streams_.erase(static_cast<OpenSLESOutputStream*>(stream)); 170 streams_.erase(static_cast<OpenSLESOutputStream*>(stream));
171 } 171 }
172 172
173 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { 173 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) {
174 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
175 DCHECK(!j_audio_manager_.is_null());
174 AudioManagerBase::ReleaseInputStream(stream); 176 AudioManagerBase::ReleaseInputStream(stream);
175 177
176 // Restore the audio mode which was used before the first communication- 178 // Restore the audio mode which was used before the first communication-
177 // mode stream was created. 179 // mode stream was created.
178 if (HadNoAudioStreams()) 180 if (HadNoAudioStreams())
179 SetCommunicationAudioModeOn(false); 181 SetCommunicationAudioModeOn(false);
180 } 182 }
181 183
182 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( 184 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
183 const AudioParameters& params) { 185 const AudioParameters& params) {
184 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 186 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
185 return new OpenSLESOutputStream(this, params); 187 return new OpenSLESOutputStream(this, params);
186 } 188 }
187 189
188 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( 190 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
189 const AudioParameters& params, 191 const AudioParameters& params,
190 const std::string& device_id, 192 const std::string& device_id,
191 const std::string& input_device_id) { 193 const std::string& input_device_id) {
192 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; 194 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
193 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 195 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
194 return new OpenSLESOutputStream(this, params); 196 return new OpenSLESOutputStream(this, params);
195 } 197 }
196 198
197 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream( 199 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream(
198 const AudioParameters& params, const std::string& device_id) { 200 const AudioParameters& params, const std::string& device_id) {
199 // TODO(henrika): add support for device selection if/when any client 201 // TODO(henrika): add support for device selection if/when any client
200 // needs it. 202 // needs it.
201 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; 203 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
202 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 204 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
205 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
206 CreateAndInitOnAudioThread();
203 return new OpenSLESInputStream(this, params); 207 return new OpenSLESInputStream(this, params);
204 } 208 }
205 209
206 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( 210 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
207 const AudioParameters& params, const std::string& device_id) { 211 const AudioParameters& params, const std::string& device_id) {
208 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 212 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
209 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; 213 DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!";
214 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
215 CreateAndInitOnAudioThread();
216
210 // Use the device ID to select the correct input device. 217 // Use the device ID to select the correct input device.
211 // Note that the input device is always associated with a certain output 218 // Note that the input device is always associated with a certain output
212 // device, i.e., this selection does also switch the output device. 219 // device, i.e., this selection does also switch the output device.
213 // All input and output streams will be affected by the device selection. 220 // All input and output streams will be affected by the device selection.
214 if (!SetAudioDevice(device_id)) { 221 if (!SetAudioDevice(device_id)) {
215 LOG(ERROR) << "Unable to select audio device!"; 222 LOG(ERROR) << "Unable to select audio device!";
216 return NULL; 223 return NULL;
217 } 224 }
218 225
219 if (params.effects() != AudioParameters::NO_EFFECTS) { 226 if (params.effects() != AudioParameters::NO_EFFECTS) {
220 // Platform effects can only be enabled through the AudioRecord path. 227 // Platform effects can only be enabled through the AudioRecord path.
221 // An effect should only have been requested here if recommended by 228 // An effect should only have been requested here if recommended by
222 // AudioManagerAndroid.shouldUse<Effect>. 229 // AudioManagerAndroid.shouldUse<Effect>.
223 // 230 //
224 // Creating this class requires Jelly Bean, which is already guaranteed by 231 // Creating this class requires Jelly Bean, which is already guaranteed by
225 // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use 232 // shouldUse<Effect>. Only DCHECK on that condition to allow tests to use
226 // the effect settings as a way to select the input path. 233 // the effect settings as a way to select the input path.
227 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16); 234 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 16);
228 DVLOG(1) << "Creating AudioRecordInputStream"; 235 DVLOG(1) << "Creating AudioRecordInputStream";
229 return new AudioRecordInputStream(this, params); 236 return new AudioRecordInputStream(this, params);
230 } 237 }
231 DVLOG(1) << "Creating OpenSLESInputStream"; 238 DVLOG(1) << "Creating OpenSLESInputStream";
232 return new OpenSLESInputStream(this, params); 239 return new OpenSLESInputStream(this, params);
233 } 240 }
234 241
242 void AudioManagerAndroid::WillDestroyCurrentMessageLoop() {
243 CloseOnAudioThread();
244 }
245
235 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, 246 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate,
236 int channels) { 247 int channels) {
237 if (IsAudioLowLatencySupported()) { 248 if (IsAudioLowLatencySupported()) {
238 return GetAudioLowLatencyOutputFrameSize(); 249 return GetAudioLowLatencyOutputFrameSize();
239 } else { 250 } else {
240 return std::max(kDefaultOutputBufferSize, 251 return std::max(kDefaultOutputBufferSize,
241 Java_AudioManagerAndroid_getMinOutputFrameSize( 252 Java_AudioManagerAndroid_getMinOutputFrameSize(
242 base::android::AttachCurrentThread(), 253 base::android::AttachCurrentThread(),
243 sample_rate, channels)); 254 sample_rate, channels));
244 } 255 }
(...skipping 21 matching lines...) Expand all
266 277
267 int user_buffer_size = GetUserBufferSize(); 278 int user_buffer_size = GetUserBufferSize();
268 if (user_buffer_size) 279 if (user_buffer_size)
269 buffer_size = user_buffer_size; 280 buffer_size = user_buffer_size;
270 281
271 return AudioParameters( 282 return AudioParameters(
272 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, 283 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
273 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); 284 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
274 } 285 }
275 286
276 bool AudioManagerAndroid::HadNoAudioStreams() { 287 bool AudioManagerAndroid::HadNoAudioStreams() {
tommi (sloooow) - chröme 2014/02/04 14:30:12 This should be called HasNoAudioStreams. "Had" is
henrika (OOO until Aug 14) 2014/02/05 09:45:57 Will fix, nop. Just FYI, it was changed based on c
277 return output_stream_count() == 0 && input_stream_count() == 0; 288 return output_stream_count() == 0 && input_stream_count() == 0;
278 } 289 }
279 290
280 // static 291 // static
281 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { 292 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) {
282 return RegisterNativesImpl(env); 293 return RegisterNativesImpl(env);
283 } 294 }
284 295
296 void AudioManagerAndroid::CreateAndInitOnAudioThread() {
297 scoped_refptr<base::SingleThreadTaskRunner> task_runner(GetTaskRunner());
298 if (task_runner->BelongsToCurrentThread()) {
299 DoCreateAndInitOnAudioThread(NULL);
300 } else {
301 base::WaitableEvent event(false, false);
302 task_runner->PostTask(
303 FROM_HERE,
304 base::Bind(
305 &AudioManagerAndroid::DoCreateAndInitOnAudioThread,
306 base::Unretained(this),
307 &event));
308 event.Wait();
309 }
310 }
311
312 void AudioManagerAndroid::DoCreateAndInitOnAudioThread(
313 base::WaitableEvent* event) {
314 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
315 if (!j_audio_manager_.is_null())
316 return;
317
318 JNIEnv* env = base::android::AttachCurrentThread();
319 CHECK(env);
320
321 // Create the Android audio manager on the audio thread.
322 j_audio_manager_.Reset(
323 Java_AudioManagerAndroid_createAudioManagerAndroid(
324 env,
325 base::android::GetApplicationContext(),
326 reinterpret_cast<intptr_t>(this)));
327
328 // Prepare the list of audio devices and register receivers for device
329 // notifications.
330 Init();
331
332 // Ensure that we are notified when the audio thread dies.
333 base::MessageLoop::current()->AddDestructionObserver(this);
334
335 if (event)
336 event->Signal();
337 }
338
285 void AudioManagerAndroid::Init() { 339 void AudioManagerAndroid::Init() {
286 Java_AudioManagerAndroid_init( 340 Java_AudioManagerAndroid_init(
287 base::android::AttachCurrentThread(), 341 base::android::AttachCurrentThread(),
288 j_audio_manager_.obj()); 342 j_audio_manager_.obj());
289 } 343 }
290 344
291 void AudioManagerAndroid::Close() { 345 void AudioManagerAndroid::Close() {
292 Java_AudioManagerAndroid_close( 346 Java_AudioManagerAndroid_close(
293 base::android::AttachCurrentThread(), 347 base::android::AttachCurrentThread(),
294 j_audio_manager_.obj()); 348 j_audio_manager_.obj());
295 } 349 }
296 350
297 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) { 351 void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) {
298 GetTaskRunner()->PostTask( 352 GetTaskRunner()->PostTask(
299 FROM_HERE, 353 FROM_HERE,
300 base::Bind( 354 base::Bind(
301 &AudioManagerAndroid::DoSetMuteOnAudioThread, 355 &AudioManagerAndroid::DoSetMuteOnAudioThread,
302 base::Unretained(this), 356 base::Unretained(this),
303 muted)); 357 muted));
304 } 358 }
305 359
306 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { 360 void AudioManagerAndroid::GetAudioInputDeviceNamesOnAudioThread(
307 base::AutoLock lock(streams_lock_); 361 base::WaitableEvent* event, AudioDeviceNames* device_names) {
308 for (OutputStreams::iterator it = streams_.begin(); 362 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
309 it != streams_.end(); ++it) { 363
310 (*it)->SetMute(muted); 364 // Always add default device parameters as first element.
365 DCHECK(device_names->empty());
366 AddDefaultDevice(device_names);
367
368 JNIEnv* env = AttachCurrentThread();
369 ScopedJavaLocalRef<jobjectArray> j_device_array =
370 Java_AudioManagerAndroid_getAudioInputDeviceNames(
371 env, j_audio_manager_.obj());
372 jsize len = env->GetArrayLength(j_device_array.obj());
373 AudioDeviceName device;
374 for (jsize i = 0; i < len; ++i) {
375 ScopedJavaLocalRef<jobject> j_device(
376 env, env->GetObjectArrayElement(j_device_array.obj(), i));
377 ScopedJavaLocalRef<jstring> j_device_name =
378 Java_AudioDeviceName_name(env, j_device.obj());
379 ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name);
380 ScopedJavaLocalRef<jstring> j_device_id =
381 Java_AudioDeviceName_id(env, j_device.obj());
382 ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id);
383 device_names->push_back(device);
311 } 384 }
385
386 if (event)
387 event->Signal();
312 } 388 }
313 389
314 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) { 390 void AudioManagerAndroid::CloseOnAudioThread() {
315 Java_AudioManagerAndroid_setCommunicationAudioModeOn( 391 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
316 base::android::AttachCurrentThread(), 392 if (j_audio_manager_.is_null())
317 j_audio_manager_.obj(), on); 393 return;
394 Close();
395 j_audio_manager_.Reset();
318 } 396 }
319 397
320 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) { 398 bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) {
321 JNIEnv* env = AttachCurrentThread(); 399 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
322 400
323 // Send the unique device ID to the Java audio manager and make the 401 // Send the unique device ID to the Java audio manager and make the
324 // device switch. Provide an empty string to the Java audio manager 402 // device switch. Provide an empty string to the Java audio manager
325 // if the default device is selected. 403 // if the default device is selected.
404 JNIEnv* env = AttachCurrentThread();
405 CHECK(env);
326 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString( 406 ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString(
327 env, 407 env,
328 device_id == AudioManagerBase::kDefaultDeviceId ? 408 device_id == AudioManagerBase::kDefaultDeviceId ?
329 std::string() : device_id); 409 std::string() : device_id);
330 return Java_AudioManagerAndroid_setDevice( 410 return Java_AudioManagerAndroid_setDevice(
331 env, j_audio_manager_.obj(), j_device_id.obj()); 411 env, j_audio_manager_.obj(), j_device_id.obj());
332 } 412 }
333 413
414 void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) {
415 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
416 base::AutoLock lock(streams_lock_);
417 for (OutputStreams::iterator it = streams_.begin();
418 it != streams_.end(); ++it) {
419 (*it)->SetMute(muted);
420 }
421 }
422
423 void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) {
424 Java_AudioManagerAndroid_setCommunicationAudioModeOn(
425 base::android::AttachCurrentThread(),
426 j_audio_manager_.obj(), on);
427 }
428
334 int AudioManagerAndroid::GetNativeOutputSampleRate() { 429 int AudioManagerAndroid::GetNativeOutputSampleRate() {
335 return Java_AudioManagerAndroid_getNativeOutputSampleRate( 430 return Java_AudioManagerAndroid_getNativeOutputSampleRate(
336 base::android::AttachCurrentThread(), 431 base::android::AttachCurrentThread(),
337 j_audio_manager_.obj()); 432 j_audio_manager_.obj());
338 } 433 }
339 434
340 bool AudioManagerAndroid::IsAudioLowLatencySupported() { 435 bool AudioManagerAndroid::IsAudioLowLatencySupported() {
341 return Java_AudioManagerAndroid_isAudioLowLatencySupported( 436 return Java_AudioManagerAndroid_isAudioLowLatencySupported(
342 base::android::AttachCurrentThread(), 437 base::android::AttachCurrentThread(),
343 j_audio_manager_.obj()); 438 j_audio_manager_.obj());
344 } 439 }
345 440
346 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { 441 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() {
347 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( 442 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize(
348 base::android::AttachCurrentThread(), 443 base::android::AttachCurrentThread(),
349 j_audio_manager_.obj()); 444 j_audio_manager_.obj());
350 } 445 }
351 446
352 } // namespace media 447 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698