Prevent floating mMediaBrowser reference

When switching to a new browser, only disconnect and change to the new
browser once connection succeeds. This will allow the old browser to be
valid and targetable until a new browser connects.

Bug: 62328135
Test: Switch between browsable players on VW carkit
Change-Id: I5701138f9adf4e8c6e08629d86583dbe87290542
(cherry picked from commit 24ff0081728d0adb11b949dcbee196a1b260e9f4)
diff --git a/android/app/src/com/android/bluetooth/avrcp/BrowsedMediaPlayer.java b/android/app/src/com/android/bluetooth/avrcp/BrowsedMediaPlayer.java
index 324e60c..ba8b64a 100644
--- a/android/app/src/com/android/bluetooth/avrcp/BrowsedMediaPlayer.java
+++ b/android/app/src/com/android/bluetooth/avrcp/BrowsedMediaPlayer.java
@@ -53,6 +53,7 @@
 
     /*  package and service name of target Media Player which is set for browsing */
     private String mPackageName;
+    private String mConnectingPackageName;
     private String mClassName;
     private Context mContext;
     private AvrcpMediaRspInterface mMediaInterface;
@@ -83,20 +84,34 @@
     private List<MediaBrowser.MediaItem> mFolderItems = null;
 
     /* Connection state callback handler */
-    private MediaBrowser.ConnectionCallback browseMediaConnectionCallback =
-            new MediaBrowser.ConnectionCallback() {
+    class MediaConnectionCallback extends MediaBrowser.ConnectionCallback {
+        private String mCallbackPackageName;
+        private MediaBrowser mBrowser;
+
+        public MediaConnectionCallback(String packageName) {
+            this.mCallbackPackageName = packageName;
+        }
+
+        public void setBrowser(MediaBrowser b) {
+            mBrowser = b;
+        }
 
         @Override
         public void onConnected() {
             mConnState = CONNECTED;
             if (DEBUG) Log.d(TAG, "mediaBrowser CONNECTED to " + mPackageName);
             /* perform init tasks and set player as browsed player on successful connection */
-            onBrowseConnect();
+            onBrowseConnect(mCallbackPackageName, mBrowser);
+
+            // Remove what could be a circular dependency causing GC to never happen on this object
+            mBrowser = null;
         }
 
         @Override
         public void onConnectionFailed() {
             mConnState = DISCONNECTED;
+            // Remove what could be a circular dependency causing GC to never happen on this object
+            mBrowser = null;
             Log.e(TAG, "mediaBrowser Connection failed with " + mPackageName
                     + ", Sending fail response!");
             mMediaInterface.setBrowsedPlayerRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR,
@@ -105,10 +120,11 @@
 
         @Override
         public void onConnectionSuspended() {
+            mBrowser = null;
             mConnState = SUSPENDED;
             Log.e(TAG, "mediaBrowser SUSPENDED connection with " + mPackageName);
         }
-    };
+    }
 
     /* Subscription callback handler. Subscribe to a folder to get its contents */
     private MediaBrowser.SubscriptionCallback folderItemsCb =
@@ -251,26 +267,45 @@
     }
 
     /* initialize mediacontroller in order to communicate with media player. */
-    private void onBrowseConnect() {
-        boolean isError = false;
+    private void onBrowseConnect(String connectedPackage, MediaBrowser browser) {
+        if (!connectedPackage.equals(mConnectingPackageName)) {
+            Log.w(TAG,
+                    "onBrowseConnect: recieved callback for package we aren't connecting to "
+                            + connectedPackage);
+            return;
+        }
+        mConnectingPackageName = null;
+
+        if (browser == null) {
+            Log.e(TAG, "onBrowseConnect: received a null browser for " + connectedPackage);
+            mMediaInterface.setBrowsedPlayerRsp(
+                    mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, (byte) 0x00, 0, null);
+            return;
+        }
+
         MediaSession.Token token = null;
         try {
-            /* get rootfolder uid from media player */
-            if (mMediaId == null) {
-                mMediaId = mMediaBrowser.getRoot();
-                /*
-                 * assuming that root folder uid will not change on uids changed
-                 */
-                mRootFolderUid = mMediaId;
-                /* store root folder uid to stack */
-                mPathStack.push(mMediaId);
-            }
-
-            if (!mMediaBrowser.isConnected()) {
+            if (!browser.isConnected()) {
                 Log.e(TAG, "setBrowsedPlayer: " + mPackageName + "not connected");
-            } else if ((token = mMediaBrowser.getSessionToken()) == null) {
+            } else if ((token = browser.getSessionToken()) == null) {
                 Log.e(TAG, "setBrowsedPlayer: " + mPackageName + "no Session token");
             } else {
+                /* update to the new MediaBrowser */
+                if (mMediaBrowser != null) mMediaBrowser.disconnect();
+                mMediaBrowser = browser;
+                mPackageName = connectedPackage;
+
+                /* get rootfolder uid from media player */
+                if (mMediaId == null) {
+                    mMediaId = mMediaBrowser.getRoot();
+                    /*
+                     * assuming that root folder uid will not change on uids changed
+                     */
+                    mRootFolderUid = mMediaId;
+                    /* store root folder uid to stack */
+                    mPathStack.push(mMediaId);
+                }
+
                 mMediaController = MediaController.wrap(
                     new android.media.session.MediaController(mContext, token));
                 /* get root folder items */
@@ -287,7 +322,7 @@
     }
 
     public void setBrowsed(String packageName, String cls) {
-        mPackageName = packageName;
+        mConnectingPackageName = packageName;
         mClassName = cls;
         /* cleanup variables from previous browsed calls */
         mFolderItems = null;
@@ -298,10 +333,14 @@
          * will be required while navigating up the folder
          */
         mPathStack = new Stack<String>();
+
         /* Bind to MediaBrowseService of MediaPlayer */
-        mMediaBrowser = new MediaBrowser(mContext, new ComponentName(mPackageName, mClassName),
-                browseMediaConnectionCallback, null);
-        mMediaBrowser.connect();
+        MediaConnectionCallback callback = new MediaConnectionCallback(packageName);
+        MediaBrowser tempBrowser = new MediaBrowser(
+                mContext, new ComponentName(packageName, mClassName), callback, null);
+        callback.setBrowser(tempBrowser);
+
+        tempBrowser.connect();
     }
 
     /* called when connection to media player is closed */