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

Commit 2a981a0c authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Make MediaSession2.Command updatable

Bug: 72619281
Test: build
Change-Id: I2b86b68f2d4840da76c992aac056512ac0cb2e20
parent 84f5de7e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -110,6 +110,11 @@ public abstract class MediaLibraryService2 extends MediaSessionService2 {
    }

    public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {

        public MediaLibrarySessionCallback(Context context) {
            super(context);
        }

        /**
         * Called to get the root information for browsing by a particular client.
         * <p>
+45 −68
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.media.session.MediaSession.Callback;
import android.media.session.PlaybackState;
import android.media.update.ApiLoader;
import android.media.update.MediaSession2Provider;
import android.media.update.MediaSession2Provider.CommandProvider;
import android.media.update.MediaSession2Provider.ControllerInfoProvider;
import android.net.Uri;
import android.os.Bundle;
@@ -120,43 +121,31 @@ public class MediaSession2 implements AutoCloseable {
     */
    // TODO(jaewan): Move this into the updatable.
    public static final class Command {
        private static final String KEY_COMMAND_CODE
                = "android.media.media_session2.command.command_code";
        private static final String KEY_COMMAND_CUSTOM_COMMAND
                = "android.media.media_session2.command.custom_command";
        private static final String KEY_COMMAND_EXTRA
                = "android.media.media_session2.command.extra";
        private final CommandProvider mProvider;

        private final int mCommandCode;
        // Nonnull if it's custom command
        private final String mCustomCommand;
        private final Bundle mExtra;

        public Command(int commandCode) {
            mCommandCode = commandCode;
            mCustomCommand = null;
            mExtra = null;
        public Command(@NonNull Context context, int commandCode) {
            mProvider = ApiLoader.getProvider(context)
                    .createMediaSession2Command(this, commandCode, null, null);
        }

        public Command(@NonNull String action, @Nullable Bundle extra) {
        public Command(@NonNull Context context, @NonNull String action, @Nullable Bundle extra) {
            if (action == null) {
                throw new IllegalArgumentException("action shouldn't be null");
            }
            mCommandCode = COMMAND_CODE_CUSTOM;
            mCustomCommand = action;
            mExtra = extra;
            mProvider = ApiLoader.getProvider(context)
                    .createMediaSession2Command(this, COMMAND_CODE_CUSTOM, action, extra);
        }

        public int getCommandCode() {
            return mCommandCode;
            return mProvider.getCommandCode_impl();
        }

        public @Nullable String getCustomCommand() {
            return mCustomCommand;
            return mProvider.getCustomCommand_impl();
        }

        public @Nullable Bundle getExtra() {
            return mExtra;
            return mProvider.getExtra_impl();
        }

        /**
@@ -164,28 +153,15 @@ public class MediaSession2 implements AutoCloseable {
         * @hide
         */
        public Bundle toBundle() {
            Bundle bundle = new Bundle();
            bundle.putInt(KEY_COMMAND_CODE, mCommandCode);
            bundle.putString(KEY_COMMAND_CUSTOM_COMMAND, mCustomCommand);
            bundle.putBundle(KEY_COMMAND_EXTRA, mExtra);
            return bundle;
            return mProvider.toBundle_impl();
        }

        /**
         * @return a new Command instance from the Bundle
         * @hide
         */
        public static Command fromBundle(Bundle command) {
            int code = command.getInt(KEY_COMMAND_CODE);
            if (code != COMMAND_CODE_CUSTOM) {
                return new Command(code);
            } else {
                String customCommand = command.getString(KEY_COMMAND_CUSTOM_COMMAND);
                if (customCommand == null) {
                    return null;
                }
                return new Command(customCommand, command.getBundle(KEY_COMMAND_EXTRA));
            }
        public static Command fromBundle(@NonNull Context context, Bundle command) {
            return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command);
        }

        @Override
@@ -193,18 +169,12 @@ public class MediaSession2 implements AutoCloseable {
            if (!(obj instanceof Command)) {
                return false;
            }
            Command other = (Command) obj;
            // TODO(jaewan): Should we also compare contents in bundle?
            //               It may not be possible if the bundle contains private class.
            return mCommandCode == other.mCommandCode
                    && TextUtils.equals(mCustomCommand, other.mCustomCommand);
            return mProvider.equals_impl(((Command) obj).mProvider);
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            return ((mCustomCommand != null)
                    ? mCustomCommand.hashCode() : 0) * prime + mCommandCode;
            return mProvider.hashCode_impl();
        }
    }

@@ -216,11 +186,14 @@ public class MediaSession2 implements AutoCloseable {
        private static final String KEY_COMMANDS =
                "android.media.mediasession2.commandgroup.commands";
        private ArraySet<Command> mCommands = new ArraySet<>();
        private final Context mContext;

        public CommandGroup() {
        public CommandGroup(Context context) {
            mContext = context;
        }

        public CommandGroup(CommandGroup others) {
        public CommandGroup(Context context, CommandGroup others) {
            this(context);
            mCommands.addAll(others.mCommands);
        }

@@ -230,17 +203,16 @@ public class MediaSession2 implements AutoCloseable {

        public void addAllPredefinedCommands() {
            // TODO(jaewan): Is there any better way than this?
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_START));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_PAUSE));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_STOP));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_PREPARE));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_FAST_FORWARD));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_REWIND));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SEEK_TO));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM));
            mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_START));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_PAUSE));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_STOP));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_PREPARE));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_FAST_FORWARD));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_REWIND));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SEEK_TO));
            mCommands.add(new Command(mContext, COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM));
        }

        public void removeCommand(Command command) {
@@ -281,7 +253,7 @@ public class MediaSession2 implements AutoCloseable {
         * @return new instance of CommandGroup from the bundle
         * @hide
         */
        public static @Nullable CommandGroup fromBundle(Bundle commands) {
        public static @Nullable CommandGroup fromBundle(Context context, Bundle commands) {
            if (commands == null) {
                return null;
            }
@@ -289,14 +261,14 @@ public class MediaSession2 implements AutoCloseable {
            if (list == null) {
                return null;
            }
            CommandGroup commandGroup = new CommandGroup();
            CommandGroup commandGroup = new CommandGroup(context);
            for (int i = 0; i < list.size(); i++) {
                Parcelable parcelable = list.get(i);
                if (!(parcelable instanceof Bundle)) {
                    continue;
                }
                Bundle commandBundle = (Bundle) parcelable;
                Command command = Command.fromBundle(commandBundle);
                Command command = Command.fromBundle(context, commandBundle);
                if (command != null) {
                    commandGroup.addCommand(command);
                }
@@ -313,6 +285,12 @@ public class MediaSession2 implements AutoCloseable {
     */
    // TODO(jaewan): Can we move this inside of the updatable for default implementation.
    public static class SessionCallback {
        private final Context mContext;

        public SessionCallback(Context context) {
            mContext = context;
        }

        /**
         * Called when a controller is created for this session. Return allowed commands for
         * controller. By default it allows all connection requests and commands.
@@ -325,7 +303,7 @@ public class MediaSession2 implements AutoCloseable {
         */
        // TODO(jaewan): Change return type. Once we do, null is for reject.
        public @Nullable CommandGroup onConnect(@NonNull ControllerInfo controller) {
            CommandGroup commands = new CommandGroup();
            CommandGroup commands = new CommandGroup(mContext);
            commands.addAllPredefinedCommands();
            return commands;
        }
@@ -611,7 +589,7 @@ public class MediaSession2 implements AutoCloseable {
                mCallbackExecutor = mContext.getMainExecutor();
            }
            if (mCallback == null) {
                mCallback = new SessionCallback();
                mCallback = new SessionCallback(mContext);
            }
            return new MediaSession2(mContext, mPlayer, mId, mVolumeProvider, mRatingType,
                    mSessionActivity, mCallbackExecutor, mCallback);
@@ -621,7 +599,6 @@ public class MediaSession2 implements AutoCloseable {
    /**
     * Information of a controller.
     */
    // TODO(jaewan): Move implementation to the updatable.
    public static final class ControllerInfo {
        private final ControllerInfoProvider mProvider;

@@ -788,9 +765,9 @@ public class MediaSession2 implements AutoCloseable {
         * @hide
         */
        // TODO(jaewan): @SystemApi
        public static @Nullable CommandButton fromBundle(Bundle bundle) {
        public static @Nullable CommandButton fromBundle(Context context, Bundle bundle) {
            Builder builder = new Builder();
            builder.setCommand(Command.fromBundle(bundle.getBundle(KEY_COMMAND)));
            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));
+11 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import java.util.concurrent.Executor;
/**
 * @hide
 */
// TODO: @SystemApi
public interface MediaSession2Provider extends TransportControlProvider {
    void initialize();

@@ -68,4 +69,14 @@ public interface MediaSession2Provider extends TransportControlProvider {
        int hashCode_impl();
        boolean equals_impl(ControllerInfoProvider obj);
    }

    interface CommandProvider {
        int getCommandCode_impl();
        String getCustomCommand_impl();
        Bundle getExtra_impl();
        Bundle toBundle_impl();

        boolean equals_impl(Object ob);
        int hashCode_impl();
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.media.SessionPlayer2;
import android.media.SessionToken2;
import android.media.VolumeProvider;
import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
import android.media.update.MediaSession2Provider.CommandProvider;
import android.media.update.MediaSession2Provider.ControllerInfoProvider;
import android.os.Bundle;
import android.os.IInterface;
@@ -66,16 +67,24 @@ public interface StaticProvider {
    ControllerInfoProvider createMediaSession2ControllerInfoProvider(Context context,
            MediaSession2.ControllerInfo instance, int uid, int pid,
            String packageName, IInterface callback);
    CommandProvider createMediaSession2Command(MediaSession2.Command instance,
            int commandCode, String action, Bundle extra);
    MediaSession2.Command fromBundle_MediaSession2Command(Context context, Bundle bundle);

    MediaController2Provider createMediaController2(Context context, MediaController2 instance,
            SessionToken2 token, Executor executor, ControllerCallback callback);

    MediaBrowser2Provider createMediaBrowser2(Context context, MediaBrowser2 instance,
            SessionToken2 token, Executor executor, BrowserCallback callback);

    MediaSessionService2Provider createMediaSessionService2(MediaSessionService2 instance);
    MediaSessionService2Provider createMediaLibraryService2(MediaLibraryService2 instance);

    MediaLibrarySessionProvider createMediaLibraryService2MediaLibrarySession(Context context,
            MediaLibrarySession instance, MediaPlayerInterface player, String id,
            VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
            Executor executor, MediaLibrarySessionCallback callback);

    SessionToken2Provider createSessionToken2(Context context, SessionToken2 instance,
            String packageName, String serviceName, int uid);
    SessionToken2 SessionToken2_fromBundle(Context context, Bundle bundle);