Support library workaround: switch to bluetooth route if available (DO NOT MERGE)

Bug: 10003524
Change-Id: I55c2da39ac312265b3a8bcc118d54057d3808f13
(cherry picked from commit 014127a0e1841120ee0968831d40728a80f16b00)
(cherry picked from commit a0db5749e35878f8372929c942d905c464ec1d43)
(cherry picked from commit 35af7c925d660508fe0892f38eec99a3845630e4)
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index a7f550e..47d8c9f 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -1637,10 +1637,20 @@
                     route.updateDescriptor(null);
                     // 2. Remove the route from the list.
                     mRoutes.remove(route);
-                    provider.mRoutes.remove(i);
                     // 3. Unselect route if needed before notifying about removal.
                     unselectRouteIfNeeded(route);
-                    // 4. Notify clients about removal.
+                }
+
+                // Choose a new selected route if needed.
+                selectRouteIfNeeded();
+
+                // Now notify clients about routes that were removed.
+                // We do this after updating the selected route to ensure
+                // that the framework media router observes the new route
+                // selection before the removal since removing the currently
+                // selected route may have side-effects.
+                for (int i = provider.mRoutes.size() - 1; i >= targetIndex; i--) {
+                    RouteInfo route = provider.mRoutes.remove(i);
                     if (DEBUG) {
                         Log.d(TAG, "Route removed: " + route);
                     }
@@ -1652,9 +1662,6 @@
                     Log.d(TAG, "Provider changed: " + provider);
                 }
                 mCallbackHandler.post(CallbackHandler.MSG_PROVIDER_CHANGED, provider);
-
-                // Choose a new selected route if needed.
-                selectRouteIfNeeded();
             }
         }
 
@@ -1686,15 +1693,19 @@
 
         private void unselectRouteIfNeeded(RouteInfo route) {
             if (mDefaultRoute == route && !isRouteSelectable(route)) {
-                Log.i(TAG, "Choosing a new default route because the current one "
+                Log.i(TAG, "Clearing the default route because it "
                         + "is no longer selectable: " + route);
                 mDefaultRoute = null;
             }
             if (mSelectedRoute == route && !isRouteSelectable(route)) {
-                Log.i(TAG, "Choosing a new selected route because the current one "
+                Log.i(TAG, "Clearing the selected route because it "
                         + "is no longer selectable: " + route);
                 setSelectedRouteInternal(null);
             }
+            // When this function terminates, the default or selected route
+            // may be null.  The caller is responsible for invoking
+            // selectRouteIfNeeded() to choose new routes after it has
+            // finished applying any other necessary changes.
         }
 
         private void selectRouteIfNeeded() {
@@ -1707,10 +1718,31 @@
                 }
             }
             if (mSelectedRoute == null) {
-                setSelectedRouteInternal(mDefaultRoute);
+                setSelectedRouteInternal(chooseFallbackRoute());
             }
         }
 
+        private RouteInfo chooseFallbackRoute() {
+            // When the current route is removed or no longer selectable,
+            // we want to revert to a live audio route if there is
+            // one (usually Bluetooth A2DP).  Failing that, use
+            // the default route.
+            for (RouteInfo route : mRoutes) {
+                if (route != mDefaultRoute
+                        && isSystemLiveAudioOnlyRoute(route)
+                        && isRouteSelectable(route)) {
+                    return route;
+                }
+            }
+            return mDefaultRoute;
+        }
+
+        private boolean isSystemLiveAudioOnlyRoute(RouteInfo route) {
+            return route.getProviderInstance() == mSystemProvider
+                    && route.supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
+                    && !route.supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
+        }
+
         private boolean isRouteSelectable(RouteInfo route) {
             // This tests whether the route is still valid and enabled.
             // The route descriptor field is set to null when the route is removed.