Loading media/java/android/media/browse/IMediaBrowserService.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -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 media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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); } media/java/android/media/browse/MediaBrowser.java +80 −60 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; /** Loading @@ -65,8 +67,8 @@ public final class MediaBrowser { private final Handler mHandler = new Handler(); private final ArrayMap<Uri,Subscription> mSubscriptions = new ArrayMap<Uri, MediaBrowser.Subscription>(); private final ArrayMap<ThumbnailRequest, HashSet<ThumbnailCallback>> mThumbnailCallbacks = new ArrayMap<ThumbnailRequest, HashSet<ThumbnailCallback>>(); private final SparseArray<ThumbnailRequest> mThumbnailRequests = new SparseArray<ThumbnailRequest>(); private int mState = CONNECT_STATE_DISCONNECTED; private MediaServiceConnection mServiceConnection; Loading @@ -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. Loading Loading @@ -367,21 +370,20 @@ public final class MediaBrowser { mHandler.post(new Runnable() { @Override public void run() { HashSet<ThumbnailCallback> 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. 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<ThumbnailCallback>(); 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. Loading Loading @@ -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); } } } }); } Loading Loading @@ -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() { Loading @@ -537,16 +539,16 @@ public final class MediaBrowser { return; } Set<ThumbnailCallback> 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); } }); } Loading Loading @@ -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<ThumbnailCallback> 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<ThumbnailCallback>(); } @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<ThumbnailCallback> getCallbacks() { return Collections.unmodifiableList(mCallbacks); } } Loading Loading @@ -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); } } } Loading media/java/android/media/browse/MediaBrowserService.java +2 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading
media/java/android/media/browse/IMediaBrowserService.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -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
media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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); }
media/java/android/media/browse/MediaBrowser.java +80 −60 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; /** Loading @@ -65,8 +67,8 @@ public final class MediaBrowser { private final Handler mHandler = new Handler(); private final ArrayMap<Uri,Subscription> mSubscriptions = new ArrayMap<Uri, MediaBrowser.Subscription>(); private final ArrayMap<ThumbnailRequest, HashSet<ThumbnailCallback>> mThumbnailCallbacks = new ArrayMap<ThumbnailRequest, HashSet<ThumbnailCallback>>(); private final SparseArray<ThumbnailRequest> mThumbnailRequests = new SparseArray<ThumbnailRequest>(); private int mState = CONNECT_STATE_DISCONNECTED; private MediaServiceConnection mServiceConnection; Loading @@ -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. Loading Loading @@ -367,21 +370,20 @@ public final class MediaBrowser { mHandler.post(new Runnable() { @Override public void run() { HashSet<ThumbnailCallback> 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. 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<ThumbnailCallback>(); 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. Loading Loading @@ -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); } } } }); } Loading Loading @@ -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() { Loading @@ -537,16 +539,16 @@ public final class MediaBrowser { return; } Set<ThumbnailCallback> 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); } }); } Loading Loading @@ -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<ThumbnailCallback> 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<ThumbnailCallback>(); } @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<ThumbnailCallback> getCallbacks() { return Collections.unmodifiableList(mCallbacks); } } Loading Loading @@ -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); } } } Loading
media/java/android/media/browse/MediaBrowserService.java +2 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading