Merge "Track the global setting of BT A2DP on/off" into oc-mr1-dev am: cc2478f90c
am: 0047534b7f

Change-Id: Iaa02ab736989e55660ad6813fcaa97e2b411a27e
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 3308fc9..dc7fa8c 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -28,6 +28,7 @@
 
     MediaRouterClientState getState(IMediaRouterClient client);
     boolean isPlaybackActive(IMediaRouterClient client);
+    boolean isGlobalBluetoothA2doOn();
 
     void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan);
     void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 29b88a2..2894e89 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -88,7 +88,6 @@
         RouteInfo mBluetoothA2dpRoute;
 
         RouteInfo mSelectedRoute;
-        RouteInfo mSystemAudioRoute;
 
         final boolean mCanConfigureWifiDisplays;
         boolean mActivelyScanningWifiDisplays;
@@ -150,7 +149,6 @@
             }
 
             addRouteStatic(mDefaultAudioVideo);
-            mSystemAudioRoute = mDefaultAudioVideo;
 
             // This will select the active wifi display route if there is one.
             updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus());
@@ -185,7 +183,7 @@
         }
 
         void updateAudioRoutes(AudioRoutesInfo newRoutes) {
-            boolean updated = false;
+            boolean audioRoutesChanged = false;
             if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) {
                 mCurAudioRoutesInfo.mainType = newRoutes.mainType;
                 int name;
@@ -201,11 +199,10 @@
                 }
                 mDefaultAudioVideo.mNameResId = name;
                 dispatchRouteChanged(mDefaultAudioVideo);
-                updated = true;
+                audioRoutesChanged = true;
             }
 
             final int mainType = mCurAudioRoutesInfo.mainType;
-
             if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
                 mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
                 if (mCurAudioRoutesInfo.bluetoothName != null) {
@@ -219,8 +216,6 @@
                         info.mDeviceType = RouteInfo.DEVICE_TYPE_BLUETOOTH;
                         mBluetoothA2dpRoute = info;
                         addRouteStatic(mBluetoothA2dpRoute);
-                        mSystemAudioRoute = mBluetoothA2dpRoute;
-                        selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false);
                     } else {
                         mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName;
                         dispatchRouteChanged(mBluetoothA2dpRoute);
@@ -229,30 +224,32 @@
                     // BT disconnected
                     removeRouteStatic(mBluetoothA2dpRoute);
                     mBluetoothA2dpRoute = null;
-                    mSystemAudioRoute = mDefaultAudioVideo;
-                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false);
                 }
-                updated = true;
+                audioRoutesChanged = true;
             }
 
-            if (mBluetoothA2dpRoute != null) {
-                final boolean a2dpEnabled = isBluetoothA2dpOn();
-                if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
-                    // A2DP off
-                    mSystemAudioRoute = mDefaultAudioVideo;
-                    updated = true;
-                } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
-                        a2dpEnabled) {
-                    // A2DP on or BT connected
-                    mSystemAudioRoute = mBluetoothA2dpRoute;
-                    updated = true;
-                }
-            }
-            if (updated) {
+            if (audioRoutesChanged) {
+                selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false);
                 Log.v(TAG, "Audio routes updated: " + newRoutes + ", a2dp=" + isBluetoothA2dpOn());
             }
         }
 
+        RouteInfo getDefaultSystemAudioRoute() {
+            boolean globalBluetoothA2doOn = false;
+            try {
+                globalBluetoothA2doOn = mMediaRouterService.isGlobalBluetoothA2doOn();
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to call isSystemBluetoothA2doOn.", ex);
+            }
+            return (globalBluetoothA2doOn && mBluetoothA2dpRoute != null)
+                    ? mBluetoothA2dpRoute : mDefaultAudioVideo;
+        }
+
+        RouteInfo getCurrentSystemAudioRoute() {
+            return (isBluetoothA2dpOn() && mBluetoothA2dpRoute != null)
+                    ? mBluetoothA2dpRoute : mDefaultAudioVideo;
+        }
+
         boolean isBluetoothA2dpOn() {
             try {
                 return mAudioService.isBluetoothA2dpOn();
@@ -603,15 +600,13 @@
 
             @Override
             public void onRestoreRoute() {
+                // Skip restoring route if the selected route is not a system audio route, or
+                // MediaRouter is initializing.
                 if ((mSelectedRoute != mDefaultAudioVideo && mSelectedRoute != mBluetoothA2dpRoute)
-                        || mSelectedRoute == mSystemAudioRoute) {
+                        || mSelectedRoute == null) {
                     return;
                 }
-                try {
-                    sStatic.mAudioService.setBluetoothA2dpOn(mSelectedRoute == mBluetoothA2dpRoute);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Error changing Bluetooth A2DP state", e);
-                }
+                mSelectedRoute.select();
             }
         }
     }
@@ -946,7 +941,7 @@
         boolean wasDefaultOrBluetoothRoute = (oldRoute == sStatic.mDefaultAudioVideo
                 || oldRoute == sStatic.mBluetoothA2dpRoute);
         if (oldRoute == route
-                && (!wasDefaultOrBluetoothRoute || oldRoute == sStatic.mSystemAudioRoute)) {
+                && (!wasDefaultOrBluetoothRoute || route == sStatic.getCurrentSystemAudioRoute())) {
             return;
         }
         if (!route.matchesTypes(types)) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 922df1e..3795b7f 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -18,9 +18,7 @@
 
 import com.android.internal.util.DumpUtils;
 import com.android.server.Watchdog;
-import com.android.server.media.AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener;
 
-import android.Manifest;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -96,9 +94,10 @@
     private final ArrayMap<IBinder, ClientRecord> mAllClientRecords =
             new ArrayMap<IBinder, ClientRecord>();
     private int mCurrentUserId = -1;
-    private boolean mHasBluetoothRoute = false;
+    private boolean mGlobalBluetoothA2dpOn = false;
     private final IAudioService mAudioService;
     private final AudioPlaybackMonitor mAudioPlaybackMonitor;
+    private final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
 
     public MediaRouterService(Context context) {
         mContext = context;
@@ -137,13 +136,39 @@
             audioRoutes = mAudioService.startWatchingRoutes(new IAudioRoutesObserver.Stub() {
                 @Override
                 public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
-                    mHasBluetoothRoute = newRoutes.bluetoothName != null;
+                    synchronized (mLock) {
+                        if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) {
+                            if ((newRoutes.mainType & (AudioRoutesInfo.MAIN_HEADSET
+                                    | AudioRoutesInfo.MAIN_HEADPHONES
+                                    | AudioRoutesInfo.MAIN_USB)) == 0) {
+                                // headset was plugged out.
+                                mGlobalBluetoothA2dpOn = newRoutes.bluetoothName != null;
+                            } else {
+                                // headset was plugged in.
+                                mGlobalBluetoothA2dpOn = false;
+                            }
+                            mCurAudioRoutesInfo.mainType = newRoutes.mainType;
+                        }
+                        if (!TextUtils.equals(
+                                newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
+                            if (newRoutes.bluetoothName == null) {
+                                // BT was disconnected.
+                                mGlobalBluetoothA2dpOn = false;
+                            } else {
+                                // BT was connected or changed.
+                                mGlobalBluetoothA2dpOn = true;
+                            }
+                            mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
+                        }
+                    }
                 }
             });
         } catch (RemoteException e) {
             Slog.w(TAG, "RemoteException in the audio service.");
         }
-        mHasBluetoothRoute = (audioRoutes != null && audioRoutes.bluetoothName != null);
+        synchronized (mLock) {
+            mGlobalBluetoothA2dpOn = (audioRoutes != null && audioRoutes.bluetoothName != null);
+        }
     }
 
     public void systemRunning() {
@@ -246,6 +271,14 @@
 
     // Binder call
     @Override
+    public boolean isGlobalBluetoothA2doOn() {
+        synchronized (mLock) {
+            return mGlobalBluetoothA2dpOn;
+        }
+    }
+
+    // Binder call
+    @Override
     public void setDiscoveryRequest(IMediaRouterClient client,
             int routeTypes, boolean activeScan) {
         if (client == null) {
@@ -346,7 +379,12 @@
 
     void restoreBluetoothA2dp() {
         try {
-            mAudioService.setBluetoothA2dpOn(mHasBluetoothRoute);
+            boolean a2dpOn = false;
+            synchronized (mLock) {
+                a2dpOn = mGlobalBluetoothA2dpOn;
+            }
+            Slog.v(TAG, "restoreBluetoothA2dp( " + a2dpOn + ")");
+            mAudioService.setBluetoothA2dpOn(a2dpOn);
         } catch (RemoteException e) {
             Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn.");
         }
@@ -354,12 +392,14 @@
 
     void restoreRoute(int uid) {
         ClientRecord clientRecord = null;
-        UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid));
-        if (userRecord != null && userRecord.mClientRecords != null) {
-            for (ClientRecord cr : userRecord.mClientRecords) {
-                if (validatePackageName(uid, cr.mPackageName)) {
-                    clientRecord = cr;
-                    break;
+        synchronized (mLock) {
+            UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid));
+            if (userRecord != null && userRecord.mClientRecords != null) {
+                for (ClientRecord cr : userRecord.mClientRecords) {
+                    if (validatePackageName(uid, cr.mPackageName)) {
+                        clientRecord = cr;
+                        break;
+                    }
                 }
             }
         }