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

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

Merge "Make MediaSession2.CommandGroup updatable"

parents 884374eb a7df615b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.media.IMediaSession2Callback;
 * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
 * and holds calls from session to make session owner(s) frozen.
 */
// TODO: Consider to make some methods oneway
interface IMediaSession2 {
    // TODO(jaewan): add onCommand() to send private command
    // TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
+111 −3
Original line number Diff line number Diff line
@@ -48,11 +48,13 @@ import android.media.VolumeProvider;
import android.media.session.MediaSessionManager;
import android.media.update.MediaSession2Provider;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.Process;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.support.annotation.GuardedBy;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;

import java.lang.ref.WeakReference;
@@ -108,6 +110,8 @@ public class MediaSession2Impl implements MediaSession2Provider {
        mId = id;
        mCallback = callback;
        mCallbackExecutor = callbackExecutor;
        // Only remember player. Actual settings will be done in the initialize().
        mPlayer = player;
        mSessionStub = new MediaSession2Stub(this);

        // Infer type from the id and package name.
@@ -126,9 +130,6 @@ public class MediaSession2Impl implements MediaSession2Provider {
            mSessionToken = new SessionToken2Impl(context, Process.myUid(), TYPE_SESSION,
                    mContext.getPackageName(), null, id, mSessionStub).getInstance();
        }

        // Only remember player. Actual settings will be done in the initialize().
        mPlayer = player;
    }

    private static String getServiceName(Context context, String serviceAction, String id) {
@@ -612,6 +613,113 @@ public class MediaSession2Impl implements MediaSession2Provider {
        }
    }

    /**
     * Represent set of {@link Command}.
     */
    public static class CommandGroupImpl implements CommandGroupProvider {
        private static final String KEY_COMMANDS =
                "android.media.mediasession2.commandgroup.commands";
        private ArraySet<Command> mCommands = new ArraySet<>();
        private final Context mContext;
        private final CommandGroup mInstance;

        public CommandGroupImpl(Context context, CommandGroup instance, Object other) {
            mContext = context;
            mInstance = instance;
            if (other != null && other instanceof CommandGroupImpl) {
                mCommands.addAll(((CommandGroupImpl) other).mCommands);
            }
        }

        @Override
        public void addCommand_impl(Command command) {
            mCommands.add(command);
        }

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

        @Override
        public void removeCommand_impl(Command command) {
            mCommands.remove(command);
        }

        @Override
        public boolean hasCommand_impl(Command command) {
            return mCommands.contains(command);
        }

        @Override
        public boolean hasCommand_impl(int code) {
            if (code == MediaSession2.COMMAND_CODE_CUSTOM) {
                throw new IllegalArgumentException("Use hasCommand(Command) for custom command");
            }
            for (int i = 0; i < mCommands.size(); i++) {
                if (mCommands.valueAt(i).getCommandCode() == code) {
                    return true;
                }
            }
            return false;
        }

        /**
         * @return new bundle from the CommandGroup
         * @hide
         */
        @Override
        public Bundle toBundle_impl() {
            ArrayList<Bundle> list = new ArrayList<>();
            for (int i = 0; i < mCommands.size(); i++) {
                list.add(mCommands.valueAt(i).toBundle());
            }
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(KEY_COMMANDS, list);
            return bundle;
        }

        /**
         * @return new instance of CommandGroup from the bundle
         * @hide
         */
        public static @Nullable CommandGroup fromBundle_impl(Context context, Bundle commands) {
            if (commands == null) {
                return null;
            }
            List<Parcelable> list = commands.getParcelableArrayList(KEY_COMMANDS);
            if (list == null) {
                return null;
            }
            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(context, commandBundle);
                if (command != null) {
                    commandGroup.addCommand(command);
                }
            }
            return commandGroup;
        }
    }

    public static class ControllerInfoImpl implements ControllerInfoProvider {
        private final ControllerInfo mInstance;
        private final int mUid;
+23 −10
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.media.MediaMetadata2;
import android.media.MediaPlayerInterface;
import android.media.MediaSession2;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
@@ -103,16 +104,8 @@ public class ApiFactory implements StaticProvider {
    }

    @Override
    public MediaSession2Provider.ControllerInfoProvider createMediaSession2ControllerInfoProvider(
            Context context, ControllerInfo instance, int uid, int pid, String packageName,
            IInterface callback) {
        return new MediaSession2Impl.ControllerInfoImpl(context,
                instance, uid, pid, packageName, (IMediaSession2Callback) callback);
    }

    @Override
    public MediaSession2Provider.CommandProvider createMediaSession2Command(Command instance,
            int commandCode, String action, Bundle extra) {
    public MediaSession2Provider.CommandProvider createMediaSession2Command(
            Command instance, int commandCode, String action, Bundle extra) {
        if (action == null && extra == null) {
            return new MediaSession2Impl.CommandImpl(instance, commandCode);
        }
@@ -124,6 +117,26 @@ public class ApiFactory implements StaticProvider {
        return MediaSession2Impl.CommandImpl.fromBundle_impl(context, command);
    }

    @Override
    public MediaSession2Provider.CommandGroupProvider createMediaSession2CommandGroup(
            Context context, CommandGroup instance, CommandGroup other) {
        return new MediaSession2Impl.CommandGroupImpl(context, instance,
                (other == null) ? null : other.getProvider());
    }

    @Override
    public CommandGroup fromBundle_MediaSession2CommandGroup(Context context, Bundle commands) {
        return MediaSession2Impl.CommandGroupImpl.fromBundle_impl(context, commands);
    }

    @Override
    public MediaSession2Provider.ControllerInfoProvider createMediaSession2ControllerInfoProvider(
            Context context, ControllerInfo instance, int uid, int pid, String packageName,
            IInterface callback) {
        return new MediaSession2Impl.ControllerInfoImpl(context,
                instance, uid, pid, packageName, (IMediaSession2Callback) callback);
    }

    @Override
    public MediaSessionService2Provider createMediaSessionService2(
            MediaSessionService2 instance) {