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

Commit 78e25771 authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Make MediaSession2.Command updatable

Bug: 72619281
Test: build & runtest-MediaComponents
Change-Id: I917caaa09dfdc5dd981a555277a2a266dac8f5a0
parent fc70138c
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -53,10 +53,9 @@ public class MediaController2Impl implements MediaController2Provider {
    private static final boolean DEBUG = true; // TODO(jaewan): Change

    private final MediaController2 mInstance;

    private final Context mContext;
    private final Object mLock = new Object();

    private final Context mContext;
    private final MediaSession2CallbackStub mSessionCallbackStub;
    private final SessionToken2 mToken;
    private final ControllerCallback mCallback;
@@ -209,6 +208,10 @@ public class MediaController2Impl implements MediaController2Provider {
        return mCallbackExecutor;
    }

    Context getContext() {
      return mContext;
    }

    @Override
    public SessionToken2 getSessionToken_impl() {
        return mToken;
@@ -606,7 +609,7 @@ public class MediaController2Impl implements MediaController2Provider {
                return;
            }
            controller.onConnectionChangedNotLocked(
                    sessionBinder, CommandGroup.fromBundle(commandGroup));
                    sessionBinder, CommandGroup.fromBundle(controller.getContext(), commandGroup));
        }

        @Override
