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 */