Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b569a583 authored by Yao Chen's avatar Yao Chen Committed by Android Git Automerger
Browse files

am 5d35986f: Merge "Add thumbnail related api." into lmp-dev

* commit '5d35986f734b4b87c8d3b1005b8440ec00a31223':
  Add thumbnail related api.
parents 05b6d041 10e62cb2
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -16164,10 +16164,11 @@ package android.media.browse {
    ctor public MediaBrowser(android.content.Context, android.content.ComponentName, android.media.browse.MediaBrowser.ConnectionCallback, android.os.Bundle);
    method public void connect();
    method public void disconnect();
    method public android.os.Bundle getExtras();
    method public android.net.Uri getRoot();
    method public android.media.session.MediaSession.Token getSessionToken();
    method public boolean isConnected();
    method public void loadThumbnail(android.net.Uri, int, int, int, android.media.browse.MediaBrowser.ThumbnailCallback);
    method public void loadThumbnail(android.net.Uri, int, int, android.media.browse.MediaBrowser.ThumbnailCallback);
    method public void subscribe(android.net.Uri, android.media.browse.MediaBrowser.SubscriptionCallback);
    method public void unsubscribe(android.net.Uri);
  }
@@ -16195,6 +16196,8 @@ package android.media.browse {
    method public int describeContents();
    method public android.os.Bundle getExtras();
    method public int getFlags();
    method public int getIconResId();
    method public android.net.Uri getIconUri();
    method public java.lang.CharSequence getSummary();
    method public java.lang.CharSequence getTitle();
    method public android.net.Uri getUri();
@@ -16210,6 +16213,8 @@ package android.media.browse {
    ctor public MediaBrowserItem.Builder(android.net.Uri, int, java.lang.CharSequence);
    method public android.media.browse.MediaBrowserItem build();
    method public android.media.browse.MediaBrowserItem.Builder setExtras(android.os.Bundle);
    method public android.media.browse.MediaBrowserItem.Builder setIconResId(int);
    method public android.media.browse.MediaBrowserItem.Builder setIconUri(android.net.Uri);
    method public android.media.browse.MediaBrowserItem.Builder setSummary(java.lang.CharSequence);
  }
@@ -16217,16 +16222,19 @@ package android.media.browse {
    ctor public MediaBrowserService();
    method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
    method public android.media.session.MediaSession.Token getSessionToken();
    method public void notifyChange();
    method public void notifyChildrenChanged(android.net.Uri);
    method public android.os.IBinder onBind(android.content.Intent);
    method public abstract android.net.Uri onGetRoot(java.lang.String, int, android.os.Bundle);
    method public abstract android.graphics.Bitmap onGetThumbnail(android.net.Uri, int, int, int);
    method public abstract java.util.List<android.media.browse.MediaBrowserItem> onLoadChildren(android.net.Uri);
    method protected abstract android.media.browse.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
    method protected abstract android.graphics.Bitmap onGetThumbnail(android.net.Uri, int, int);
    method protected abstract java.util.List<android.media.browse.MediaBrowserItem> onLoadChildren(android.net.Uri);
    method public void setSessionToken(android.media.session.MediaSession.Token);
    field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
  }
  public static class MediaBrowserService.BrowserRoot {
    ctor public MediaBrowserService.BrowserRoot(android.net.Uri, android.os.Bundle);
  }
}
package android.media.effect {
+2 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

package android.media.browse;

import android.content.res.Configuration;
import android.media.browse.IMediaBrowserServiceCallbacks;
import android.net.Uri;
import android.os.Bundle;
@@ -17,4 +18,5 @@ 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);
}
 No newline at end of file
+6 −2
Original line number Diff line number Diff line
@@ -3,8 +3,10 @@
package android.media.browse;

import android.content.pm.ParceledListSlice;
import android.graphics.Bitmap;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Bundle;

/**
 * Media API allows clients to browse through hierarchy of a user’s media collection,
@@ -17,8 +19,10 @@ oneway interface IMediaBrowserServiceCallbacks {
     * @param root The root Uri for browsing.
     * @param session The {@link MediaSession.Token media session token} that can be used to control
     *         the playback of the media app.
     * @param extra Extras returned by the media service.
     */
    void onConnect(in Uri root, in MediaSession.Token session);
    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);
}
+151 −13
Original line number Diff line number Diff line
@@ -17,11 +17,13 @@
package android.media.browse;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.media.session.MediaSession;
import android.net.Uri;
@@ -36,7 +38,9 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Browses media content offered by a link MediaBrowserService.
@@ -61,6 +65,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 int mState = CONNECT_STATE_DISCONNECTED;
    private MediaServiceConnection mServiceConnection;
