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

View File

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