summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/AudioManager.java14
-rw-r--r--media/java/android/media/IAudioService.aidl6
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java174
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java10
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java20
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java4
6 files changed, 209 insertions, 19 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b1d2e33df3f7..4759689335e9 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3730,7 +3730,12 @@ public class AudioManager {
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(Manifest.permission.BLUETOOTH_STACK)
public void setA2dpSuspended(boolean enable) {
- AudioSystem.setParameters("A2dpSuspended=" + enable);
+ final IAudioService service = getService();
+ try {
+ service.setA2dpSuspended(enable);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -3743,7 +3748,12 @@ public class AudioManager {
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(Manifest.permission.BLUETOOTH_STACK)
public void setLeAudioSuspended(boolean enable) {
- AudioSystem.setParameters("LeAudioSuspended=" + enable);
+ final IAudioService service = getService();
+ try {
+ service.setLeAudioSuspended(enable);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index fe5afc5a717e..7ce189ba85d5 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -231,6 +231,12 @@ interface IAudioService {
void setBluetoothScoOn(boolean on);
+ @EnforcePermission("BLUETOOTH_STACK")
+ void setA2dpSuspended(boolean on);
+
+ @EnforcePermission("BLUETOOTH_STACK")
+ void setLeAudioSuspended(boolean enable);
+
boolean isBluetoothScoOn();
void setBluetoothA2dpOn(boolean on);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 71401f437232..f4c9d05ee0ef 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -209,6 +209,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void init() {
setupMessaging(mContext);
+ initAudioHalBluetoothState();
initRoutingStrategyIds();
mPreferredCommunicationDevice = null;
updateActiveCommunicationDevice();
@@ -864,21 +865,174 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
- /**
- * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
- */
+ // Lock protecting state variable related to Bluetooth audio state
+ private final Object mBluetoothAudioStateLock = new Object();
+
+ // Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
+ @GuardedBy("mBluetoothAudioStateLock")
private boolean mBluetoothScoOn;
+ // value of BT_SCO parameter currently applied to audio HAL.
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothScoOnApplied;
+
+ // A2DP suspend state requested by AudioManager.setA2dpSuspended() API.
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothA2dpSuspendedExt;
+ // A2DP suspend state requested by AudioDeviceInventory.
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothA2dpSuspendedInt;
+ // value of BT_A2dpSuspendedSCO parameter currently applied to audio HAL.
+
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothA2dpSuspendedApplied;
+
+ // LE Audio suspend state requested by AudioManager.setLeAudioSuspended() API.
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothLeSuspendedExt;
+ // LE Audio suspend state requested by AudioDeviceInventory.
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothLeSuspendedInt;
+ // value of LeAudioSuspended parameter currently applied to audio HAL.
+ @GuardedBy("mBluetoothAudioStateLock")
+ private boolean mBluetoothLeSuspendedApplied;
+
+ private void initAudioHalBluetoothState() {
+ synchronized (mBluetoothAudioStateLock) {
+ mBluetoothScoOnApplied = false;
+ AudioSystem.setParameters("BT_SCO=off");
+ mBluetoothA2dpSuspendedApplied = false;
+ AudioSystem.setParameters("A2dpSuspended=false");
+ mBluetoothLeSuspendedApplied = false;
+ AudioSystem.setParameters("LeAudioSuspended=false");
+ }
+ }
+
+ @GuardedBy("mBluetoothAudioStateLock")
+ private void updateAudioHalBluetoothState() {
+ if (mBluetoothScoOn != mBluetoothScoOnApplied) {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothScoOn: "
+ + mBluetoothScoOn + ", mBluetoothScoOnApplied: " + mBluetoothScoOnApplied);
+ }
+ if (mBluetoothScoOn) {
+ if (!mBluetoothA2dpSuspendedApplied) {
+ AudioSystem.setParameters("A2dpSuspended=true");
+ mBluetoothA2dpSuspendedApplied = true;
+ }
+ if (!mBluetoothLeSuspendedApplied) {
+ AudioSystem.setParameters("LeAudioSuspended=true");
+ mBluetoothLeSuspendedApplied = true;
+ }
+ AudioSystem.setParameters("BT_SCO=on");
+ } else {
+ AudioSystem.setParameters("BT_SCO=off");
+ }
+ mBluetoothScoOnApplied = mBluetoothScoOn;
+ }
+ if (!mBluetoothScoOnApplied) {
+ if ((mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt)
+ != mBluetoothA2dpSuspendedApplied) {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothA2dpSuspendedExt: "
+ + mBluetoothA2dpSuspendedExt
+ + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt
+ + ", mBluetoothA2dpSuspendedApplied: "
+ + mBluetoothA2dpSuspendedApplied);
+ }
+ mBluetoothA2dpSuspendedApplied =
+ mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt;
+ if (mBluetoothA2dpSuspendedApplied) {
+ AudioSystem.setParameters("A2dpSuspended=true");
+ } else {
+ AudioSystem.setParameters("A2dpSuspended=false");
+ }
+ }
+ if ((mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt)
+ != mBluetoothLeSuspendedApplied) {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothLeSuspendedExt: "
+ + mBluetoothLeSuspendedExt
+ + ", mBluetoothLeSuspendedInt: " + mBluetoothLeSuspendedInt
+ + ", mBluetoothLeSuspendedApplied: " + mBluetoothLeSuspendedApplied);
+ }
+ mBluetoothLeSuspendedApplied =
+ mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt;
+ if (mBluetoothLeSuspendedApplied) {
+ AudioSystem.setParameters("LeAudioSuspended=true");
+ } else {
+ AudioSystem.setParameters("LeAudioSuspended=false");
+ }
+ }
+ }
+ }
/*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
}
- synchronized (mDeviceStateLock) {
+ synchronized (mBluetoothAudioStateLock) {
mBluetoothScoOn = on;
+ updateAudioHalBluetoothState();
postUpdateCommunicationRouteClient(eventSource);
}
}
+ /*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) {
+ synchronized (mBluetoothAudioStateLock) {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: "
+ + enable + ", internal: " + internal
+ + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt
+ + ", mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt);
+ }
+ if (internal) {
+ mBluetoothA2dpSuspendedInt = enable;
+ } else {
+ mBluetoothA2dpSuspendedExt = enable;
+ }
+ updateAudioHalBluetoothState();
+ }
+ }
+
+ /*package*/ void clearA2dpSuspended() {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "clearA2dpSuspended");
+ }
+ synchronized (mBluetoothAudioStateLock) {
+ mBluetoothA2dpSuspendedInt = false;
+ mBluetoothA2dpSuspendedExt = false;
+ updateAudioHalBluetoothState();
+ }
+ }
+
+ /*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) {
+ synchronized (mBluetoothAudioStateLock) {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: "
+ + enable + ", internal: " + internal
+ + ", mBluetoothLeSuspendedInt: " + mBluetoothA2dpSuspendedInt
+ + ", mBluetoothLeSuspendedExt: " + mBluetoothA2dpSuspendedExt);
+ }
+ if (internal) {
+ mBluetoothLeSuspendedInt = enable;
+ } else {
+ mBluetoothLeSuspendedExt = enable;
+ }
+ updateAudioHalBluetoothState();
+ }
+ }
+
+ /*package*/ void clearLeAudioSuspended() {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "clearLeAudioSuspended");
+ }
+ synchronized (mBluetoothAudioStateLock) {
+ mBluetoothLeSuspendedInt = false;
+ mBluetoothLeSuspendedExt = false;
+ updateAudioHalBluetoothState();
+ }
+ }
+
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
synchronized (mDeviceStateLock) {
return mDeviceInventory.startWatchingRoutes(observer);
@@ -1985,7 +2139,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
@GuardedBy("mDeviceStateLock")
@Nullable private AudioDeviceAttributes preferredCommunicationDevice() {
- boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
+ boolean btSCoOn = mBtHelper.isBluetoothScoOn();
+ synchronized (mBluetoothAudioStateLock) {
+ btSCoOn = btSCoOn && mBluetoothScoOn;
+ }
+
if (btSCoOn) {
// Use the SCO device known to BtHelper so that it matches exactly
// what has been communicated to audio policy manager. The device
@@ -2020,12 +2178,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
"updateCommunicationRoute, preferredCommunicationDevice: "
+ preferredCommunicationDevice + " eventSource: " + eventSource)));
- if (preferredCommunicationDevice == null
- || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
- AudioSystem.setParameters("BT_SCO=off");
- } else {
- AudioSystem.setParameters("BT_SCO=on");
- }
if (preferredCommunicationDevice == null) {
AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
if (defaultDevice != null) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index b70c3e48b6e6..1d8bef1c6732 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1478,7 +1478,7 @@ public class AudioDeviceInventory {
}
// Reset A2DP suspend state each time a new sink is connected
- mAudioSystem.setParameters("A2dpSuspended=false");
+ mDeviceBroker.clearA2dpSuspended();
// The convention for head tracking sensors associated with A2DP devices is to
// use a UUID derived from the MAC address as follows:
@@ -1751,7 +1751,8 @@ public class AudioDeviceInventory {
private void makeA2dpDeviceUnavailableLater(String address, int delayMs) {
// prevent any activity on the A2DP audio output to avoid unwanted
// reconnection of the sink.
- mAudioSystem.setParameters("A2dpSuspended=true");
+ mDeviceBroker.setA2dpSuspended(
+ true /*enable*/, true /*internal*/, "makeA2dpDeviceUnavailableLater");
// retrieve DeviceInfo before removing device
final String deviceKey =
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
@@ -1898,7 +1899,7 @@ public class AudioDeviceInventory {
"LE Audio device addr=" + address + " now available").printLog(TAG));
}
// Reset LEA suspend state each time a new sink is connected
- mAudioSystem.setParameters("LeAudioSuspended=false");
+ mDeviceBroker.clearLeAudioSuspended();
UUID sensorUuid = UuidUtils.uuidFromAudioDeviceAttributes(ada);
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
@@ -1953,7 +1954,8 @@ public class AudioDeviceInventory {
private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) {
// prevent any activity on the LEA output to avoid unwanted
// reconnection of the sink.
- mAudioSystem.setParameters("LeAudioSuspended=true");
+ mDeviceBroker.setLeAudioSuspended(
+ true /*enable*/, true /*internal*/, "makeLeAudioDeviceUnavailableLater");
// the device will be made unavailable later, so consider it disconnected right away
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
// send the delayed message to make the device unavailable later
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 24eba76ccf66..7ebc68612e4d 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6412,6 +6412,26 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.setBluetoothScoOn(on, eventSource);
}
+ /** @see AudioManager#setA2dpSuspended(boolean) */
+ @android.annotation.EnforcePermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setA2dpSuspended(boolean enable) {
+ super.setA2dpSuspended_enforcePermission();
+ final String eventSource = new StringBuilder("setA2dpSuspended(").append(enable)
+ .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
+ .append(Binder.getCallingPid()).toString();
+ mDeviceBroker.setA2dpSuspended(enable, false /*internal*/, eventSource);
+ }
+
+ /** @see AudioManager#setA2dpSuspended(boolean) */
+ @android.annotation.EnforcePermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setLeAudioSuspended(boolean enable) {
+ super.setLeAudioSuspended_enforcePermission();
+ final String eventSource = new StringBuilder("setLeAudioSuspended(").append(enable)
+ .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
+ .append(Binder.getCallingPid()).toString();
+ mDeviceBroker.setLeAudioSuspended(enable, false /*internal*/, eventSource);
+ }
+
/** @see AudioManager#isBluetoothScoOn()
* Note that it doesn't report internal state, but state seen by apps (which may have
* called setBluetoothScoOn() */
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index bfa6c36e1c57..e46c3cc4a285 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -445,8 +445,8 @@ public class BtHelper {
/*package*/ synchronized void resetBluetoothSco() {
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- AudioSystem.setParameters("A2dpSuspended=false");
- AudioSystem.setParameters("LeAudioSuspended=false");
+ mDeviceBroker.clearA2dpSuspended();
+ mDeviceBroker.clearLeAudioSuspended();
mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco");
}