@@ -68,6 +74,7 @@ public final class MediaBrowser {
    private IMediaBrowserServiceCallbacks mServiceCallbacks;
    private Uri mRootUri;
    private MediaSession.Token mMediaSessionToken;
    private Bundle mExtras;

    /**
     * Creates a media browser for the specified media browse service.
@@ -162,7 +169,6 @@ public final class MediaBrowser {

    /**
     * Disconnects from the media browse service.
     * @more
     * After this, no more callbacks will be received.
     */
    public void disconnect() {
@@ -232,6 +238,19 @@ public final class MediaBrowser {
        return mRootUri;
    }

    /**
     * Gets any extras for the media service.
     *
     * @throws IllegalStateException if not connected.
     */
    public @Nullable Bundle getExtras() {
        if (mState != CONNECT_STATE_CONNECTED) {
            throw new IllegalStateException("getExtras() called while not connected (state="
                    + getStateLabel(mState) + ")");
        }
        return mExtras;
    }

    /**
     * Gets the media session token associated with the media browser.
     * <p>
@@ -332,18 +351,45 @@ public final class MediaBrowser {
    /**
     * Loads the thumbnail of a media item.
     *
     * @param uri The uri of the media item.
     * @param uri The uri of the thumbnail.
     * @param width The preferred width of the icon in dp.
     * @param height The preferred width of the icon in dp.
     * @param density The preferred density of the icon. Must be one of the android
     *      density buckets.
     * @param callback The callback to receive the thumbnail.
     *
     * @throws IllegalStateException if not connected. TODO: Is this restriction necessary?
     */
    public void loadThumbnail(@NonNull Uri uri, int width, int height, int density,
            @NonNull ThumbnailCallback callback) {
        throw new RuntimeException("implement me");
    public void loadThumbnail(final @NonNull Uri uri, final int width, final int height,
            final @NonNull ThumbnailCallback callback) {
        if (uri == null) {
            throw new IllegalArgumentException("thumbnail uri cannot be null");
        }
        if (callback == null) {
            throw new IllegalArgumentException("thumbnail callback cannot be null");
        }
        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.
                    return;
                }
                callbackSet = new HashSet<ThumbnailCallback>();
                callbackSet.add(callback);
                mThumbnailCallbacks.put(request, callbackSet);
                if (mState == CONNECT_STATE_CONNECTED) {
                    try {
                        mServiceBinder.loadThumbnail(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.
                        Log.d(TAG, "loadThumbnail failed with RemoteException uri=" + uri);
                    }
                }
            }
        });
    }

    /**
@@ -365,7 +411,7 @@ public final class MediaBrowser {
    }

    private final void onServiceConnected(final IMediaBrowserServiceCallbacks callback,
            final Uri root, final MediaSession.Token session) {
            final Uri root, final MediaSession.Token session, final Bundle extra) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
@@ -382,6 +428,7 @@ public final class MediaBrowser {
                }
                mRootUri = root;
                mMediaSessionToken = session;
                mExtras = extra;
                mState = CONNECT_STATE_CONNECTED;

                if (DBG) {
@@ -402,6 +449,17 @@ public final class MediaBrowser {
                    }
                }

                for (ThumbnailRequest request : mThumbnailCallbacks.keySet()) {
                    try {
                        mServiceBinder.loadThumbnail(request.uri, request.width, request.height,
                                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);
                    }
                }

            }
        });
    }
@@ -468,6 +526,31 @@ public final class MediaBrowser {
        });
    }

    private final void onLoadThumbnail(final IMediaBrowserServiceCallbacks callback,
            final ThumbnailRequest request, final Bitmap bitmap) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // Check that there hasn't been a disconnect or a different
                // ServiceConnection.
                if (!isCurrent(callback, "onLoadThumbnail")) {
                    return;
                }

                Set<ThumbnailCallback> callbackSet = mThumbnailCallbacks.get(request);
                if (callbackSet == null) {
                    Log.d(TAG, "onLoadThumbnail called for request=" + request +
                            " but the callback is not registered");
                    return;
                }
                for (ThumbnailCallback thumbnailCallback : callbackSet) {
                    thumbnailCallback.onThumbnailLoaded(request.uri, bitmap);
                }
                mThumbnailCallbacks.remove(request);
            }
        });
    }


    /**
     * Return true if {@code callback} is the current ServiceCallbacks.  Also logs if it's not.
@@ -567,6 +650,51 @@ public final class MediaBrowser {
        }
    }

    private static class ThumbnailRequest {
        Uri uri;
        int width;
        int height;
        ThumbnailRequest(@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;
        }

        @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;
        }

        @Override
        public int hashCode() {
            int result = uri.hashCode();
            result = 31 * result + width;
            result = 31 * result + height;
            return result;
        }

        @Override
        public String toString() {
            return "ThumbnailRequest{" +
                    "uri=" + uri +
                    ", width=" + width +
                    ", height=" + height +
                    '}';
        }
    }

    /**
     * ServiceConnection to the other app.
     */