@@ -645,7 +648,8 @@ public class MediaController2Impl implements MediaController2Provider {
            }
            List<CommandButton> layout = new ArrayList<>();
            for (int i = 0; i < commandButtonlist.size(); i++) {
                CommandButton button = CommandButton.fromBundle(commandButtonlist.get(i));
                CommandButton button = CommandButton.fromBundle(
                        browser.getContext(), commandButtonlist.get(i));
                if (button != null) {
                    layout.add(button);
                }
@@ -662,7 +666,7 @@ public class MediaController2Impl implements MediaController2Provider {
                Log.w(TAG, "Don't fail silently here. Highly likely a bug");
                return;
            }
            Command command = Command.fromBundle(commandBundle);
            Command command = Command.fromBundle(controller.getContext(), commandBundle);
            if (command == null) {
                return;
            }
+92 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static android.media.SessionToken2.TYPE_LIBRARY_SERVICE;
import static android.media.SessionToken2.TYPE_SESSION;
import static android.media.SessionToken2.TYPE_SESSION_SERVICE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.Manifest.permission;
import android.app.PendingIntent;
import android.content.Context;
@@ -520,6 +522,96 @@ public class MediaSession2Impl implements MediaSession2Provider {
        }
    }

    public static final class CommandImpl implements CommandProvider {
        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 Command mInstance;
        private final int mCommandCode;
        // Nonnull if it's custom command
        private final String mCustomCommand;
        private final Bundle mExtra;

        public CommandImpl(Command instance, int commandCode) {
            mInstance = instance;
            mCommandCode = commandCode;
            mCustomCommand = null;
            mExtra = null;
        }

        public CommandImpl(Command instance, @NonNull String action, @Nullable Bundle extra) {
            if (action == null) {
                throw new IllegalArgumentException("action shouldn't be null");
            }
            mInstance = instance;
            mCommandCode = MediaSession2.COMMAND_CODE_CUSTOM;
            mCustomCommand = action;
            mExtra = extra;
        }

        public int getCommandCode_impl() {
            return mCommandCode;
        }

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

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

        /**
         * @ 7return a new Bundle instance from the Command
         */
        public Bundle toBundle_impl() {
            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 a new Command instance from the Bundle
         */
        public static Command fromBundle_impl(Context context, Bundle command) {
            int code = command.getInt(KEY_COMMAND_CODE);
            if (code != MediaSession2.COMMAND_CODE_CUSTOM) {
                return new Command(context, code);
            } else {
                String customCommand = command.getString(KEY_COMMAND_CUSTOM_COMMAND);
                if (customCommand == null) {
                    return null;
                }
                return new Command(context, customCommand, command.getBundle(KEY_COMMAND_EXTRA));
            }
        }

        @Override
        public boolean equals_impl(Object obj) {
            if (!(obj instanceof CommandImpl)) {
                return false;
            }
            CommandImpl other = (CommandImpl) 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);
        }

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

    public static class ControllerInfoImpl implements ControllerInfoProvider {
        private final ControllerInfo mInstance;
        private final int mUid;
+6 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.media;

import android.content.Context;
import android.media.MediaItem2;
import android.media.MediaLibraryService2.BrowserRoot;
import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -92,7 +93,8 @@ public class MediaSession2Stub extends IMediaSession2.Stub {
    public void connect(String callingPackage, final IMediaSession2Callback callback)
            throws RuntimeException {
        final MediaSession2Impl sessionImpl = getSession();
        final ControllerInfo request = new ControllerInfo(sessionImpl.getContext(),
        final Context context = sessionImpl.getContext();
        final ControllerInfo request = new ControllerInfo(context,
                Binder.getCallingUid(), Binder.getCallingPid(), callingPackage, callback);
        sessionImpl.getCallbackExecutor().execute(() -> {
            final MediaSession2Impl session = mSession.get();
@@ -111,7 +113,7 @@ public class MediaSession2Stub extends IMediaSession2.Stub {
                }
                if (allowedCommands == null) {
                    // For trusted apps, send non-null allowed commands to keep connection.
                    allowedCommands = new CommandGroup();
                    allowedCommands = new CommandGroup(context);
                }
            }
            if (DEBUG) {
@@ -178,7 +180,7 @@ public class MediaSession2Stub extends IMediaSession2.Stub {
                return;
            }
            // TODO(jaewan): Sanity check.
            Command command = new Command(commandCode);
            Command command = new Command(session.getContext(), commandCode);
            boolean accepted = session.getCallback().onCommandRequest(controller, command);
            if (!accepted) {
                // Don't run rejected command.
@@ -248,7 +250,7 @@ public class MediaSession2Stub extends IMediaSession2.Stub {
            if (session == null) {
                return;
            }
            final Command command = Command.fromBundle(commandBundle);
            final Command command = Command.fromBundle(session.getContext(), commandBundle);
            session.getCallback().onCustomCommand(controller, command, args, receiver);
        });
    }
+1 −1
Original line number Diff line number Diff line
@@ -152,7 +152,7 @@ public class SessionToken2Impl implements SessionToken2Provider {
        return mSessionBinder;
    }

    public static SessionToken2 fromBundle(Context context, Bundle bundle) {
    public static SessionToken2 fromBundle_impl(Context context, Bundle bundle) {
        if (bundle == null) {
            return null;
        }
+16 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
import android.media.MediaMetadata2;
import android.media.MediaPlayerInterface;
import android.media.MediaSession2;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
@@ -109,6 +110,20 @@ public class ApiFactory implements StaticProvider {
                instance, uid, pid, packageName, (IMediaSession2Callback) callback);
    }

    @Override
    public MediaSession2Provider.CommandProvider createMediaSession2Command(Command instance,
            int commandCode, String action, Bundle extra) {
        if (action == null && extra == null) {
            return new MediaSession2Impl.CommandImpl(instance, commandCode);
        }
        return new MediaSession2Impl.CommandImpl(instance, action, extra);
    }

    @Override
    public Command fromBundle_MediaSession2Command(Context context, Bundle command) {
        return MediaSession2Impl.CommandImpl.fromBundle_impl(context, command);
    }

    @Override
    public MediaSessionService2Provider createMediaSessionService2(
            MediaSessionService2 instance) {
@@ -151,7 +166,7 @@ public class ApiFactory implements StaticProvider {

    @Override
    public SessionToken2 SessionToken2_fromBundle(Context context, Bundle bundle) {
        return SessionToken2Impl.fromBundle(context, bundle);
        return SessionToken2Impl.fromBundle_impl(context, bundle);
    }

    @Override
Loading