Resolve call supported routes issue

When connecting a wired headset during a call, a reporter noted that the
audio wasn't going through the headset. Upon closer inspection, the call
supported routes weren't updated to take into account the newly added
route. As a result, the wired headset route wasn't found from the
available call supported routes so the routing was ignored. This CL
ensures that the call supported routes are updated when the available
routes are updated.

This wasn't caught by unit testing as the update only occurred when the
foreground call was updated (UPDATE_SYSTEM_AUDIO_ROUTE). Consequently,
the available routes were used instead of the call supported routes. Now
that the routes are properly updated for the call supported routes,
those are being used in the existing tests so no additional tests need
to be added.

Bug: 363885916
Test: Manual
Test: atest CallAudioRouteControllerTest
Flag:
com.android.server.telecom.flags.use_refactored_audio_route_switching

Change-Id: If71913181c7d632488726a6e2951825dfc5ce056
diff --git a/src/com/android/server/telecom/CallAudioRouteController.java b/src/com/android/server/telecom/CallAudioRouteController.java
index 6f205c2..3dcd58e 100644
--- a/src/com/android/server/telecom/CallAudioRouteController.java
+++ b/src/com/android/server/telecom/CallAudioRouteController.java
@@ -109,6 +109,7 @@
     private int mFocusType;
     private int mCallSupportedRouteMask = -1;
     private boolean mIsScoAudioConnected;
+    private boolean mAvailableRoutesUpdated;
     private final Object mLock = new Object();
     private final TelecomSystem.SyncRoot mTelecomLock;
     private final BroadcastReceiver mSpeakerPhoneChangeReceiver = new BroadcastReceiver() {
@@ -359,7 +360,7 @@
                 Log.w(this, "Can't find available audio device info for route TYPE_SPEAKER");
             } else {
                 mTypeRoutes.put(AudioRoute.TYPE_SPEAKER, mSpeakerDockRoute);
-                mAvailableRoutes.add(mSpeakerDockRoute);
+                updateAvailableRoutes(mSpeakerDockRoute, true);
             }
         }
 
@@ -371,7 +372,7 @@
                 Log.w(this, "Can't find available audio device info for route TYPE_WIRED_HEADSET");
             } else {
                 mTypeRoutes.put(AudioRoute.TYPE_WIRED, mEarpieceWiredRoute);
-                mAvailableRoutes.add(mEarpieceWiredRoute);
+                updateAvailableRoutes(mEarpieceWiredRoute, true);
             }
         } else if ((supportMask & CallAudioState.ROUTE_EARPIECE) != 0) {
             // Create earpiece routes
@@ -381,7 +382,7 @@
                 Log.w(this, "Can't find available audio device info for route TYPE_EARPIECE");
             } else {
                 mTypeRoutes.put(AudioRoute.TYPE_EARPIECE, mEarpieceWiredRoute);
-                mAvailableRoutes.add(mEarpieceWiredRoute);
+                updateAvailableRoutes(mEarpieceWiredRoute, true);
             }
         }
 
@@ -546,8 +547,8 @@
         }
 
         if (wiredHeadsetRoute != null) {
-            mAvailableRoutes.add(wiredHeadsetRoute);
-            mAvailableRoutes.remove(mEarpieceWiredRoute);
+            updateAvailableRoutes(wiredHeadsetRoute, true);
+            updateAvailableRoutes(mEarpieceWiredRoute, false);
             mTypeRoutes.put(AudioRoute.TYPE_WIRED, wiredHeadsetRoute);
             mEarpieceWiredRoute = wiredHeadsetRoute;
             routeTo(mIsActive, wiredHeadsetRoute);
@@ -559,12 +560,12 @@
         // Update audio route states
         AudioRoute wiredHeadsetRoute = mTypeRoutes.remove(AudioRoute.TYPE_WIRED);
         if (wiredHeadsetRoute != null) {
-            mAvailableRoutes.remove(wiredHeadsetRoute);
+            updateAvailableRoutes(wiredHeadsetRoute, false);
             mEarpieceWiredRoute = null;
         }
         AudioRoute earpieceRoute = mTypeRoutes.get(AudioRoute.TYPE_EARPIECE);
         if (earpieceRoute != null) {
-            mAvailableRoutes.add(earpieceRoute);
+            updateAvailableRoutes(earpieceRoute, true);
             mEarpieceWiredRoute = earpieceRoute;
         }
         onAvailableRoutesChanged();
@@ -585,8 +586,8 @@
         }
 
         if (dockRoute != null) {
-            mAvailableRoutes.add(dockRoute);
-            mAvailableRoutes.remove(mSpeakerDockRoute);
+            updateAvailableRoutes(dockRoute, true);
+            updateAvailableRoutes(mSpeakerDockRoute, false);
             mTypeRoutes.put(AudioRoute.TYPE_DOCK, dockRoute);
             mSpeakerDockRoute = dockRoute;
             routeTo(mIsActive, dockRoute);
@@ -598,12 +599,12 @@
         // Update audio route states
         AudioRoute dockRoute = mTypeRoutes.get(AudioRoute.TYPE_DOCK);
         if (dockRoute != null) {
-            mAvailableRoutes.remove(dockRoute);
+            updateAvailableRoutes(dockRoute, false);
             mSpeakerDockRoute = null;
         }
         AudioRoute speakerRoute = mTypeRoutes.get(AudioRoute.TYPE_SPEAKER);
         if (speakerRoute != null) {
-            mAvailableRoutes.add(speakerRoute);
+            updateAvailableRoutes(speakerRoute, true);
             mSpeakerDockRoute = speakerRoute;
         }
         onAvailableRoutesChanged();
@@ -679,7 +680,7 @@
      * Message being handled: BT_DEVICE_ADDED
      */
     private void handleBtConnected(@AudioRoute.AudioRouteType int type,
-                                   BluetoothDevice bluetoothDevice) {
+            BluetoothDevice bluetoothDevice) {
         if (containsHearingAidPair(type, bluetoothDevice)) {
             return;
         }
@@ -691,7 +692,7 @@
                     + AudioRoute.DEVICE_TYPE_STRINGS.get(type));
         } else {
             Log.i(this, "bluetooth route added: " + bluetoothRoute);
-            mAvailableRoutes.add(bluetoothRoute);
+            updateAvailableRoutes(bluetoothRoute, true);
             mBluetoothRoutes.put(bluetoothRoute, bluetoothDevice);
             onAvailableRoutesChanged();
         }