@@ -666,10 +794,11 @@ public final class MediaBrowser {
         * are the initial data as requested.
         */
        @Override
        public void onConnect(final Uri root, final MediaSession.Token session) {
        public void onConnect(final Uri root, final MediaSession.Token session,
                final Bundle extras) {
            MediaBrowser mediaBrowser = mMediaBrowser.get();
            if (mediaBrowser != null) {
                mediaBrowser.onServiceConnected(this, root, session);
                mediaBrowser.onServiceConnected(this, root, session, extras);
            }
        }

@@ -691,6 +820,15 @@ public final class MediaBrowser {
                mediaBrowser.onLoadChildren(this, uri, list);
            }
        }

        @Override
        public void onLoadThumbnail(final Uri uri, int width, int height, final Bitmap bitmap) {
            MediaBrowser mediaBrowser = mMediaBrowser.get();
            if (mediaBrowser != null) {
                ThumbnailRequest request = new ThumbnailRequest(uri, width, height);
                mediaBrowser.onLoadThumbnail(this, request, bitmap);
            }
        }
    }

    private static class Subscription {
+48 −3
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ import java.lang.annotation.RetentionPolicy;
 */
public final class MediaBrowserItem implements Parcelable {
    private final Uri mUri;
    private final Uri mIconUri;
    private final int mIconResId;
    private final int mFlags;
    private final CharSequence mTitle;
    private final CharSequence mSummary;
@@ -59,8 +61,8 @@ public final class MediaBrowserItem implements Parcelable {
    /**
     * Initialize a MediaBrowserItem object.
     */
    private MediaBrowserItem(@NonNull Uri uri, int flags, @NonNull CharSequence title,
            CharSequence summary, Bundle extras) {
    private MediaBrowserItem(@NonNull Uri uri, @Nullable Uri iconUri, int iconResId, int flags,
            @NonNull CharSequence title, CharSequence summary, Bundle extras) {
        if (uri == null) {
            throw new IllegalArgumentException("uri can not be null");
        }
@@ -68,6 +70,8 @@ public final class MediaBrowserItem implements Parcelable {
            throw new IllegalArgumentException("title can not be null");
        }
        mUri = uri;
        mIconUri = iconUri;
        mIconResId = iconResId;
        mFlags = flags;
        mTitle = title;
        mSummary = summary;
@@ -79,6 +83,8 @@ public final class MediaBrowserItem implements Parcelable {
     */
    private MediaBrowserItem(Parcel in) {
        mUri = Uri.CREATOR.createFromParcel(in);
        mIconUri = Uri.CREATOR.createFromParcel(in);
        mIconResId = in.readInt();
        mFlags = in.readInt();
        mTitle = in.readCharSequence();
        if (in.readInt() != 0) {
@@ -101,6 +107,8 @@ public final class MediaBrowserItem implements Parcelable {
    @Override
    public void writeToParcel(Parcel out, int flags) {
        mUri.writeToParcel(out, flags);
        mIconUri.writeToParcel(out, flags);
        out.writeInt(mIconResId);
        out.writeInt(mFlags);
        out.writeCharSequence(mTitle);
        if (mSummary != null) {
@@ -137,6 +145,20 @@ public final class MediaBrowserItem implements Parcelable {
        return mUri;
    }

    /**
     * Gets the Uri of the icon.
     */
    public @Nullable Uri getIconUri() {
        return mIconUri;
    }

    /**
     * Gets the resource id of the icon.
     */
    public int getIconResId() {
        return mIconResId;
    }

    /**
     * Gets the flags of the item.
     */
@@ -195,6 +217,8 @@ public final class MediaBrowserItem implements Parcelable {
        private final Uri mUri;
        private final int mFlags;
        private final CharSequence mTitle;
        private Uri mIconUri;
        private int mIconResId;
        private CharSequence mSummary;
        private Bundle mExtras;

@@ -213,6 +237,26 @@ public final class MediaBrowserItem implements Parcelable {
            mTitle = title;
        }

        /**
         * Sets the uri of the icon.
         * <p>
         * If both {@link #setIconUri(Uri)} and {@link #setIconResId(int)} are called,
         * the resource id will be used to load the icon.
         * </p>
         */
        public @NonNull Builder setIconUri(@Nullable Uri iconUri) {
            mIconUri = iconUri;
            return this;
        }

        /**
         * Sets the resource id of the icon.
         */
        public @NonNull Builder setIconResId(int resId) {
            mIconResId = resId;
            return this;
        }

        /**
         * Sets summary of the item, or null if none.
         */
@@ -234,7 +278,8 @@ public final class MediaBrowserItem implements Parcelable {
        * Builds the item.
        */
        public @NonNull MediaBrowserItem build() {
            return new MediaBrowserItem(mUri, mFlags, mTitle, mSummary, mExtras);
            return new MediaBrowserItem(mUri, mIconUri, mIconResId,
                    mFlags, mTitle, mSummary, mExtras);
        }
    }
}
Loading