Index: media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java |
diff --git a/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java b/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java |
index db674f52d3b9f2a0a43978447f7078cdb5ef1671..1a9cb0a383687af8f62e67fa8864f05a6917e742 100644 |
--- a/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java |
+++ b/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java |
@@ -19,8 +19,8 @@ import android.os.Build; |
import android.os.Process; |
import android.util.Log; |
-import java.util.Arrays; |
import java.util.ArrayList; |
+import java.util.Arrays; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Set; |
@@ -114,6 +114,10 @@ class AudioManagerAndroid { |
private Integer mAudioDeviceState = STATE_NO_DEVICE_SELECTED; |
+ // Lock to protect |mAudioDevices| which can be accessed from the main |
+ // thread and the audio manager thread. |
+ private final Object mLock = new Object(); |
+ |
// Contains a list of currently available audio devices. |
private boolean[] mAudioDevices = new boolean[DEVICE_COUNT]; |
@@ -141,8 +145,10 @@ class AudioManagerAndroid { |
if (mIsInitialized) |
return; |
- for (int i = 0; i < DEVICE_COUNT; ++i) { |
- mAudioDevices[i] = false; |
+ synchronized (mLock) { |
+ for (int i = 0; i < DEVICE_COUNT; ++i) { |
+ mAudioDevices[i] = false; |
+ } |
} |
// Store microphone mute state and speakerphone state so it can |
@@ -157,10 +163,12 @@ class AudioManagerAndroid { |
mAudioDeviceState = STATE_SPEAKERPHONE_ON; |
// Initialize audio device list with things we know is always available. |
- if (hasEarpiece()) { |
- mAudioDevices[DEVICE_EARPIECE] = true; |
+ synchronized (mLock) { |
+ if (hasEarpiece()) { |
+ mAudioDevices[DEVICE_EARPIECE] = true; |
+ } |
+ mAudioDevices[DEVICE_SPEAKERPHONE] = true; |
} |
- mAudioDevices[DEVICE_SPEAKERPHONE] = true; |
// Register receiver for broadcasted intents related to adding/ |
// removing a wired headset (Intent.ACTION_HEADSET_PLUG). |
@@ -213,16 +221,20 @@ class AudioManagerAndroid { |
*/ |
@CalledByNative |
public void setDevice(String deviceId) { |
+ boolean devices[] = null; |
+ synchronized (mLock) { |
+ devices = mAudioDevices.clone(); |
+ } |
if (deviceId.isEmpty()) { |
logd("setDevice: default"); |
// Use a special selection scheme if the default device is selected. |
// The "most unique" device will be selected; Bluetooth first, then |
// wired headset and last the speaker phone. |
- if (mAudioDevices[DEVICE_BLUETOOTH_HEADSET]) { |
+ if (devices[DEVICE_BLUETOOTH_HEADSET]) { |
// TODO(henrika): possibly need improvements here if we are |
// in a STATE_BLUETOOTH_TURNING_OFF state. |
setAudioDevice(DEVICE_BLUETOOTH_HEADSET); |
- } else if (mAudioDevices[DEVICE_WIRED_HEADSET]) { |
+ } else if (devices[DEVICE_WIRED_HEADSET]) { |
setAudioDevice(DEVICE_WIRED_HEADSET); |
} else { |
setAudioDevice(DEVICE_SPEAKERPHONE); |
@@ -248,18 +260,20 @@ class AudioManagerAndroid { |
*/ |
@CalledByNative |
public AudioDeviceName[] getAudioInputDeviceNames() { |
- List<String> devices = new ArrayList<String>(); |
- AudioDeviceName[] array = new AudioDeviceName[getNumOfAudioDevices()]; |
- int i = 0; |
- for (int id = 0; id < DEVICE_COUNT; ++id ) { |
- if (mAudioDevices[id]) { |
- array[i] = new AudioDeviceName(id, DEVICE_NAMES[id]); |
- devices.add(DEVICE_NAMES[id]); |
- i++; |
+ synchronized (mLock) { |
+ List<String> devices = new ArrayList<String>(); |
+ AudioDeviceName[] array = new AudioDeviceName[getNumOfAudioDevicesWithLock()]; |
+ int i = 0; |
+ for (int id = 0; id < DEVICE_COUNT; ++id ) { |
+ if (mAudioDevices[id]) { |
+ array[i] = new AudioDeviceName(id, DEVICE_NAMES[id]); |
+ devices.add(DEVICE_NAMES[id]); |
+ i++; |
+ } |
} |
+ logd("getAudioInputDeviceNames: " + devices); |
+ return array; |
} |
- logd("getAudioInputDeviceNames: " + devices); |
- return array; |
} |
@CalledByNative |
@@ -363,8 +377,7 @@ class AudioManagerAndroid { |
* 'state' value where 0 means unplugged, and 1 means plugged. |
*/ |
private void registerForWiredHeadsetIntentBroadcast() { |
- IntentFilter filter = new IntentFilter(); |
- filter.addAction(Intent.ACTION_HEADSET_PLUG); |
+ IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); |
/** |
* Receiver which handles changes in wired headset availablilty. |
@@ -378,22 +391,25 @@ class AudioManagerAndroid { |
@Override |
public void onReceive(Context context, Intent intent) { |
String action = intent.getAction(); |
- if (!action.equals(Intent.ACTION_HEADSET_PLUG)) |
+ if (!action.equals(Intent.ACTION_HEADSET_PLUG)) { |
return; |
+ } |
int state = intent.getIntExtra("state", STATE_UNPLUGGED); |
int microphone = intent.getIntExtra("microphone", HAS_NO_MIC); |
String name = intent.getStringExtra("name"); |
logd("==> onReceive: s=" + state |
+ ", m=" + microphone |
+ ", n=" + name |
- + ", s=" + isInitialStickyBroadcast()); |
+ + ", sb=" + isInitialStickyBroadcast()); |
switch (state) { |
case STATE_UNPLUGGED: |
- // Wired headset and earpiece are mutually exclusive. |
- mAudioDevices[DEVICE_WIRED_HEADSET] = false; |
- if (hasEarpiece()) { |
- mAudioDevices[DEVICE_EARPIECE] = true; |
+ synchronized (mLock) { |
+ // Wired headset and earpiece are mutually exclusive. |
+ mAudioDevices[DEVICE_WIRED_HEADSET] = false; |
+ if (hasEarpiece()) { |
+ mAudioDevices[DEVICE_EARPIECE] = true; |
+ } |
} |
// If wired headset was used before it was unplugged, |
// switch to speaker phone. If it was not in use; just |
@@ -405,10 +421,12 @@ class AudioManagerAndroid { |
} |
break; |
case STATE_PLUGGED: |
- // Wired headset and earpiece are mutually exclusive. |
- mAudioDevices[DEVICE_WIRED_HEADSET] = true; |
- mAudioDevices[DEVICE_EARPIECE] = false; |
- setAudioDevice(DEVICE_WIRED_HEADSET); |
+ synchronized (mLock) { |
+ // Wired headset and earpiece are mutually exclusive. |
+ mAudioDevices[DEVICE_WIRED_HEADSET] = true; |
+ mAudioDevices[DEVICE_EARPIECE] = false; |
+ setAudioDevice(DEVICE_WIRED_HEADSET); |
+ } |
break; |
default: |
loge("Invalid state!"); |
@@ -472,7 +490,9 @@ class AudioManagerAndroid { |
android.bluetooth.BluetoothProfile.STATE_CONNECTED == |
btAdapter.getProfileConnectionState( |
android.bluetooth.BluetoothProfile.HEADSET)) { |
- mAudioDevices[DEVICE_BLUETOOTH_HEADSET] = true; |
+ synchronized (mLock) { |
+ mAudioDevices[DEVICE_BLUETOOTH_HEADSET] = true; |
+ } |
// TODO(henrika): ensure that we set the active audio |
// device to Bluetooth (not trivial). |
setAudioDevice(DEVICE_BLUETOOTH_HEADSET); |
@@ -513,7 +533,7 @@ class AudioManagerAndroid { |
reportUpdate(); |
} |
- private int getNumOfAudioDevices() { |
+ private int getNumOfAudioDevicesWithLock() { |
int count = 0; |
for (int i = 0; i < DEVICE_COUNT; ++i) { |
if (mAudioDevices[i]) |
@@ -524,18 +544,20 @@ class AudioManagerAndroid { |
/** |
* For now, just log the state change but the idea is that we should |
- * notifies a registered state change listener (if any) that there has |
+ * notify a registered state change listener (if any) that there has |
* been a change in the state. |
* TODO(henrika): add support for state change listener. |
*/ |
private void reportUpdate() { |
- List<String> devices = new ArrayList<String>(); |
- for (int i = 0; i < DEVICE_COUNT; ++i) { |
- if (mAudioDevices[i]) |
- devices.add(DEVICE_NAMES[i]); |
+ synchronized (mLock) { |
+ List<String> devices = new ArrayList<String>(); |
+ for (int i = 0; i < DEVICE_COUNT; ++i) { |
+ if (mAudioDevices[i]) |
+ devices.add(DEVICE_NAMES[i]); |
+ } |
+ logd("reportUpdate: state=" + mAudioDeviceState |
+ + ", devices=" + devices); |
} |
- logd("reportUpdate: state=" + mAudioDeviceState |
- + ", devices=" + devices); |
} |
private void logDeviceInfo() { |