From 80bb169d0ff778ca7073486f4e2900f8479c2daa Mon Sep 17 00:00:00 2001 From: Yao Chen Date: Wed, 23 Jul 2014 15:04:48 -0700 Subject: [PATCH] Use a sequence number for thumbnail callback. Change-Id: I27888cd0437b4f654cb29371b7d86b9341d84ae9 --- .../android/media/browse/IMediaBrowserService.aidl | 3 +- .../browse/IMediaBrowserServiceCallbacks.aidl | 2 +- media/java/android/media/browse/MediaBrowser.java | 140 ++++++++++++--------- .../android/media/browse/MediaBrowserService.java | 4 +- 4 files changed, 85 insertions(+), 64 deletions(-) diff --git a/media/java/android/media/browse/IMediaBrowserService.aidl b/media/java/android/media/browse/IMediaBrowserService.aidl index 177bd1bbc5de..5126f6bd1833 100644 --- a/media/java/android/media/browse/IMediaBrowserService.aidl +++ b/media/java/android/media/browse/IMediaBrowserService.aidl @@ -18,5 +18,6 @@ oneway interface IMediaBrowserService { void addSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks); void removeSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks); - void loadThumbnail(in Uri uri, int width, int height, IMediaBrowserServiceCallbacks callbacks); + void loadThumbnail(in int seqNum, in Uri uri, int width, int height, + IMediaBrowserServiceCallbacks callbacks); } \ No newline at end of file diff --git a/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl b/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl index 1f03a1a84b2e..f6d5daefdd79 100644 --- a/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl +++ b/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl @@ -24,5 +24,5 @@ oneway interface IMediaBrowserServiceCallbacks { void onConnect(in Uri root, in MediaSession.Token session, in Bundle extras); void onConnectFailed(); void onLoadChildren(in Uri uri, in ParceledListSlice list); - void onLoadThumbnail(in Uri uri, int width, int height, in Bitmap bitmap); + void onLoadThumbnail(int seqNum, in Bitmap bitmap); } diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java index d17f95d6c5f4..f6ea360f3ada 100644 --- a/media/java/android/media/browse/MediaBrowser.java +++ b/media/java/android/media/browse/MediaBrowser.java @@ -33,6 +33,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; +import android.util.SparseArray; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -40,6 +41,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -65,8 +67,8 @@ public final class MediaBrowser { private final Handler mHandler = new Handler(); private final ArrayMap mSubscriptions = new ArrayMap(); - private final ArrayMap> mThumbnailCallbacks = - new ArrayMap>(); + private final SparseArray mThumbnailRequests = + new SparseArray(); private int mState = CONNECT_STATE_DISCONNECTED; private MediaServiceConnection mServiceConnection; @@ -75,6 +77,7 @@ public final class MediaBrowser { private Uri mRootUri; private MediaSession.Token mMediaSessionToken; private Bundle mExtras; + private int mNextSeq; /** * Creates a media browser for the specified media browse service. @@ -367,21 +370,20 @@ public final class MediaBrowser { mHandler.post(new Runnable() { @Override public void run() { - HashSet callbackSet; - ThumbnailRequest request = new ThumbnailRequest(uri, width, height); - callbackSet = mThumbnailCallbacks.get(request); - if (callbackSet != null) { - callbackSet.add(callback); - mThumbnailCallbacks.put(request, callbackSet); - // same request has been sent. we will wait for the callback. - return; + for (int i = 0; i < mThumbnailRequests.size(); i++) { + ThumbnailRequest existingRequest = mThumbnailRequests.valueAt(i); + if (existingRequest.isSameRequest(uri, width, height)) { + existingRequest.addCallback(callback); + return; + } } - callbackSet = new HashSet(); - callbackSet.add(callback); - mThumbnailCallbacks.put(request, callbackSet); + final int seq = mNextSeq++; + ThumbnailRequest request = new ThumbnailRequest(seq, uri, width, height); + request.addCallback(callback); + mThumbnailRequests.put(seq, request); if (mState == CONNECT_STATE_CONNECTED) { try { - mServiceBinder.loadThumbnail(uri, width, height, mServiceCallbacks); + mServiceBinder.loadThumbnail(seq, uri, width, height, mServiceCallbacks); } catch (RemoteException e) { // Process is crashing. We will disconnect, and upon reconnect we will // automatically reload the thumbnails. So nothing to do here. @@ -449,17 +451,17 @@ public final class MediaBrowser { } } - for (ThumbnailRequest request : mThumbnailCallbacks.keySet()) { + for (int i = 0; i < mThumbnailRequests.size(); i++) { + ThumbnailRequest request = mThumbnailRequests.valueAt(i); try { - mServiceBinder.loadThumbnail(request.uri, request.width, request.height, - mServiceCallbacks); + mServiceBinder.loadThumbnail(request.mSeq, request.mUri, + request.mWidth, request.mHeight, mServiceCallbacks); } catch (RemoteException e) { // Process is crashing. We will disconnect, and upon reconnect we will // automatically reload. So nothing to do here. - Log.d(TAG, "loadThumbnail failed with RemoteException uri=" + request.uri); + Log.d(TAG, "loadThumbnail failed with RemoteException request=" + request); } } - } }); } @@ -527,7 +529,7 @@ public final class MediaBrowser { } private final void onLoadThumbnail(final IMediaBrowserServiceCallbacks callback, - final ThumbnailRequest request, final Bitmap bitmap) { + final int seqNum, final Bitmap bitmap) { mHandler.post(new Runnable() { @Override public void run() { @@ -537,16 +539,16 @@ public final class MediaBrowser { return; } - Set callbackSet = mThumbnailCallbacks.get(request); - if (callbackSet == null) { - Log.d(TAG, "onLoadThumbnail called for request=" + request + - " but the callback is not registered"); + ThumbnailRequest request = mThumbnailRequests.get(seqNum); + if (request == null) { + Log.d(TAG, "onLoadThumbnail called for seqNum=" + seqNum + " request=" + + request + " but the request is not registered"); return; } - for (ThumbnailCallback thumbnailCallback : callbackSet) { - thumbnailCallback.onThumbnailLoaded(request.uri, bitmap); + mThumbnailRequests.delete(seqNum); + for (ThumbnailCallback thumbnailCallback : request.getCallbacks()) { + thumbnailCallback.onThumbnailLoaded(request.mUri, bitmap); } - mThumbnailCallbacks.remove(request); } }); } @@ -651,47 +653,66 @@ public final class MediaBrowser { } private static class ThumbnailRequest { - Uri uri; - int width; - int height; - ThumbnailRequest(@NonNull Uri uri, int width, int height) { + final int mSeq; + final Uri mUri; + final int mWidth; + final int mHeight; + final List mCallbacks; + + /** + * Constructs a thumbnail request. + * @param seq The unique sequence number assigned to the request by the media browser. + * @param uri The Uri for the thumbnail. + * @param width The width for the thumbnail. + * @param height The height for the thumbnail. + */ + ThumbnailRequest(int seq, @NonNull Uri uri, int width, int height) { if (uri == null) { throw new IllegalArgumentException("thumbnail uri cannot be null"); } - this.uri = uri; - this.width = width; - this.height = height; + this.mSeq = seq; + this.mUri = uri; + this.mWidth = width; + this.mHeight = height; + mCallbacks = new ArrayList(); } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ThumbnailRequest)) return false; - - ThumbnailRequest that = (ThumbnailRequest) o; - - if (height != that.height) return false; - if (width != that.width) return false; - if (!uri.equals(that.uri)) return false; - - return true; + /** + * Adds a callback to the thumbnail request. + * If the callback already exists, it will not be added again. + */ + public void addCallback(@NonNull ThumbnailCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null in ThumbnailRequest"); + } + if (!mCallbacks.contains(callback)) { + mCallbacks.add(callback); + } } - @Override - public int hashCode() { - int result = uri.hashCode(); - result = 31 * result + width; - result = 31 * result + height; - return result; + /** + * Checks if the thumbnail request has the same uri, width, and height as the given values. + */ + public boolean isSameRequest(@Nullable Uri uri, int width, int height) { + return Objects.equals(mUri, uri) && mWidth == width && mHeight == height; } @Override public String toString() { - return "ThumbnailRequest{" + - "uri=" + uri + - ", width=" + width + - ", height=" + height + - '}'; + final StringBuilder sb = new StringBuilder("ThumbnailRequest{"); + sb.append("uri=").append(mUri); + sb.append(", width=").append(mWidth); + sb.append(", height=").append(mHeight); + sb.append(", seq=").append(mSeq); + sb.append('}'); + return sb.toString(); + } + + /** + * Gets an unmodifiable view of the list of callbacks associated with the request. + */ + public List getCallbacks() { + return Collections.unmodifiableList(mCallbacks); } } @@ -822,11 +843,10 @@ public final class MediaBrowser { } @Override - public void onLoadThumbnail(final Uri uri, int width, int height, final Bitmap bitmap) { + public void onLoadThumbnail(final int seqNum, final Bitmap bitmap) { MediaBrowser mediaBrowser = mMediaBrowser.get(); if (mediaBrowser != null) { - ThumbnailRequest request = new ThumbnailRequest(uri, width, height); - mediaBrowser.onLoadThumbnail(this, request, bitmap); + mediaBrowser.onLoadThumbnail(this, seqNum, bitmap); } } } diff --git a/media/java/android/media/browse/MediaBrowserService.java b/media/java/android/media/browse/MediaBrowserService.java index 2d4bb7830aa6..ffbaeddcb3fd 100644 --- a/media/java/android/media/browse/MediaBrowserService.java +++ b/media/java/android/media/browse/MediaBrowserService.java @@ -266,7 +266,7 @@ public abstract class MediaBrowserService extends Service { } @Override - public void loadThumbnail(final Uri uri, final int width, final int height, + public void loadThumbnail(final int seq, final Uri uri, final int width, final int height, final IMediaBrowserServiceCallbacks callbacks) { if (uri == null) { throw new IllegalStateException("loadThumbnail sent null list for uri " + uri); @@ -299,7 +299,7 @@ public abstract class MediaBrowserService extends Service { } try { - callbacks.onLoadThumbnail(uri, width, height, bitmap); + callbacks.onLoadThumbnail(seq, bitmap); } catch (RemoteException e) { // The other side is in the process of crashing. Log.w(TAG, "RemoteException in calling onLoadThumbnail", e); -- 2.11.0