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

Commit 66df850d authored by RoboErik's avatar RoboErik Committed by Android (Google) Code Review
Browse files

Merge "Add getMediaItem API to MediaBrowser"

parents 25af2fc0 b1c88103
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -16217,6 +16217,7 @@ package android.media.browse {
    method public void connect();
    method public void disconnect();
    method public android.os.Bundle getExtras();
    method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
    method public java.lang.String getRoot();
    method public android.content.ComponentName getServiceComponent();
    method public android.media.session.MediaSession.Token getSessionToken();
@@ -16246,6 +16247,12 @@ package android.media.browse {
    field public static final int FLAG_PLAYABLE = 2; // 0x2
  }
  public static abstract class MediaBrowser.MediaItemCallback {
    ctor public MediaBrowser.MediaItemCallback();
    method public void onError();
    method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
  }
  public static abstract class MediaBrowser.SubscriptionCallback {
    ctor public MediaBrowser.SubscriptionCallback();
    method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -27360,6 +27367,7 @@ package android.service.media {
  public abstract class MediaBrowserService extends android.app.Service {
    ctor public MediaBrowserService();
    method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
    method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
    method public android.media.session.MediaSession.Token getSessionToken();
    method public void notifyChildrenChanged(java.lang.String);
    method public android.os.IBinder onBind(android.content.Intent);
+78 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.service.media.MediaBrowserService;
import android.service.media.IMediaBrowserService;
import android.service.media.IMediaBrowserServiceCallbacks;
@@ -347,8 +348,8 @@ public final class MediaBrowser {
     */
    public void unsubscribe(@NonNull String parentId) {
        // Check arguments.
        if (parentId == null) {
            throw new IllegalArgumentException("parentId is null");
        if (TextUtils.isEmpty(parentId)) {
            throw new IllegalArgumentException("parentId is empty.");
        }

        // Remove from our list.
@@ -366,6 +367,60 @@ public final class MediaBrowser {
        }
    }

    /**
     * Retrieves a specific {@link MediaItem} from the connected service. Not
     * all services may support this, so falling back to subscribing to the
     * parent's id should be used when unavailable.
     *
     * @param mediaId The id of the item to retrieve.
     * @param cb The callback to receive the result on.
     */
    public void getMediaItem(@NonNull String mediaId, @NonNull final MediaItemCallback cb) {
        if (TextUtils.isEmpty(mediaId)) {
            throw new IllegalArgumentException("mediaId is empty.");
        }
        if (cb == null) {
            throw new IllegalArgumentException("cb is null.");
        }
        if (mState != CONNECT_STATE_CONNECTED) {
            Log.i(TAG, "Not connected, unable to retrieve the MediaItem.");
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    cb.onError();
                }
            });
            return;
        }
        ResultReceiver receiver = new ResultReceiver(mHandler) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                if (resultCode != 0 || resultData == null
                        || !resultData.containsKey(MediaBrowserService.KEY_MEDIA_ITEM)) {
                    cb.onError();
                    return;
                }
                Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
                if (!(item instanceof MediaItem)) {
                    cb.onError();
                }
                cb.onMediaItemLoaded((MediaItem) resultData.getParcelable(
                        MediaBrowserService.KEY_MEDIA_ITEM));
            }
        };
        try {
            mServiceBinder.getMediaItem(mediaId, receiver);
        } catch (RemoteException e) {
            Log.i(TAG, "Remote error getting media item.");
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    cb.onError();
                }
            });
        }
    }

    /**
     * For debugging.
     */
@@ -689,6 +744,27 @@ public final class MediaBrowser {
        }
    }

    /**
     * Callback for receiving the result of {@link #getMediaItem}.
     */
    public static abstract class MediaItemCallback {

        /**
         * Called when the item has been returned by the browser service.
         *
         * @param item The item that was returned or null if it doesn't exist.
         */
        public void onMediaItemLoaded(MediaItem item) {
        }

        /**
         * Called when the id doesn't exist or there was an error retrieving the
         * item.
         */
        public void onError() {
        }
    }

    /**
     * ServiceConnection to the other app.
     */
+2 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import android.content.res.Configuration;
import android.service.media.IMediaBrowserServiceCallbacks;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;

/**
 * Media API allows clients to browse through hierarchy of a user’s media collection,
@@ -18,4 +19,5 @@ oneway interface IMediaBrowserService {

    void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
    void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
    void getMediaItem(String uri, in ResultReceiver cb);
}
 No newline at end of file
+83 −19
Original line number Diff line number Diff line
@@ -32,8 +32,10 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.service.media.IMediaBrowserService;
import android.service.media.IMediaBrowserServiceCallbacks;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;

@@ -74,6 +76,13 @@ public abstract class MediaBrowserService extends Service {
    @SdkConstant(SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";

    /**
     * A key for passing the MediaItem to the ResultReceiver in getMediaItem.
     *
     * @hide
     */
    public static final String KEY_MEDIA_ITEM = "media_item";

    private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
    private final Handler mHandler = new Handler();
    private ServiceBinder mBinder;
@@ -261,6 +270,33 @@ public abstract class MediaBrowserService extends Service {
                }
            });
        }

        @Override
        public void getMediaItem(final String mediaId, final ResultReceiver receiver) {
            if (TextUtils.isEmpty(mediaId) || receiver == null) {
                return;
            }

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    final Result<MediaBrowser.MediaItem> result
                            = new Result<MediaBrowser.MediaItem>(mediaId) {
                        @Override
                        void onResultSent(MediaBrowser.MediaItem item) {
                            Bundle bundle = new Bundle();
                            bundle.putParcelable(KEY_MEDIA_ITEM, item);
                            receiver.send(0, bundle);
                        }
                    };
                    try {
                        MediaBrowserService.this.getMediaItem(mediaId, result);
                    } catch (UnsupportedOperationException e) {
                        receiver.send(-1, null);
                    }
                }
            });
        }
    }

    @Override
@@ -284,20 +320,21 @@ public abstract class MediaBrowserService extends Service {
    /**
     * Called to get the root information for browsing by a particular client.
     * <p>
     * The implementation should verify that the client package has
     * permission to access browse media information before returning
     * the root id; it should return null if the client is not
     * allowed to access this information.
     * The implementation should verify that the client package has permission
     * to access browse media information before returning the root id; it
     * should return null if the client is not allowed to access this
     * information.
     * </p>
     *
     * @param clientPackageName The package name of the application
     * which is requesting access to browse media.
     * @param clientUid The uid of the application which is requesting
     * access to browse media.
     * @param clientPackageName The package name of the application which is
     *            requesting access to browse media.
     * @param clientUid The uid of the application which is requesting access to
     *            browse media.
     * @param rootHints An optional bundle of service-specific arguments to send
     * to the media browse service when connecting and retrieving the root id
     * for browsing, or null if none.  The contents of this bundle may affect
     * the information returned when browsing.
     *            to the media browse service when connecting and retrieving the
     *            root id for browsing, or null if none. The contents of this
     *            bundle may affect the information returned when browsing.
     * @return The {@link BrowserRoot} for accessing this app's content or null.
     */
    public abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
            int clientUid, @Nullable Bundle rootHints);
@@ -305,24 +342,51 @@ public abstract class MediaBrowserService extends Service {
    /**
     * Called to get information about the children of a media item.
     * <p>
     * Implementations must call result.{@link Result#sendResult result.sendResult} with the list
     * of children. If loading the children will be an expensive operation that should be performed
     * on another thread, result.{@link Result#detach result.detach} may be called before returning
     * from this function, and then {@link Result#sendResult result.sendResult} called when
     * the loading is complete.
     * Implementations must call {@link Result#sendResult result.sendResult}
     * with the list of children. If loading the children will be an expensive
     * operation that should be performed on another thread,
     * {@link Result#detach result.detach} may be called before returning from
     * this function, and then {@link Result#sendResult result.sendResult}
     * called when the loading is complete.
     *
     * @param parentId The id of the parent media item whose
     * children are to be queried.
     * @return The list of children, or null if the id is invalid.
     * @param parentId The id of the parent media item whose children are to be
     *            queried.
     * @param result The Result to send the list of children to, or null if the
     *            id is invalid.
     */
    public abstract void onLoadChildren(@NonNull String parentId,
            @NonNull Result<List<MediaBrowser.MediaItem>> result);

    /**
     * Called to get a specific media item. The mediaId should be the same id
     * that would be returned for this item when it is in a list of child items.
     * <p>
     * Implementations must call {@link Result#sendResult result.sendResult}. If
     * loading the item will be an expensive operation {@link Result#detach
     * result.detach} may be called before returning from this function, and
     * then {@link Result#sendResult result.sendResult} called when the item has
     * been loaded.
     * <p>
     * The default implementation throws an exception.
     *
     * @param mediaId The id for the specific
     *            {@link android.media.browse.MediaBrowser.MediaItem}.
     * @param result The Result to send the item to, or null if the id is
     *            invalid.
     * @throws UnsupportedOperationException
     */
    public void getMediaItem(String mediaId, Result<MediaBrowser.MediaItem> result)
            throws UnsupportedOperationException {
        throw new UnsupportedOperationException("getMediaItem is not supported.");
    }

    /**
     * Call to set the media session.
     * <p>
     * This should be called as soon as possible during the service's startup.
     * It may only be called once.
     *
     * @param token The token for the service's {@link MediaSession}.
     */
    public void setSessionToken(final MediaSession.Token token) {
        if (token == null) {