AudioDeviceBroker: clean communication route clients upon device disconnection

When a device is disconnected and is a valid communication device,
go over the communication route clients stack and cancel all route
requests to this device.

Bug: 286545833
Test: atest AudioCommunicationDeviceTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df5f3fb6a5309b8bc6892e49490bc2e887b24a14)
Merged-In: Ie6b8514fe61d3efce6c65af5bc8e5fa2562db4ca
Change-Id: Ie6b8514fe61d3efce6c65af5bc8e5fa2562db4ca
This commit is contained in:
Eric Laurent
2023-06-09 10:57:47 +02:00
committed by Cherrypicker Worker
parent 43e951b21d
commit 9a703c8092
2 changed files with 72 additions and 13 deletions

View File

@@ -375,7 +375,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
int scoAudioMode, boolean isPrivileged, String eventSource) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
Log.v(TAG, "setCommunicationRouteForClient: device: " + device
+ ", eventSource: " + eventSource);
}
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
"setCommunicationRouteForClient for uid: " + uid
@@ -497,14 +498,48 @@ import java.util.concurrent.atomic.AtomicBoolean;
};
/*package */ static boolean isValidCommunicationDevice(AudioDeviceInfo device) {
return isValidCommunicationDeviceType(device.getType());
}
private static boolean isValidCommunicationDeviceType(int deviceType) {
for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
if (device.getType() == type) {
if (deviceType == type) {
return true;
}
}
return false;
}
/*package */
void postCheckCommunicationDeviceRemoval(@NonNull AudioDeviceAttributes device) {
if (!isValidCommunicationDeviceType(
AudioDeviceInfo.convertInternalDeviceToDeviceType(device.getInternalType()))) {
return;
}
sendLMsgNoDelay(MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL, SENDMSG_QUEUE, device);
}
@GuardedBy("mDeviceStateLock")
void onCheckCommunicationDeviceRemoval(@NonNull AudioDeviceAttributes device) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "onCheckCommunicationDeviceRemoval device: " + device.toString());
}
for (CommunicationRouteClient crc : mCommunicationRouteClients) {
if (device.equals(crc.getDevice())) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "onCheckCommunicationDeviceRemoval removing client: "
+ crc.toString());
}
// Cancelling the route for this client will remove it from the stack and update
// the communication route.
CommunicationDeviceInfo deviceInfo = new CommunicationDeviceInfo(
crc.getBinder(), crc.getUid(), device, false,
BtHelper.SCO_MODE_UNDEFINED, "onCheckCommunicationDeviceRemoval",
false, crc.isPrivileged());
postSetCommunicationDeviceForClient(deviceInfo);
}
}
}
/* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() {
ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>();
AudioDeviceInfo[] allDevices =
@@ -1449,7 +1484,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
/*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes,
/*package*/ boolean handleDeviceConnection(@NonNull AudioDeviceAttributes attributes,
boolean connect, @Nullable BluetoothDevice btDevice) {
synchronized (mDeviceStateLock) {
return mDeviceInventory.handleDeviceConnection(
@@ -1858,6 +1893,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
} break;
case MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL: {
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
onCheckCommunicationDeviceRemoval((AudioDeviceAttributes) msg.obj);
}
}
} break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -1934,6 +1978,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49;
private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
private static final int MSG_L_CHECK_COMMUNICATION_DEVICE_REMOVAL = 53;
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
@@ -2308,6 +2353,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
dispatchCommunicationDevice();
}
@GuardedBy("mDeviceStateLock")
private CommunicationRouteClient removeCommunicationRouteClient(
IBinder cb, boolean unregister) {
for (CommunicationRouteClient cl : mCommunicationRouteClients) {

View File

@@ -1245,8 +1245,9 @@ public class AudioDeviceInventory {
* @param btDevice the corresponding Bluetooth device when relevant.
* @return false if an error was reported by AudioSystem
*/
/*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect,
boolean isForTesting, @Nullable BluetoothDevice btDevice) {
/*package*/ boolean handleDeviceConnection(@NonNull AudioDeviceAttributes attributes,
boolean connect, boolean isForTesting,
@Nullable BluetoothDevice btDevice) {
int device = attributes.getInternalType();
String address = attributes.getAddress();
String deviceName = attributes.getName();
@@ -1297,6 +1298,7 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_STATE_UNAVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
// always remove even if disconnection failed
mConnectedDevices.remove(deviceKey);
mDeviceBroker.postCheckCommunicationDeviceRemoval(attributes);
status = true;
}
if (status) {
@@ -1801,8 +1803,9 @@ public class AudioDeviceInventory {
// device to remove was visible by APM, update APM
mDeviceBroker.clearAvrcpAbsoluteVolumeSupported();
final int res = mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address),
AudioDeviceAttributes ada = new AudioDeviceAttributes(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
final int res = mAudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_UNAVAILABLE, a2dpCodec);
if (res != AudioSystem.AUDIO_STATUS_OK) {
@@ -1816,11 +1819,13 @@ public class AudioDeviceInventory {
"A2DP device addr=" + address + " made unavailable")).printLog(TAG));
}
mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null, true /*fromA2dp*/);
mmi.record();
updateBluetoothPreferredModes_l(null /*connectedDevice*/);
purgeDevicesRoles_l();
mDeviceBroker.postCheckCommunicationDeviceRemoval(ada);
}
@GuardedBy("mDevicesLock")
@@ -1855,12 +1860,14 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeA2dpSrcUnavailable(String address) {
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
AudioDeviceAttributes ada = new AudioDeviceAttributes(
AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
mAudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.remove(
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address));
mDeviceBroker.postCheckCommunicationDeviceRemoval(ada);
}
@GuardedBy("mDevicesLock")
@@ -1893,8 +1900,9 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeHearingAidDeviceUnavailable(String address) {
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
AudioSystem.DEVICE_OUT_HEARING_AID, address),
AudioDeviceAttributes ada = new AudioDeviceAttributes(
AudioSystem.DEVICE_OUT_HEARING_AID, address);
mAudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.remove(
@@ -1906,6 +1914,7 @@ public class AudioDeviceInventory {
.set(MediaMetrics.Property.DEVICE,
AudioSystem.getDeviceName(AudioSystem.DEVICE_OUT_HEARING_AID))
.record();
mDeviceBroker.postCheckCommunicationDeviceRemoval(ada);
}
/**
@@ -2002,9 +2011,10 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeLeAudioDeviceUnavailableNow(String address, int device) {
AudioDeviceAttributes ada = null;
if (device != AudioSystem.DEVICE_NONE) {
final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
device, address),
ada = new AudioDeviceAttributes(device, address);
final int res = AudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
@@ -2024,6 +2034,9 @@ public class AudioDeviceInventory {
setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
updateBluetoothPreferredModes_l(null /*connectedDevice*/);
purgeDevicesRoles_l();
if (ada != null) {
mDeviceBroker.postCheckCommunicationDeviceRemoval(ada);
}
}
@GuardedBy("mDevicesLock")