Loading services/core/java/com/android/server/audio/AudioDeviceBroker.java +21 −12 Original line number Diff line number Diff line Loading @@ -503,7 +503,7 @@ import java.util.concurrent.atomic.AtomicBoolean; } } private static final class BtDeviceConnectionInfo { /*package*/ static final class BtDeviceConnectionInfo { final @NonNull BluetoothDevice mDevice; final @AudioService.BtProfileConnectionState int mState; final int mProfile; Loading @@ -520,6 +520,14 @@ import java.util.concurrent.atomic.AtomicBoolean; mVolume = vol; } BtDeviceConnectionInfo(@NonNull BtDeviceConnectionInfo info) { mDevice = info.mDevice; mState = info.mState; mProfile = info.mProfile; mSupprNoisy = info.mSupprNoisy; mVolume = info.mVolume; } // redefine equality op so we can match messages intended for this device @Override public boolean equals(Object o) { Loading @@ -541,18 +549,19 @@ import java.util.concurrent.atomic.AtomicBoolean; } } /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, suppressNoisyIntent, a2dpVolume); final String name = TextUtils.emptyIfNull(device.getName()); /** * will block on mDeviceStateLock, which is held during an A2DP (dis) connection * not just a simple message post * @param info struct with the (dis)connection information */ /*package*/ void queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @NonNull BtDeviceConnectionInfo info) { final String name = TextUtils.emptyIfNull(info.mDevice.getName()); new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR + "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent") .set(MediaMetrics.Property.STATE, state == BluetoothProfile.STATE_CONNECTED .set(MediaMetrics.Property.STATE, info.mState == BluetoothProfile.STATE_CONNECTED ? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED) .set(MediaMetrics.Property.INDEX, a2dpVolume) .set(MediaMetrics.Property.INDEX, info.mVolume) .set(MediaMetrics.Property.NAME, name) .record(); Loading @@ -562,10 +571,10 @@ import java.util.concurrent.atomic.AtomicBoolean; // when receiving a request to change the connection state of a device, this last // request is the source of truth, so cancel all previous requests that are already in // the handler removeScheduledA2dpEvents(device); removeScheduledA2dpEvents(info.mDevice); sendLMsgNoDelay( state == BluetoothProfile.STATE_CONNECTED info.mState == BluetoothProfile.STATE_CONNECTED ? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION : MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION, SENDMSG_QUEUE, info); Loading services/core/java/com/android/server/audio/AudioService.java +21 −4 Original line number Diff line number Diff line Loading @@ -310,6 +310,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_UPDATE_A11Y_SERVICE_UIDS = 35; private static final int MSG_UPDATE_AUDIO_MODE = 36; private static final int MSG_RECORDING_CONFIG_CHANGE = 37; private static final int MSG_SET_A2DP_DEV_CONNECTION_STATE = 38; private static final int MSG_A2DP_DEV_CONFIG_CHANGE = 39; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), Loading Loading @@ -6114,7 +6116,7 @@ public class AudioService extends IAudioService.Stub * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() */ public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, @NonNull BluetoothDevice device, @BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { if (device == null) { throw new IllegalArgumentException("Illegal null device"); Loading @@ -6124,8 +6126,13 @@ public class AudioService extends IAudioService.Stub throw new IllegalArgumentException("Illegal BluetoothProfile state for device " + " (dis)connection, got " + state); } mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state, AudioDeviceBroker.BtDeviceConnectionInfo info = new AudioDeviceBroker.BtDeviceConnectionInfo(device, state, profile, suppressNoisyIntent, a2dpVolume); sendMsg(mAudioHandler, MSG_SET_A2DP_DEV_CONNECTION_STATE, SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, /*obj*/ info, 0 /*delay*/); } /** only public for mocking/spying, do not call outside of AudioService */ Loading @@ -6143,7 +6150,8 @@ public class AudioService extends IAudioService.Stub if (device == null) { throw new IllegalArgumentException("Illegal null device"); } mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device); sendMsg(mAudioHandler, MSG_A2DP_DEV_CONFIG_CHANGE, SENDMSG_QUEUE, 0, 0, /*obj*/ device, /*delay*/ 0); } private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET; Loading Loading @@ -7505,6 +7513,15 @@ public class AudioService extends IAudioService.Stub onUpdateAudioMode(msg.arg1, msg.arg2, (String) msg.obj, false /*force*/); } break; case MSG_SET_A2DP_DEV_CONNECTION_STATE: mDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( (AudioDeviceBroker.BtDeviceConnectionInfo) msg.obj); break; case MSG_A2DP_DEV_CONFIG_CHANGE: mDeviceBroker.postBluetoothA2dpDeviceConfigChange((BluetoothDevice) msg.obj); break; } } } Loading services/core/java/com/android/server/audio/BtHelper.java +4 −2 Original line number Diff line number Diff line Loading @@ -454,8 +454,10 @@ public class BtHelper { } final BluetoothDevice btDevice = deviceList.get(0); // the device is guaranteed CONNECTED mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(btDevice, BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, true, -1); mDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(btDevice, BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, true, -1)); } /*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) { Loading services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java +12 −8 Original line number Diff line number Diff line Loading @@ -98,8 +98,9 @@ public class AudioDeviceBrokerTest { Log.i(TAG, "starting testPostA2dpDeviceConnectionChange"); Assert.assertNotNull("invalid null BT device", mFakeBtDevice); mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1)); Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS); verify(mSpyDevInventory, times(1)).setBluetoothA2dpDeviceConnectionState( any(BluetoothDevice.class), Loading Loading @@ -209,20 +210,23 @@ public class AudioDeviceBrokerTest { ((NoOpAudioSystemAdapter) mSpyAudioSystem).configureIsStreamActive(mockMediaPlayback); // first connection: ensure the device is connected as a starting condition for the test mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1)); Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS); // disconnection mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP, false, -1); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP, false, -1)); if (delayAfterDisconnection > 0) { Thread.sleep(delayAfterDisconnection); } // reconnection mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 2); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 2)); Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS); // Verify disconnection has been cancelled and we're seeing two connections attempts, Loading Loading
services/core/java/com/android/server/audio/AudioDeviceBroker.java +21 −12 Original line number Diff line number Diff line Loading @@ -503,7 +503,7 @@ import java.util.concurrent.atomic.AtomicBoolean; } } private static final class BtDeviceConnectionInfo { /*package*/ static final class BtDeviceConnectionInfo { final @NonNull BluetoothDevice mDevice; final @AudioService.BtProfileConnectionState int mState; final int mProfile; Loading @@ -520,6 +520,14 @@ import java.util.concurrent.atomic.AtomicBoolean; mVolume = vol; } BtDeviceConnectionInfo(@NonNull BtDeviceConnectionInfo info) { mDevice = info.mDevice; mState = info.mState; mProfile = info.mProfile; mSupprNoisy = info.mSupprNoisy; mVolume = info.mVolume; } // redefine equality op so we can match messages intended for this device @Override public boolean equals(Object o) { Loading @@ -541,18 +549,19 @@ import java.util.concurrent.atomic.AtomicBoolean; } } /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, suppressNoisyIntent, a2dpVolume); final String name = TextUtils.emptyIfNull(device.getName()); /** * will block on mDeviceStateLock, which is held during an A2DP (dis) connection * not just a simple message post * @param info struct with the (dis)connection information */ /*package*/ void queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @NonNull BtDeviceConnectionInfo info) { final String name = TextUtils.emptyIfNull(info.mDevice.getName()); new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR + "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent") .set(MediaMetrics.Property.STATE, state == BluetoothProfile.STATE_CONNECTED .set(MediaMetrics.Property.STATE, info.mState == BluetoothProfile.STATE_CONNECTED ? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED) .set(MediaMetrics.Property.INDEX, a2dpVolume) .set(MediaMetrics.Property.INDEX, info.mVolume) .set(MediaMetrics.Property.NAME, name) .record(); Loading @@ -562,10 +571,10 @@ import java.util.concurrent.atomic.AtomicBoolean; // when receiving a request to change the connection state of a device, this last // request is the source of truth, so cancel all previous requests that are already in // the handler removeScheduledA2dpEvents(device); removeScheduledA2dpEvents(info.mDevice); sendLMsgNoDelay( state == BluetoothProfile.STATE_CONNECTED info.mState == BluetoothProfile.STATE_CONNECTED ? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION : MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION, SENDMSG_QUEUE, info); Loading
services/core/java/com/android/server/audio/AudioService.java +21 −4 Original line number Diff line number Diff line Loading @@ -310,6 +310,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_UPDATE_A11Y_SERVICE_UIDS = 35; private static final int MSG_UPDATE_AUDIO_MODE = 36; private static final int MSG_RECORDING_CONFIG_CHANGE = 37; private static final int MSG_SET_A2DP_DEV_CONNECTION_STATE = 38; private static final int MSG_A2DP_DEV_CONFIG_CHANGE = 39; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), Loading Loading @@ -6114,7 +6116,7 @@ public class AudioService extends IAudioService.Stub * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() */ public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, @NonNull BluetoothDevice device, @BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { if (device == null) { throw new IllegalArgumentException("Illegal null device"); Loading @@ -6124,8 +6126,13 @@ public class AudioService extends IAudioService.Stub throw new IllegalArgumentException("Illegal BluetoothProfile state for device " + " (dis)connection, got " + state); } mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state, AudioDeviceBroker.BtDeviceConnectionInfo info = new AudioDeviceBroker.BtDeviceConnectionInfo(device, state, profile, suppressNoisyIntent, a2dpVolume); sendMsg(mAudioHandler, MSG_SET_A2DP_DEV_CONNECTION_STATE, SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, /*obj*/ info, 0 /*delay*/); } /** only public for mocking/spying, do not call outside of AudioService */ Loading @@ -6143,7 +6150,8 @@ public class AudioService extends IAudioService.Stub if (device == null) { throw new IllegalArgumentException("Illegal null device"); } mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device); sendMsg(mAudioHandler, MSG_A2DP_DEV_CONFIG_CHANGE, SENDMSG_QUEUE, 0, 0, /*obj*/ device, /*delay*/ 0); } private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET; Loading Loading @@ -7505,6 +7513,15 @@ public class AudioService extends IAudioService.Stub onUpdateAudioMode(msg.arg1, msg.arg2, (String) msg.obj, false /*force*/); } break; case MSG_SET_A2DP_DEV_CONNECTION_STATE: mDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( (AudioDeviceBroker.BtDeviceConnectionInfo) msg.obj); break; case MSG_A2DP_DEV_CONFIG_CHANGE: mDeviceBroker.postBluetoothA2dpDeviceConfigChange((BluetoothDevice) msg.obj); break; } } } Loading
services/core/java/com/android/server/audio/BtHelper.java +4 −2 Original line number Diff line number Diff line Loading @@ -454,8 +454,10 @@ public class BtHelper { } final BluetoothDevice btDevice = deviceList.get(0); // the device is guaranteed CONNECTED mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(btDevice, BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, true, -1); mDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(btDevice, BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, true, -1)); } /*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) { Loading
services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java +12 −8 Original line number Diff line number Diff line Loading @@ -98,8 +98,9 @@ public class AudioDeviceBrokerTest { Log.i(TAG, "starting testPostA2dpDeviceConnectionChange"); Assert.assertNotNull("invalid null BT device", mFakeBtDevice); mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1)); Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS); verify(mSpyDevInventory, times(1)).setBluetoothA2dpDeviceConnectionState( any(BluetoothDevice.class), Loading Loading @@ -209,20 +210,23 @@ public class AudioDeviceBrokerTest { ((NoOpAudioSystemAdapter) mSpyAudioSystem).configureIsStreamActive(mockMediaPlayback); // first connection: ensure the device is connected as a starting condition for the test mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1)); Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS); // disconnection mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP, false, -1); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP, false, -1)); if (delayAfterDisconnection > 0) { Thread.sleep(delayAfterDisconnection); } // reconnection mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 2); mAudioDeviceBroker.queueBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( new AudioDeviceBroker.BtDeviceConnectionInfo(mFakeBtDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 2)); Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS); // Verify disconnection has been cancelled and we're seeing two connections attempts, Loading