diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index a1bea0594b9b8..393e43008fd0f 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -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 getAvailableCommunicationDevices() { ArrayList 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) { diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 0c7f11f988093..b70e11ddcd91d 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -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")