Merge "Resolve call supported routes issue" into main
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) {