Merge "Use a binder instead of a bundle in removeSubscriptionWithOptions" into nyc-dev

am: 067f821

* commit '067f821ec84d3bcb556a8de77f3e3d3b8c042186':
  Use a binder instead of a bundle in removeSubscriptionWithOptions

Change-Id: Ie6cd52b5169c9b29d437fc04fc1cd71881eede22
This commit is contained in:
Sungsoo Lim
2016-04-15 16:49:22 +00:00
committed by android-build-merger
4 changed files with 73 additions and 108 deletions

View File

@@ -27,6 +27,7 @@ import android.content.pm.ParceledListSlice;
import android.media.MediaDescription; import android.media.MediaDescription;
import android.media.session.MediaController; import android.media.session.MediaController;
import android.media.session.MediaSession; import android.media.session.MediaSession;
import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
@@ -475,14 +476,8 @@ public final class MediaBrowser {
// the service will be told when we connect. // the service will be told when we connect.
if (mState == CONNECT_STATE_CONNECTED) { if (mState == CONNECT_STATE_CONNECTED) {
try { try {
// NOTE: Do not call addSubscriptionWithOptions when options are null. Otherwise, mServiceBinder.addSubscription(parentId, callback.mToken, options,
// it will break the action of support library which expects addSubscription will mServiceCallbacks);
// be called when options are null.
if (options == null) {
mServiceBinder.addSubscription(parentId, mServiceCallbacks);
} else {
mServiceBinder.addSubscriptionWithOptions(parentId, options, mServiceCallbacks);
}
} catch (RemoteException ex) { } catch (RemoteException ex) {
// Process is crashing. We will disconnect, and upon reconnect we will // Process is crashing. We will disconnect, and upon reconnect we will
// automatically reregister. So nothing to do here. // automatically reregister. So nothing to do here.
@@ -497,34 +492,37 @@ public final class MediaBrowser {
throw new IllegalArgumentException("parentId is empty."); throw new IllegalArgumentException("parentId is empty.");
} }
// Remove from our list.
Subscription sub = mSubscriptions.get(parentId); Subscription sub = mSubscriptions.get(parentId);
if (sub == null) {
return;
}
// Tell the service if necessary. // Tell the service if necessary.
if (mState == CONNECT_STATE_CONNECTED && sub != null) { try {
try { if (callback == null) {
if (callback == null) { if (mState == CONNECT_STATE_CONNECTED) {
mServiceBinder.removeSubscription(parentId, mServiceCallbacks); mServiceBinder.removeSubscription(parentId, null, mServiceCallbacks);
} else { }
final List<SubscriptionCallback> callbacks = sub.getCallbacks(); } else {
final List<Bundle> optionsList = sub.getOptionsList(); final List<SubscriptionCallback> callbacks = sub.getCallbacks();
for (int i = callbacks.size() - 1; i >= 0; --i) { final List<Bundle> optionsList = sub.getOptionsList();
if (callbacks.get(i) == callback) { for (int i = callbacks.size() - 1; i >= 0; --i) {
mServiceBinder.removeSubscriptionWithOptions( if (callbacks.get(i) == callback) {
parentId, optionsList.get(i), mServiceCallbacks); if (mState == CONNECT_STATE_CONNECTED) {
callbacks.remove(i); mServiceBinder.removeSubscription(
optionsList.remove(i); parentId, callback.mToken, mServiceCallbacks);
} }
callbacks.remove(i);
optionsList.remove(i);
} }
} }
} catch (RemoteException ex) {
// Process is crashing. We will disconnect, and upon reconnect we will
// automatically reregister. So nothing to do here.
Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
} }
} catch (RemoteException ex) {
// Process is crashing. We will disconnect, and upon reconnect we will
// automatically reregister. So nothing to do here.
Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
} }
if (sub != null && (sub.isEmpty() || callback == null)) { if (sub.isEmpty() || callback == null) {
mSubscriptions.remove(parentId); mSubscriptions.remove(parentId);
} }
} }
@@ -579,17 +577,12 @@ public final class MediaBrowser {
for (Entry<String, Subscription> subscriptionEntry : mSubscriptions.entrySet()) { for (Entry<String, Subscription> subscriptionEntry : mSubscriptions.entrySet()) {
String id = subscriptionEntry.getKey(); String id = subscriptionEntry.getKey();
Subscription sub = subscriptionEntry.getValue(); Subscription sub = subscriptionEntry.getValue();
for (Bundle options : sub.getOptionsList()) { List<SubscriptionCallback> callbackList = sub.getCallbacks();
List<Bundle> optionsList = sub.getOptionsList();
for (int i = 0; i < callbackList.size(); ++i) {
try { try {
// NOTE: Do not call addSubscriptionWithOptions when options are null. mServiceBinder.addSubscription(id, callbackList.get(i).mToken,
// Otherwise, it will break the action of support library which expects optionsList.get(i), mServiceCallbacks);
// addSubscription will be called when options are null.
if (options == null) {
mServiceBinder.addSubscription(id, mServiceCallbacks);
} else {
mServiceBinder.addSubscriptionWithOptions(
id, options, mServiceCallbacks);
}
} catch (RemoteException ex) { } catch (RemoteException ex) {
// Process is crashing. We will disconnect, and upon reconnect we will // Process is crashing. We will disconnect, and upon reconnect we will
// automatically reregister. So nothing to do here. // automatically reregister. So nothing to do here.
@@ -859,6 +852,12 @@ public final class MediaBrowser {
* Callbacks for subscription related events. * Callbacks for subscription related events.
*/ */
public static abstract class SubscriptionCallback { public static abstract class SubscriptionCallback {
Binder mToken;
public SubscriptionCallback() {
mToken = new Binder();
}
/** /**
* Called when the list of children is loaded or updated. * Called when the list of children is loaded or updated.
* *
@@ -1071,12 +1070,7 @@ public final class MediaBrowser {
} }
@Override @Override
public void onLoadChildren(String parentId, ParceledListSlice list) { public void onLoadChildren(String parentId, ParceledListSlice list,
onLoadChildrenWithOptions(parentId, list, null);
}
@Override
public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
final Bundle options) { final Bundle options) {
MediaBrowser mediaBrowser = mMediaBrowser.get(); MediaBrowser mediaBrowser = mMediaBrowser.get();
if (mediaBrowser != null) { if (mediaBrowser != null) {

View File

@@ -14,19 +14,11 @@ import android.os.ResultReceiver;
* @hide * @hide
*/ */
oneway interface IMediaBrowserService { oneway interface IMediaBrowserService {
// Warning: DO NOT CHANGE the methods signature and order of methods.
// A change of the order or the method signatures could break the support library.
void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks); void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
void disconnect(IMediaBrowserServiceCallbacks callbacks); void disconnect(IMediaBrowserServiceCallbacks callbacks);
void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks); void addSubscription(String uri, in IBinder token, in Bundle options,
void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks); IMediaBrowserServiceCallbacks callbacks);
void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks);
void getMediaItem(String uri, in ResultReceiver cb); void getMediaItem(String uri, in ResultReceiver cb);
void addSubscriptionWithOptions(String uri, in Bundle options,
IMediaBrowserServiceCallbacks callbacks);
void removeSubscriptionWithOptions(String uri, in Bundle options,
IMediaBrowserServiceCallbacks callbacks);
} }

View File

@@ -13,10 +13,6 @@ import android.os.Bundle;
* @hide * @hide
*/ */
oneway interface IMediaBrowserServiceCallbacks { oneway interface IMediaBrowserServiceCallbacks {
// Warning: DO NOT CHANGE the methods signature and order of methods.
// A change of the order or the method signatures could break the support library.
/** /**
* Invoked when the connected has been established. * Invoked when the connected has been established.
* @param root The root media id for browsing. * @param root The root media id for browsing.
@@ -26,6 +22,5 @@ oneway interface IMediaBrowserServiceCallbacks {
*/ */
void onConnect(String root, in MediaSession.Token session, in Bundle extras); void onConnect(String root, in MediaSession.Token session, in Bundle extras);
void onConnectFailed(); void onConnectFailed();
void onLoadChildren(String mediaId, in ParceledListSlice list); void onLoadChildren(String mediaId, in ParceledListSlice list, in Bundle options);
void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list, in Bundle options);
} }

View File

@@ -39,6 +39,7 @@ import android.service.media.IMediaBrowserServiceCallbacks;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -108,7 +109,7 @@ public abstract class MediaBrowserService extends Service {
Bundle rootHints; Bundle rootHints;
IMediaBrowserServiceCallbacks callbacks; IMediaBrowserServiceCallbacks callbacks;
BrowserRoot root; BrowserRoot root;
HashMap<String, List<Bundle>> subscriptions = new HashMap<>(); HashMap<String, List<Pair<IBinder, Bundle>>> subscriptions = new HashMap<>();
} }
/** /**
@@ -247,13 +248,7 @@ public abstract class MediaBrowserService extends Service {
} }
@Override @Override
public void addSubscription(final String id, public void addSubscription(final String id, final IBinder token, final Bundle options,
final IMediaBrowserServiceCallbacks callbacks) {
addSubscriptionWithOptions(id, null, callbacks);
}
@Override
public void addSubscriptionWithOptions(final String id, final Bundle options,
final IMediaBrowserServiceCallbacks callbacks) { final IMediaBrowserServiceCallbacks callbacks) {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
@@ -268,19 +263,13 @@ public abstract class MediaBrowserService extends Service {
return; return;
} }
MediaBrowserService.this.addSubscription(id, connection, options); MediaBrowserService.this.addSubscription(id, connection, token, options);
} }
}); });
} }
@Override @Override
public void removeSubscription(final String id, public void removeSubscription(final String id, final IBinder token,
final IMediaBrowserServiceCallbacks callbacks) {
removeSubscriptionWithOptions(id, null, callbacks);
}
@Override
public void removeSubscriptionWithOptions(final String id, final Bundle options,
final IMediaBrowserServiceCallbacks callbacks) { final IMediaBrowserServiceCallbacks callbacks) {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
@@ -293,7 +282,7 @@ public abstract class MediaBrowserService extends Service {
+ id); + id);
return; return;
} }
if (!MediaBrowserService.this.removeSubscription(id, connection, options)) { if (!MediaBrowserService.this.removeSubscription(id, connection, token)) {
Log.w(TAG, "removeSubscription called for " + id Log.w(TAG, "removeSubscription called for " + id
+ " which is not subscribed"); + " which is not subscribed");
} }
@@ -519,11 +508,12 @@ public abstract class MediaBrowserService extends Service {
public void run() { public void run() {
for (IBinder binder : mConnections.keySet()) { for (IBinder binder : mConnections.keySet()) {
ConnectionRecord connection = mConnections.get(binder); ConnectionRecord connection = mConnections.get(binder);
List<Bundle> optionsList = connection.subscriptions.get(parentId); List<Pair<IBinder, Bundle>> callbackList =
if (optionsList != null) { connection.subscriptions.get(parentId);
for (Bundle bundle : optionsList) { if (callbackList != null) {
if (MediaBrowserUtils.hasDuplicatedItems(options, bundle)) { for (Pair<IBinder, Bundle> callback : callbackList) {
performLoadChildren(parentId, connection, bundle); if (MediaBrowserUtils.hasDuplicatedItems(options, callback.second)) {
performLoadChildren(parentId, connection, callback.second);
} }
} }
} }
@@ -553,19 +543,21 @@ public abstract class MediaBrowserService extends Service {
/** /**
* Save the subscription and if it is a new subscription send the results. * Save the subscription and if it is a new subscription send the results.
*/ */
private void addSubscription(String id, ConnectionRecord connection, Bundle options) { private void addSubscription(String id, ConnectionRecord connection, IBinder token,
Bundle options) {
// Save the subscription // Save the subscription
List<Bundle> optionsList = connection.subscriptions.get(id); List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
if (optionsList == null) { if (callbackList == null) {
optionsList = new ArrayList<>(); callbackList = new ArrayList<>();
} }
for (Bundle bundle : optionsList) { for (Pair<IBinder, Bundle> callback : callbackList) {
if (MediaBrowserUtils.areSameOptions(options, bundle)) { if (token == callback.first
&& MediaBrowserUtils.areSameOptions(options, callback.second)) {
return; return;
} }
} }
optionsList.add(options); callbackList.add(new Pair<>(token, options));
connection.subscriptions.put(id, optionsList); connection.subscriptions.put(id, callbackList);
// send the results // send the results
performLoadChildren(id, connection, options); performLoadChildren(id, connection, options);
} }
@@ -573,21 +565,20 @@ public abstract class MediaBrowserService extends Service {
/** /**
* Remove the subscription. * Remove the subscription.
*/ */
private boolean removeSubscription(String id, ConnectionRecord connection, Bundle options) { private boolean removeSubscription(String id, ConnectionRecord connection, IBinder token) {
if (options == null) { if (token == null) {
return connection.subscriptions.remove(id) != null; return connection.subscriptions.remove(id) != null;
} }
boolean removed = false; boolean removed = false;
List<Bundle> optionsList = connection.subscriptions.get(id); List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
if (optionsList != null) { if (callbackList != null) {
for (Bundle bundle : optionsList) { for (Pair<IBinder, Bundle> callback : callbackList) {
if (MediaBrowserUtils.areSameOptions(options, bundle)) { if (token == callback.first) {
removed = true; removed = true;
optionsList.remove(bundle); callbackList.remove(callback);
break;
} }
} }
if (optionsList.size() == 0) { if (callbackList.size() == 0) {
connection.subscriptions.remove(id); connection.subscriptions.remove(id);
} }
} }
@@ -619,14 +610,7 @@ public abstract class MediaBrowserService extends Service {
final ParceledListSlice<MediaBrowser.MediaItem> pls = final ParceledListSlice<MediaBrowser.MediaItem> pls =
filteredList == null ? null : new ParceledListSlice<>(filteredList); filteredList == null ? null : new ParceledListSlice<>(filteredList);
try { try {
// NOTE: Do not call onLoadChildrenWithOptions when options are null. Otherwise, connection.callbacks.onLoadChildren(parentId, pls, options);
// it will break the action of support library which expects onLoadChildren will
// be called when options are null.
if (options == null) {
connection.callbacks.onLoadChildren(parentId, pls);
} else {
connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
}
} catch (RemoteException ex) { } catch (RemoteException ex) {
// The other side is in the process of crashing. // The other side is in the process of crashing.
Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId