summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/AudioManager.java35
-rw-r--r--media/java/android/media/AudioService.java48
-rw-r--r--media/java/android/media/AudioSystem.java3
-rw-r--r--media/java/android/media/IAudioService.aidl4
4 files changed, 80 insertions, 10 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 16cfa92..6c7c160 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1270,25 +1270,42 @@ public class AudioManager {
}
/**
- * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
- * headset; <var>false</var> disable A2DP audio
+ * Allow or disallow use of Bluetooth A2DP for media.
+ * <p>The default behavior of the system is to use A2DP for media playback whenever an A2DP sink
+ * is connected. Applications can use this method to override this behavior.
+ * Note that the request will not persist after a wired headset or an A2DP sink is connected or
+ * disconnected:
+ * - Connection of an A2DP sink automatically enables use of A2DP.
+ * - Connection of a wired headset automatically disables use of A2DP.
+ * - Disconnection of a wired headset automatically enables use of A2DP if an A2DP sink is
+ * connected.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
+ * @param on set <var>true</var> to allow use of A2DP for media (default).
+ * <var>false</var> to disallow use of A2DP for media.
* @deprecated Do not use.
*/
@Deprecated public void setBluetoothA2dpOn(boolean on){
+ IAudioService service = getService();
+ try {
+ service.setBluetoothA2dpOn(on);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setBluetoothA2dpOn", e);
+ }
}
/**
- * Checks whether A2DP audio routing to the Bluetooth headset is on or off.
+ * Checks whether use of A2DP sinks is enabled for media.
*
- * @return true if A2DP audio is being routed to/from Bluetooth headset;
- * false if otherwise
+ * @return true if use of A2DP is enabled for media, false otherwise.
*/
public boolean isBluetoothA2dpOn() {
- if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"")
- == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
+ IAudioService service = getService();
+ try {
+ return service.isBluetoothA2dpOn();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in isBluetoothA2dpOn", e);
return false;
- } else {
- return true;
}
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index da01c44..5e338ab 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -392,6 +392,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
+ // Request to override default use of A2DP for media.
+ private boolean mBluetoothA2dpEnabled;
+ private final Object mBluetoothA2dpEnabledLock = new Object();
+
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -481,6 +485,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mMasterVolumeRamp = context.getResources().getIntArray(
com.android.internal.R.array.config_masterVolumeRamp);
+
}
private void createAudioSystemThread() {
@@ -1651,6 +1656,21 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
}
+ /** @see AudioManager#setBluetoothA2dpOn() */
+ public void setBluetoothA2dpOn(boolean on) {
+ if (!checkAudioSettingsPermission("setBluetoothA2dpOn()")) {
+ return;
+ }
+ setBluetoothA2dpOnInt(on);
+ }
+
+ /** @see AudioManager#isBluetoothA2dpOn() */
+ public boolean isBluetoothA2dpOn() {
+ synchronized (mBluetoothA2dpEnabledLock) {
+ return mBluetoothA2dpEnabled;
+ }
+ }
+
/** @see AudioManager#startBluetoothSco() */
public void startBluetoothSco(IBinder cb){
if (!checkAudioSettingsPermission("startBluetoothSco()") ||
@@ -1673,6 +1693,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
}
+
private class ScoClient implements IBinder.DeathRecipient {
private IBinder mCb; // To be notified of client's death
private int mCreatorPid;
@@ -2894,6 +2915,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
setOrientationForAudioSystem();
}
+ synchronized (mBluetoothA2dpEnabledLock) {
+ AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+ mBluetoothA2dpEnabled ?
+ AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
+ }
// indicate the end of reconfiguration phase to audio HAL
AudioSystem.setParameters("restarting=false");
break;
@@ -2976,6 +3002,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// must be called synchronized on mConnectedDevices
private void makeA2dpDeviceAvailable(String address) {
+ // enable A2DP before notifying A2DP connection to avoid unecessary processing in
+ // audio policy manager
+ setBluetoothA2dpOnInt(true);
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE,
address);
@@ -3177,7 +3206,15 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
} else {
device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
}
+ // enable A2DP before notifying headset disconnection to avoid glitches
+ if (state == 0) {
+ setBluetoothA2dpOnInt(true);
+ }
handleDeviceConnection((state == 1), device, "");
+ // disable A2DP after notifying headset connection to avoid glitches
+ if (state != 0) {
+ setBluetoothA2dpOnInt(false);
+ }
} else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) {
state = intent.getIntExtra("state", 0);
Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state);
@@ -4655,6 +4692,17 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}
+ // Handles request to override default use of A2DP for media.
+ public void setBluetoothA2dpOnInt(boolean on) {
+ synchronized (mBluetoothA2dpEnabledLock) {
+ mBluetoothA2dpEnabled = on;
+ sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
+ AudioSystem.FOR_MEDIA,
+ mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
+ null, 0);
+ }
+ }
+
@Override
public void setRingtonePlayer(IRingtonePlayer player) {
mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 55071ec..1ca0df4 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -318,7 +318,8 @@ public class AudioSystem
public static final int FORCE_BT_DESK_DOCK = 7;
public static final int FORCE_ANALOG_DOCK = 8;
public static final int FORCE_DIGITAL_DOCK = 9;
- private static final int NUM_FORCE_CONFIG = 10;
+ public static final int FORCE_NO_BT_A2DP = 10;
+ private static final int NUM_FORCE_CONFIG = 11;
public static final int FORCE_DEFAULT = FORCE_NONE;
// usage for setForceUse, must match AudioSystem::force_use
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 6753ad3..7fbe28c 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -96,6 +96,10 @@ interface IAudioService {
boolean isBluetoothScoOn();
+ oneway void setBluetoothA2dpOn(boolean on);
+
+ boolean isBluetoothA2dpOn();
+
int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, IAudioFocusDispatcher l,
String clientId, String callingPackageName);