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

Unified Diff: media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java

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: Restored DCHECKs and disabled unit test in content_unittessts instead 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 side-by-side diff with in-line comments
Download patch
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 5fbadca16f81314696c9e504c2430b159c19e654..35f72c1a5242fa98b6eccecf39563c5026af8a8f 100644
--- a/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java
+++ b/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java
@@ -40,6 +40,36 @@ class AudioManagerAndroid {
// NOTE: always check in as false.
private static final boolean DEBUG = false;
+ /**
+ * NonThreadSafe is a helper class used to help verify that methods of a
+ * class are called from the same thread.
+ * Inspired by class in package com.google.android.apps.chrome.utilities.
+ * Is only utilized when DEBUG is set to true.
+ */
+ private static class NonThreadSafe {
+ private final Long mThreadId;
+
+ public NonThreadSafe() {
+ if (DEBUG) {
+ mThreadId = Thread.currentThread().getId();
+ } else {
+ // Avoids "Unread field" issue reported by findbugs.
+ mThreadId = 0L;
+ }
+ }
+
+ /**
+ * Checks if the method is called on the valid thread.
+ * Assigns the current thread if no thread was assigned.
+ */
+ public boolean calledOnValidThread() {
+ if (DEBUG) {
+ return mThreadId.equals(Thread.currentThread().getId());
+ }
+ return true;
+ }
+ }
+
private static boolean runningOnJellyBeanOrHigher() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
}
@@ -135,6 +165,11 @@ class AudioManagerAndroid {
// call to setDevice().
private int mRequestedAudioDevice = DEVICE_INVALID;
+ // This class should be created, initialized and closed on the audio thread
+ // in the audio manager. We use |mNonThreadSafe| to ensure that this is
+ // the case. Only active when |DEBUG| is set to true.
+ private final NonThreadSafe mNonThreadSafe = new NonThreadSafe();
+
// Lock to protect |mAudioDevices| and |mRequestedAudioDevice| which can
// be accessed from the main thread and the audio manager thread.
private final Object mLock = new Object();
@@ -180,18 +215,14 @@ class AudioManagerAndroid {
*/
@CalledByNative
private void init() {
+ checkIfCalledOnValidThread();
if (DEBUG) logd("init");
if (mIsInitialized)
return;
- for (int i = 0; i < DEVICE_COUNT; ++i) {
- mAudioDevices[i] = false;
- }
-
// Initialize audio device list with things we know is always available.
- if (hasEarpiece()) {
- mAudioDevices[DEVICE_EARPIECE] = true;
- }
+ mAudioDevices[DEVICE_EARPIECE] = hasEarpiece();
+ mAudioDevices[DEVICE_WIRED_HEADSET] = hasWiredHeadset();
mAudioDevices[DEVICE_SPEAKERPHONE] = true;
// Register receivers for broadcast intents related to Bluetooth device
@@ -218,6 +249,7 @@ class AudioManagerAndroid {
}
mIsInitialized = true;
+
if (DEBUG) reportUpdate();
}
@@ -227,6 +259,7 @@ class AudioManagerAndroid {
*/
@CalledByNative
private void close() {
+ checkIfCalledOnValidThread();
if (DEBUG) logd("close");
if (!mIsInitialized)
return;
@@ -354,6 +387,7 @@ class AudioManagerAndroid {
*/
@CalledByNative
private AudioDeviceName[] getAudioInputDeviceNames() {
+ if (DEBUG) logd("getAudioInputDeviceNames");
if (!mIsInitialized)
return null;
boolean devices[] = null;
@@ -442,7 +476,7 @@ class AudioManagerAndroid {
}
@CalledByNative
- public static boolean shouldUseAcousticEchoCanceler() {
+ private static boolean shouldUseAcousticEchoCanceler() {
// AcousticEchoCanceler was added in API level 16 (Jelly Bean).
if (!runningOnJellyBeanOrHigher()) {
return false;
@@ -450,14 +484,14 @@ class AudioManagerAndroid {
// Next is a list of device models which have been vetted for good
// quality platform echo cancellation.
- if (!Build.MODEL.equals("SM-T310R") && // Galaxy Tab 3 7.0
- !Build.MODEL.equals("GT-I9300") && // Galaxy S3
+ if (!Build.MODEL.equals("GT-I9300") && // Galaxy S3
!Build.MODEL.equals("GT-I9500") && // Galaxy S4
!Build.MODEL.equals("GT-N7105") && // Galaxy Note 2
- !Build.MODEL.equals("SM-N9005") && // Galaxy Note 3
!Build.MODEL.equals("Nexus 4") &&
!Build.MODEL.equals("Nexus 5") &&
- !Build.MODEL.equals("Nexus 7")) {
+ !Build.MODEL.equals("Nexus 7") &&
+ !Build.MODEL.equals("SM-N9005") && // Galaxy Note 3
+ !Build.MODEL.equals("SM-T310R")) { // Galaxy Tab 3 7.0
return false;
}
@@ -467,6 +501,16 @@ class AudioManagerAndroid {
}
/**
+ * Helper method for debugging purposes. Logs message if method is not
+ * called on same thread as this object was created on.
+ */
+ private void checkIfCalledOnValidThread() {
+ if (DEBUG && !mNonThreadSafe.calledOnValidThread()) {
+ Log.wtf(TAG, "Method is not called on valid thread!");
+ }
+ }
+
+ /**
* Register for BT intents if we have the BLUETOOTH permission.
* Also extends the list of available devices with a BT device if one exists.
*/
@@ -483,9 +527,7 @@ class AudioManagerAndroid {
if (!mHasBluetoothPermission) {
return;
}
- if (hasBluetoothHeadset()) {
- mAudioDevices[DEVICE_BLUETOOTH_HEADSET] = true;
- }
+ mAudioDevices[DEVICE_BLUETOOTH_HEADSET] = hasBluetoothHeadset();
// Register receivers for broadcast intents related to changes in
// Bluetooth headset availability and usage of the SCO channel.
@@ -525,12 +567,24 @@ class AudioManagerAndroid {
return mAudioManager.isMicrophoneMute();
}
- /** Gets the current earpice state. */
+ /** Gets the current earpiece state. */
private boolean hasEarpiece() {
return mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY);
}
+ /**
+ * Checks whether a wired headset is connected or not.
+ * This is not a valid indication that audio playback is actually over
+ * the wired headset as audio routing depends on other conditions. We
+ * only use it as an early indicator (during initialization) of an attached
+ * wired headset.
+ */
+ @Deprecated
+ private boolean hasWiredHeadset() {
+ return mAudioManager.isWiredHeadsetOn();
+ }
+
/** Checks if the process has BLUETOOTH permission or not. */
private boolean hasBluetoothPermission() {
boolean hasBluetooth = mContext.checkPermission(
« media/audio/audio_input_unittest.cc ('K') | « media/audio/audio_manager_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698