@@ -706,13 +707,13 @@
      * Message being handled: BT_DEVICE_REMOVED
      */
     private void handleBtDisconnected(@AudioRoute.AudioRouteType int type,
-                                      BluetoothDevice bluetoothDevice) {
+            BluetoothDevice bluetoothDevice) {
         // Clean up unavailable routes
         AudioRoute bluetoothRoute = getBluetoothRoute(type, bluetoothDevice.getAddress());
         if (bluetoothRoute != null) {
             Log.i(this, "bluetooth route removed: " + bluetoothRoute);
             mBluetoothRoutes.remove(bluetoothRoute);
-            mAvailableRoutes.remove(bluetoothRoute);
+            updateAvailableRoutes(bluetoothRoute, false);
             onAvailableRoutesChanged();
         }
 
@@ -730,7 +731,7 @@
      * Message being handled: BT_ACTIVE_DEVICE_PRESENT
      */
     private void handleBtActiveDevicePresent(@AudioRoute.AudioRouteType int type,
-                                             String deviceAddress) {
+            String deviceAddress) {
         AudioRoute bluetoothRoute = getBluetoothRoute(type, deviceAddress);
         if (bluetoothRoute != null) {
             Log.i(this, "request to route to bluetooth route: %s (active=%b)", bluetoothRoute,
@@ -809,11 +810,12 @@
                     // was routed to a watch. When active focus is received, this selection will be
                     // honored provided that the current route is associated.
                     Log.i(this, "handleSwitchFocus (ACTIVE_FOCUS): mBluetoothAddressForRinging = "
-                        + "%s, mCurrentRoute = %s", mBluetoothAddressForRinging, mCurrentRoute);
+                            + "%s, mCurrentRoute = %s", mBluetoothAddressForRinging, mCurrentRoute);
                     AudioRoute audioRoute = mBluetoothAddressForRinging != null
-                        && mBluetoothAddressForRinging.equals(mCurrentRoute.getBluetoothAddress())
-                        ? mCurrentRoute
-                        : getBaseRoute(true, null);
+                            && mBluetoothAddressForRinging.equals(
+                                    mCurrentRoute.getBluetoothAddress())
+                            ? mCurrentRoute
+                            : getBaseRoute(true, null);
                     routeTo(true, audioRoute);
                     clearRingingBluetoothAddress();
                 }
@@ -1042,6 +1044,7 @@
     private boolean updateCallSupportedAudioRoutes() {
         int availableRouteMask = 0;
         Call foregroundCall = mCallsManager.getForegroundCall();
+        mCallSupportedRoutes.clear();
         if (foregroundCall != null) {
             int foregroundCallSupportedRouteMask = foregroundCall.getSupportedAudioRoutes();
             for (AudioRoute route : getAvailableRoutes()) {
@@ -1054,7 +1057,6 @@
             mCallSupportedRouteMask = availableRouteMask & foregroundCallSupportedRouteMask;
             return true;
         } else {
-            mCallSupportedRoutes.clear();
             mCallSupportedRouteMask = -1;
             return false;
         }
@@ -1193,6 +1195,10 @@
         if (mCurrentRoute.equals(mStreamingRoute)) {
             return mStreamingRoutes;
         } else {
+            if (mAvailableRoutesUpdated) {
+                updateCallSupportedAudioRoutes();
+                mAvailableRoutesUpdated = false;
+            }
             return mCallSupportedRoutes.isEmpty() ? mAvailableRoutes : mCallSupportedRoutes;
         }
     }
@@ -1420,6 +1426,15 @@
         }
     }
 
+    private void updateAvailableRoutes(AudioRoute route, boolean includeRoute) {
+        if (includeRoute) {
+            mAvailableRoutes.add(route);
+        } else {
+            mAvailableRoutes.remove(route);
+        }
+        mAvailableRoutesUpdated = true;
+    }
+
     @VisibleForTesting
     public void setActive(boolean active) {
         if (active) {