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

Unified 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: tommi@ Created 6 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: media/audio/android/audio_manager_android.cc
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc
index 33e9e085688de87c37eebfbdbfdeddfb9949f2db..1bfcbac2eb816c2ed08216a73b3beec71c528363 100644
--- a/media/audio/android/audio_manager_android.cc
+++ b/media/audio/android/audio_manager_android.cc
@@ -9,6 +9,7 @@
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "jni/AudioManagerAndroid_jni.h"
#include "media/audio/android/audio_record_input.h"
@@ -45,9 +46,9 @@ AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
}
AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory)
- : AudioManagerBase(audio_log_factory) {
+ : AudioManagerBase(audio_log_factory),
+ initialized_on_audio_thread_(false) {
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
-
j_audio_manager_.Reset(
Java_AudioManagerAndroid_createAudioManagerAndroid(
base::android::AttachCurrentThread(),
@@ -59,6 +60,8 @@ AudioManagerAndroid::AudioManagerAndroid(AudioLogFactory* audio_log_factory)
AudioManagerAndroid::~AudioManagerAndroid() {
Close();
Shutdown();
+ // Verify that WillDestroyCurrentMessageLoop() has been called.
+ DCHECK(!initialized_on_audio_thread_);
}
bool AudioManagerAndroid::HasAudioOutputDevices() {
@@ -71,26 +74,22 @@ bool AudioManagerAndroid::HasAudioInputDevices() {
void AudioManagerAndroid::GetAudioInputDeviceNames(
AudioDeviceNames* device_names) {
- // Always add default device parameters as first element.
- DCHECK(device_names->empty());
- AddDefaultDevice(device_names);
-
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobjectArray> j_device_array =
- Java_AudioManagerAndroid_getAudioInputDeviceNames(
- env, j_audio_manager_.obj());
- jsize len = env->GetArrayLength(j_device_array.obj());
- AudioDeviceName device;
- for (jsize i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jobject> j_device(
- env, env->GetObjectArrayElement(j_device_array.obj(), i));
- ScopedJavaLocalRef<jstring> j_device_name =
- Java_AudioDeviceName_name(env, j_device.obj());
- ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name);
- ScopedJavaLocalRef<jstring> j_device_id =
- Java_AudioDeviceName_id(env, j_device.obj());
- ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id);
- device_names->push_back(device);
+ // Get list of available audio devices and use the audio thread to reduce
+ // the number of calling threads to the Java layer. Also, ensure that the
+ // calling thread sees this function call as synchronous.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner(GetTaskRunner());
+ if (task_runner->BelongsToCurrentThread()) {
+ GetAudioInputDeviceNamesOnAudioThread(NULL, device_names);
+ } else {
+ base::WaitableEvent event(false, false);
+ task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AudioManagerAndroid::GetAudioInputDeviceNamesOnAudioThread,
+ base::Unretained(this),
+ &event,
+ device_names));
+ event.Wait();
}
}
@@ -146,6 +145,7 @@ AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
AudioInputStream* AudioManagerAndroid::MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) {
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
bool had_no_streams = HadNoAudioStreams();
AudioInputStream* stream =
AudioManagerBase::MakeAudioInputStream(params, device_id);
@@ -206,6 +206,7 @@ AudioInputStream* AudioManagerAndroid::MakeLinearInputStream(
AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
const AudioParameters& params, const std::string& device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ // DCHECK(GetTaskRunner()->BelongsToCurrentThread());
tommi (sloooow) - chröme 2014/01/30 15:26:04 will you uncomment this before checkin?
henrika (OOO until Aug 14) 2014/01/30 17:20:23 Done.
DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!";
// Use the device ID to select the correct input device.
// Note that the input device is always associated with a certain output
@@ -232,6 +233,13 @@ AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
return new OpenSLESInputStream(this, params);
}
+void AudioManagerAndroid::WillDestroyCurrentMessageLoop() {
+ // This call matches previous calls to InitializeOnAudioThread() and it
+ // ensures that we unregister receivers for events related to changes in
+ // availability of audio devices.
+ CloseOnAudioThread();
+}
+
int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate,
int channels) {
if (IsAudioLowLatencySupported()) {
@@ -303,32 +311,124 @@ void AudioManagerAndroid::SetMute(JNIEnv* env, jobject obj, jboolean muted) {
muted));
}
-void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) {
- base::AutoLock lock(streams_lock_);
- for (OutputStreams::iterator it = streams_.begin();
- it != streams_.end(); ++it) {
- (*it)->SetMute(muted);
+void AudioManagerAndroid::GetAudioInputDeviceNamesOnAudioThread(
+ base::WaitableEvent* event, AudioDeviceNames* device_names) {
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+
+ // Set up the initial list of available audio devices and register for
+ // broadcasted notifications about any changes of availability.
+ // This method is only executed when called for the first time and it can
+ // also be called from SetAudioDeviceOnAudioThread().
+ InitializeOnAudioThread();
+
+ // Always add default device parameters as first element.
+ DCHECK(device_names->empty());
+ AddDefaultDevice(device_names);
+
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobjectArray> j_device_array =
+ Java_AudioManagerAndroid_getAudioInputDeviceNames(
+ env, j_audio_manager_.obj());
+ jsize len = env->GetArrayLength(j_device_array.obj());
+ AudioDeviceName device;
+ for (jsize i = 0; i < len; ++i) {
+ ScopedJavaLocalRef<jobject> j_device(
+ env, env->GetObjectArrayElement(j_device_array.obj(), i));
+ ScopedJavaLocalRef<jstring> j_device_name =
+ Java_AudioDeviceName_name(env, j_device.obj());
+ ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name);
+ ScopedJavaLocalRef<jstring> j_device_id =
+ Java_AudioDeviceName_id(env, j_device.obj());
+ ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id);
+ device_names->push_back(device);
}
+
+ if (event)
+ event->Signal();
}
-void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) {
- Java_AudioManagerAndroid_setCommunicationAudioModeOn(
- base::android::AttachCurrentThread(),
- j_audio_manager_.obj(), on);
+void AudioManagerAndroid::InitializeOnAudioThread() {
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ if (!initialized_on_audio_thread_) {
+ base::MessageLoop::current()->AddDestructionObserver(this);
+ Java_AudioManagerAndroid_initAudioDeviceList(
+ base::android::AttachCurrentThread(),
+ j_audio_manager_.obj());
+ initialized_on_audio_thread_ = true;
+ }
+}
+
+void AudioManagerAndroid::CloseOnAudioThread() {
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ if (!initialized_on_audio_thread_)
+ return;
+ Java_AudioManagerAndroid_closeAudioDeviceList(
+ base::android::AttachCurrentThread(),
+ j_audio_manager_.obj());
+ initialized_on_audio_thread_ = false;
}
bool AudioManagerAndroid::SetAudioDevice(const std::string& device_id) {
- JNIEnv* env = AttachCurrentThread();
+ // Select audio device and use the audio thread to reduce the number of
+ // calling threads to the Java layer. Also, ensure that the calling thread
+ // sees this function call as synchronous.
+ bool result = false;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner(GetTaskRunner());
+ if (task_runner->BelongsToCurrentThread()) {
+ SetAudioDeviceOnAudioThread(NULL, device_id, &result);
+ } else {
+ base::WaitableEvent event(false, false);
+ task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &AudioManagerAndroid::SetAudioDeviceOnAudioThread,
+ base::Unretained(this),
+ &event,
+ device_id,
+ &result));
+ event.Wait();
+ }
+ return result;
+}
+
+void AudioManagerAndroid::SetAudioDeviceOnAudioThread(
+ base::WaitableEvent* event, const std::string& device_id, bool* result) {
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+
+ // Set up the initial list of available audio devices and register for
+ // broadcasted notifications about any changes of availability.
+ // This method is only executed when called for the first time and it can
+ // also be called from GetAudioInputDeviceNamesOnAudioThread().
+ InitializeOnAudioThread();
// Send the unique device ID to the Java audio manager and make the
// device switch. Provide an empty string to the Java audio manager
// if the default device is selected.
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_device_id = ConvertUTF8ToJavaString(
env,
device_id == AudioManagerBase::kDefaultDeviceId ?
std::string() : device_id);
- return Java_AudioManagerAndroid_setDevice(
+ *result = Java_AudioManagerAndroid_setDevice(
env, j_audio_manager_.obj(), j_device_id.obj());
+
+ if (event)
+ event->Signal();
+}
+
+void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) {
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ base::AutoLock lock(streams_lock_);
+ for (OutputStreams::iterator it = streams_.begin();
+ it != streams_.end(); ++it) {
+ (*it)->SetMute(muted);
+ }
+}
+
+void AudioManagerAndroid::SetCommunicationAudioModeOn(bool on) {
+ Java_AudioManagerAndroid_setCommunicationAudioModeOn(
+ base::android::AttachCurrentThread(),
+ j_audio_manager_.obj(), on);
}
int AudioManagerAndroid::GetNativeOutputSampleRate() {

Powered by Google App Engine
This is Rietveld 408576698