Resolve multiple BT device switching and active device updates
This CL fixes issues found around device switching between multiple
BT devices (LE) where we reroute back into the same device. We should
exclude the BT address for the device which became inactive so
that it isn't selected in the base routing.
Bug: 372197811
Test: Manual log verification from QA test
Flag: com.android.server.telecom.flags.resolve_active_bt_routing_and_bt_timing_issue
Change-Id: Ie19342494687ec6b7cd80d598cc242c5a1a5e9fa
diff --git a/src/com/android/server/telecom/CallAudioRouteController.java b/src/com/android/server/telecom/CallAudioRouteController.java
index 839b89f..7422286 100644
--- a/src/com/android/server/telecom/CallAudioRouteController.java
+++ b/src/com/android/server/telecom/CallAudioRouteController.java
@@ -766,6 +766,7 @@
if (bluetoothRoute != null) {
Log.i(this, "request to route to bluetooth route: %s (active=%b)", bluetoothRoute,
mIsActive);
+ updateActiveBluetoothDevice(new Pair<>(type, deviceAddress));
routeTo(mIsActive, bluetoothRoute);
} else {
Log.i(this, "request to route to unavailable bluetooth route - type (%s), address (%s)",
@@ -784,10 +785,34 @@
* Message being handled: BT_ACTIVE_DEVICE_GONE
*/
private void handleBtActiveDeviceGone(@AudioRoute.AudioRouteType int type) {
- if ((mIsPending && mPendingAudioRoute.getDestRoute().getType() == type)
- || (!mIsPending && mCurrentRoute.getType() == type)) {
- // Fallback to an available route
- routeTo(mIsActive, getBaseRoute(true, null));
+ // Determine what the active device for the BT audio type was so that we can exclude this
+ // device from being used when calculating the base route.
+ String previouslyActiveDeviceAddress = mFeatureFlags
+ .resolveActiveBtRoutingAndBtTimingIssue()
+ ? mActiveDeviceCache.get(type)
+ : null;
+ // It's possible that the dest route hasn't been set yet when the controller is first
+ // initialized.
+ boolean pendingRouteNeedsUpdate = mPendingAudioRoute.getDestRoute() != null
+ && mPendingAudioRoute.getDestRoute().getType() == type;
+ boolean currentRouteNeedsUpdate = mCurrentRoute.getType() == type;
+ if (mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
+ if (pendingRouteNeedsUpdate) {
+ pendingRouteNeedsUpdate &= mPendingAudioRoute.getDestRoute().getBluetoothAddress()
+ .equals(previouslyActiveDeviceAddress);
+ }
+ if (currentRouteNeedsUpdate) {
+ currentRouteNeedsUpdate &= mCurrentRoute.getBluetoothAddress()
+ .equals(previouslyActiveDeviceAddress);
+ }
+ }
+ if ((mIsPending && pendingRouteNeedsUpdate) || (!mIsPending && currentRouteNeedsUpdate)) {
+ // Fallback to an available route excluding the previously active device.
+ routeTo(mIsActive, getBaseRoute(true, previouslyActiveDeviceAddress));
+ }
+ // Clear out the active device for the BT audio type.
+ if (mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
+ updateActiveBluetoothDevice(new Pair(type, null));
}
}
@@ -1490,9 +1515,16 @@
// If a device was removed, check to ensure that no other device is still considered
// active.
boolean hasActiveDevice = false;
- for (String address : mActiveDeviceCache.values()) {
+ List<Map.Entry<Integer, String>> activeBtDevices = new ArrayList<>(
+ mActiveDeviceCache.entrySet());
+ for (Map.Entry<Integer,String> activeDevice : activeBtDevices) {
+ Integer btAudioType = activeDevice.getKey();
+ String address = activeDevice.getValue();
if (address != null) {
hasActiveDevice = true;
+ if (mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
+ mActiveBluetoothDevice = new Pair<>(btAudioType, address);
+ }
break;
}
}
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index cd52889..bb1a745 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -252,12 +252,17 @@
CallAudioRouteController audioRouteController = (CallAudioRouteController)
mCallAudioRouteAdapter;
if (device == null) {
- audioRouteController.updateActiveBluetoothDevice(new Pair(audioRouteType, null));
+ if (!mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
+ audioRouteController.updateActiveBluetoothDevice(
+ new Pair(audioRouteType, null));
+ }
mCallAudioRouteAdapter.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_GONE,
audioRouteType);
} else {
- audioRouteController.updateActiveBluetoothDevice(
- new Pair(audioRouteType, device.getAddress()));
+ if (!mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
+ audioRouteController.updateActiveBluetoothDevice(
+ new Pair(audioRouteType, device.getAddress()));
+ }
mCallAudioRouteAdapter.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_PRESENT,
audioRouteType, device.getAddress());
if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID
@@ -267,9 +272,11 @@
Log.i(this, "handleActiveDeviceChanged: Failed to set "
+ "communication device for %s. Sending PENDING_ROUTE_FAILED to "
+ "pending audio route.", device);
- mCallAudioRouteAdapter.getPendingAudioRoute()
- .onMessageReceived(new Pair<>(PENDING_ROUTE_FAILED,
- device.getAddress()), device.getAddress());
+ if (!mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()) {
+ mCallAudioRouteAdapter.getPendingAudioRoute()
+ .onMessageReceived(new Pair<>(PENDING_ROUTE_FAILED,
+ device.getAddress()), device.getAddress());
+ }
} else {
// Track the currently set communication device.
int routeType = deviceType == BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO