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

Commit 899715b9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topics "mediasession2_libraryroot",...

Merge changes from topics "mediasession2_libraryroot", "mediasession2_commandbutton", "medianotification_updatable"

* changes:
  MediaSession2: Rename BrowserRoot to LibraryRoot and move to updatable
  MediaSession2: Move MediaSession2.CommandButton to updatable
  MediaSession2: Move MediaSessionService2.MediaNotification to updatable
parents 4aa09f4c ac9edc37
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package android.media;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaBrowser2Provider;
@@ -41,14 +40,14 @@ public class MediaBrowser2 extends MediaController2 {
     */
    public static class BrowserCallback extends MediaController2.ControllerCallback {
        /**
         * Called with the result of {@link #getBrowserRoot(Bundle)}.
         * Called with the result of {@link #getLibraryRoot(Bundle)}.
         * <p>
         * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the browser root isn't
         * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the library root isn't
         * available.
         *
         * @param rootHints rootHints that you previously requested.
         * @param rootMediaId media id of the browser root. Can be {@code null}
         * @param rootExtra extra of the browser root. Can be {@code null}
         * @param rootMediaId media id of the library root. Can be {@code null}
         * @param rootExtra extra of the library root. Can be {@code null}
         */
        public void onGetRootResult(Bundle rootHints, @Nullable String rootMediaId,
                @Nullable Bundle rootExtra) { }
@@ -114,8 +113,15 @@ public class MediaBrowser2 extends MediaController2 {
                .createMediaBrowser2(context, this, token, executor, (BrowserCallback) callback);
    }

    public void getBrowserRoot(Bundle rootHints) {
        mProvider.getBrowserRoot_impl(rootHints);
    /**
     * Get the library root. Result would be sent back asynchronously with the
     * {@link BrowserCallback#onGetRootResult(Bundle, String, Bundle)}.
     *
     * @param rootHints hint for the root
     * @see BrowserCallback#onGetRootResult(Bundle, String, Bundle)
     */
    public void getLibraryRoot(Bundle rootHints) {
        mProvider.getLibraryRoot_impl(rootHints);
    }

    /**
+33 −36
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.Context;
import android.media.MediaSession2.BuilderBase;
import android.media.MediaSession2.ControllerInfo;
import android.media.update.ApiLoader;
import android.media.update.MediaLibraryService2Provider.LibraryRootProvider;
import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
import android.media.update.MediaSession2Provider;
import android.media.update.MediaSessionService2Provider;
@@ -116,15 +117,15 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 {
         *
         * @param controllerInfo information of the controller requesting access to browse media.
         * @param rootHints An optional bundle of service-specific arguments to send
         * to the media browser service when connecting and retrieving the
         * to the media library 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.
         * @see BrowserRoot#EXTRA_RECENT
         * @see BrowserRoot#EXTRA_OFFLINE
         * @see BrowserRoot#EXTRA_SUGGESTED
         * @return The {@link LibraryRoot} for accessing this app's content or null.
         * @see LibraryRoot#EXTRA_RECENT
         * @see LibraryRoot#EXTRA_OFFLINE
         * @see LibraryRoot#EXTRA_SUGGESTED
         */
        public @Nullable BrowserRoot onGetRoot(@NonNull ControllerInfo controllerInfo,
        public @Nullable LibraryRoot onGetRoot(@NonNull ControllerInfo controllerInfo,
                @Nullable Bundle rootHints) {
            return null;
        }
@@ -237,17 +238,17 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 {
    public @NonNull abstract MediaLibrarySession onCreateSession(String sessionId);

    /**
     * Contains information that the browser service needs to send to the client
     * when first connected.
     * Contains information that the library service needs to send to the client when
     * {@link MediaBrowser2#getLibraryRoot(Bundle)} is called.
     */
    public static final class BrowserRoot {
    public static final class LibraryRoot {
        /**
         * The lookup key for a boolean that indicates whether the browser service should return a
         * browser root for recently played media items.
         * The lookup key for a boolean that indicates whether the library service should return a
         * librar root for recently played media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * <p>When creating a media browser for a given media library service, this key can be
         * supplied as a root hint for retrieving media items that are recently played.
         * If the media browser service can provide such media items, the implementation must return
         * If the media library service can provide such media items, the implementation must return
         * the key in the root hint when
         * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back.
         *
@@ -259,13 +260,13 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 {
        public static final String EXTRA_RECENT = "android.media.extra.RECENT";

        /**
         * The lookup key for a boolean that indicates whether the browser service should return a
         * browser root for offline media items.
         * The lookup key for a boolean that indicates whether the library service should return a
         * library root for offline media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * <p>When creating a media browser for a given media library service, this key can be
         * supplied as a root hint for retrieving media items that are can be played without an
         * internet connection.
         * If the media browser service can provide such media items, the implementation must return
         * If the media library service can provide such media items, the implementation must return
         * the key in the root hint when
         * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back.
         *
@@ -277,14 +278,14 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 {
        public static final String EXTRA_OFFLINE = "android.media.extra.OFFLINE";

        /**
         * The lookup key for a boolean that indicates whether the browser service should return a
         * browser root for suggested media items.
         * The lookup key for a boolean that indicates whether the library service should return a
         * library root for suggested media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * supplied as a root hint for retrieving the media items suggested by the media browser
         * <p>When creating a media browser for a given media library service, this key can be
         * supplied as a root hint for retrieving the media items suggested by the media library
         * service. The list of media items is considered ordered by relevance, first being the top
         * suggestion.
         * If the media browser service can provide such media items, the implementation must return
         * If the media library service can provide such media items, the implementation must return
         * the key in the root hint when
         * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back.
         *
@@ -295,35 +296,31 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 {
         */
        public static final String EXTRA_SUGGESTED = "android.media.extra.SUGGESTED";

        final private String mRootId;
        final private Bundle mExtras;
        private final LibraryRootProvider mProvider;

        /**
         * Constructs a browser root.
         * Constructs a library root.
         * @param rootId The root id for browsing.
         * @param extras Any extras about the browser service.
         * @param extras Any extras about the library service.
         */
        public BrowserRoot(@NonNull String rootId, @Nullable Bundle extras) {
            if (rootId == null) {
                throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " +
                        "Use null for BrowserRoot instead.");
            }
            mRootId = rootId;
            mExtras = extras;
        public LibraryRoot(@NonNull Context context,
                @NonNull String rootId, @Nullable Bundle extras) {
            mProvider = ApiLoader.getProvider(context).createMediaLibraryService2LibraryRoot(
                    context, this, rootId, extras);
        }

        /**
         * Gets the root id for browsing.
         */
        public String getRootId() {
            return mRootId;
            return mProvider.getRootId_impl();
        }

        /**
         * Gets any extras about the browser service.
         * Gets any extras about the library service.
         */
        public Bundle getExtras() {
            return mExtras;
            return mProvider.getExtras_impl();
        }
    }
}
+28 −86
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.media.session.PlaybackState;
import android.media.update.ApiLoader;
import android.media.update.MediaSession2Provider;
import android.media.update.MediaSession2Provider.BuilderBaseProvider;
import android.media.update.MediaSession2Provider.CommandButtonProvider;
import android.media.update.MediaSession2Provider.CommandGroupProvider;
import android.media.update.MediaSession2Provider.CommandProvider;
import android.media.update.MediaSession2Provider.ControllerInfoProvider;
@@ -768,32 +769,15 @@ public class MediaSession2 implements AutoCloseable {
     * <p>
     * It's up to the controller's decision to respect or ignore this customization request.
     */
    // TODO(jaewan): Move this to updatable.
    public static class CommandButton {
        private static final String KEY_COMMAND
                = "android.media.media_session2.command_button.command";
        private static final String KEY_ICON_RES_ID
                = "android.media.media_session2.command_button.icon_res_id";
        private static final String KEY_DISPLAY_NAME
                = "android.media.media_session2.command_button.display_name";
        private static final String KEY_EXTRA
                = "android.media.media_session2.command_button.extra";
        private static final String KEY_ENABLED
                = "android.media.media_session2.command_button.enabled";

        private Command mCommand;
        private int mIconResId;
        private String mDisplayName;
        private Bundle mExtra;
        private boolean mEnabled;

        private CommandButton(@Nullable Command command, int iconResId,
                @Nullable String displayName, Bundle extra, boolean enabled) {
            mCommand = command;
            mIconResId = iconResId;
            mDisplayName = displayName;
            mExtra = extra;
            mEnabled = enabled;
        private final CommandButtonProvider mProvider;

        /**
         * @hide
         */
        @SystemApi
        public CommandButton(CommandButtonProvider provider) {
            mProvider = provider;
        }

        /**
@@ -803,7 +787,7 @@ public class MediaSession2 implements AutoCloseable {
         * @return command or {@code null}
         */
        public @Nullable Command getCommand() {
            return mCommand;
            return mProvider.getCommand_impl();
        }

        /**
@@ -813,7 +797,7 @@ public class MediaSession2 implements AutoCloseable {
         * @return resource id of the icon. Can be {@code 0}.
         */
        public int getIconResId() {
            return mIconResId;
            return mProvider.getIconResId_impl();
        }

        /**
@@ -823,7 +807,7 @@ public class MediaSession2 implements AutoCloseable {
         * @return custom display name. Can be {@code null} or empty.
         */
        public @Nullable String getDisplayName() {
            return mDisplayName;
            return mProvider.getDisplayName_impl();
        }

        /**
@@ -832,7 +816,7 @@ public class MediaSession2 implements AutoCloseable {
         * @return
         */
        public @Nullable Bundle getExtra() {
            return mExtra;
            return mProvider.getExtra_impl();
        }

        /**
@@ -841,92 +825,50 @@ public class MediaSession2 implements AutoCloseable {
         * @return {@code true} if enabled. {@code false} otherwise.
         */
        public boolean isEnabled() {
            return mEnabled;
            return mProvider.isEnabled_impl();
        }

        /**
         * @hide
         */
        // TODO(jaewan): @SystemApi
        public @NonNull Bundle toBundle() {
            Bundle bundle = new Bundle();
            bundle.putBundle(KEY_COMMAND, mCommand.toBundle());
            bundle.putInt(KEY_ICON_RES_ID, mIconResId);
            bundle.putString(KEY_DISPLAY_NAME, mDisplayName);
            bundle.putBundle(KEY_EXTRA, mExtra);
            bundle.putBoolean(KEY_ENABLED, mEnabled);
            return bundle;
        }

        /**
         * @hide
         */
        // TODO(jaewan): @SystemApi
        public static @Nullable CommandButton fromBundle(Context context, Bundle bundle) {
            Builder builder = new Builder();
            builder.setCommand(Command.fromBundle(context, bundle.getBundle(KEY_COMMAND)));
            builder.setIconResId(bundle.getInt(KEY_ICON_RES_ID, 0));
            builder.setDisplayName(bundle.getString(KEY_DISPLAY_NAME));
            builder.setExtra(bundle.getBundle(KEY_EXTRA));
            builder.setEnabled(bundle.getBoolean(KEY_ENABLED));
            try {
                return builder.build();
            } catch (IllegalStateException e) {
                // Malformed or version mismatch. Return null for now.
                return null;
            }
        @SystemApi
        public CommandButtonProvider getProvider() {
            return mProvider;
        }

        /**
         * Builder for {@link CommandButton}.
         */
        public static class Builder {
            private Command mCommand;
            private int mIconResId;
            private String mDisplayName;
            private Bundle mExtra;
            private boolean mEnabled;
            private final CommandButtonProvider.BuilderProvider mProvider;

            public Builder() {
                mEnabled = true;
            public Builder(@NonNull Context context) {
                mProvider = ApiLoader.getProvider(context)
                        .createMediaSession2CommandButtonBuilder(context, this);
            }

            public Builder setCommand(Command command) {
                mCommand = command;
                return this;
                return mProvider.setCommand_impl(command);
            }

            public Builder setIconResId(int resId) {
                mIconResId = resId;
                return this;
                return mProvider.setIconResId_impl(resId);
            }

            public Builder setDisplayName(String displayName) {
                mDisplayName = displayName;
                return this;
                return mProvider.setDisplayName_impl(displayName);
            }

            public Builder setEnabled(boolean enabled) {
                mEnabled = enabled;
                return this;
                return mProvider.setEnabled_impl(enabled);
            }

            public Builder setExtra(Bundle extra) {
                mExtra = extra;
                return this;
                return mProvider.setExtra_impl(extra);
            }

            public CommandButton build() {
                if (mEnabled && mCommand == null) {
                    throw new IllegalStateException("Enabled button needs Command"
                            + " for controller to invoke the command");
                }
                if (mCommand != null && mCommand.getCommandCode() == COMMAND_CODE_CUSTOM
                        && (mIconResId == 0 || TextUtils.isEmpty(mDisplayName))) {
                    throw new IllegalStateException("Custom commands needs icon and"
                            + " and name to display");
                }
                return new CommandButton(mCommand, mIconResId, mDisplayName, mExtra, mEnabled);
                return mProvider.build_impl();
            }
        }
    }
+18 −17
Original line number Diff line number Diff line
@@ -21,10 +21,12 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaSession2.ControllerInfo;
import android.media.update.ApiLoader;
import android.media.update.MediaSessionService2Provider;
import android.media.update.MediaSessionService2Provider.MediaNotificationProvider;
import android.os.IBinder;

/**
@@ -165,7 +167,6 @@ public abstract class MediaSessionService2 extends Service {
     * @param state playback state
     * @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown.
     */
    // TODO(jaewan): Also add metadata
    public MediaNotification onUpdateNotification(PlaybackState2 state) {
        return mProvider.onUpdateNotification_impl(state);
    }
@@ -204,31 +205,31 @@ public abstract class MediaSessionService2 extends Service {
     * foreground service to keep playback running in the background. It's highly recommended to
     * show media style notification here.
     */
    // TODO(jaewan): Should we also move this to updatable?
    public static class MediaNotification {
        public final int id;
        public final Notification notification;

        private MediaNotification(int id, @NonNull Notification notification) {
            this.id = id;
            this.notification = notification;
        }
        private final MediaNotificationProvider mProvider;

        /**
         * Create a {@link MediaNotification}.
         * Default constructor
         *
         * @param context context
         * @param notificationId notification id to be used for
         *      {@link android.app.NotificationManager#notify(int, Notification)}.
         * @param notification a notification to make session service foreground service. Media
         *      style notification is recommended here.
         * @return
         */
        public static MediaNotification create(int notificationId,
                @NonNull Notification notification) {
            if (notification == null) {
                throw new IllegalArgumentException("Notification cannot be null");
        public MediaNotification(@NonNull Context context,
                int notificationId, @NonNull Notification notification) {
            mProvider = ApiLoader.getProvider(context)
                    .createMediaSessionService2MediaNotification(
                            context, this, notificationId, notification);
        }
            return new MediaNotification(notificationId, notification);

        public int getNotificationId() {
            return mProvider.getNotificationId_impl();
        }

        public Notification getNotification() {
            return mProvider.getNotification_impl();
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import android.os.Bundle;
 * @hide
 */
public interface MediaBrowser2Provider extends MediaController2Provider {
    void getBrowserRoot_impl(Bundle rootHints);
    void getLibraryRoot_impl(Bundle rootHints);

    void subscribe_impl(String parentId, Bundle options);
    void unsubscribe_impl(String parentId, Bundle options);
Loading