Make MediaSession2.CommandGroup updatable

Bug: 72665979
Test: build
Change-Id: I1ba53c0bd5eb8b72847733693f4975d53e97f2d9
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 7eebcdc..0ea1e86 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -30,20 +30,18 @@
 import android.media.session.PlaybackState;
 import android.media.update.ApiLoader;
 import android.media.update.MediaSession2Provider;
+import android.media.update.MediaSession2Provider.CommandGroupProvider;
 import android.media.update.MediaSession2Provider.CommandProvider;
 import android.media.update.MediaSession2Provider.ControllerInfoProvider;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IInterface;
-import android.os.Parcelable;
 import android.os.ResultReceiver;
 import android.text.TextUtils;
-import android.util.ArraySet;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -156,14 +154,6 @@
             return mProvider.toBundle_impl();
         }
 
-        /**
-         * @return a new Command instance from the Bundle
-         * @hide
-         */
-        public static Command fromBundle(@NonNull Context context, Bundle command) {
-            return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command);
-        }
-
         @Override
         public boolean equals(Object obj) {
             if (!(obj instanceof Command)) {
@@ -176,63 +166,55 @@
         public int hashCode() {
             return mProvider.hashCode_impl();
         }
+
+        /**
+         * @return a new Command instance from the Bundle
+         * @hide
+         */
+        public static Command fromBundle(@NonNull Context context, Bundle command) {
+            return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command);
+        }
     }
 
     /**
      * Represent set of {@link Command}.
      */
-    // TODO(jaewan): Move this to updatable
     public static class CommandGroup {
-        private static final String KEY_COMMANDS =
-                "android.media.mediasession2.commandgroup.commands";
-        private ArraySet<Command> mCommands = new ArraySet<>();
-        private final Context mContext;
+        private final CommandGroupProvider mProvider;
 
         public CommandGroup(Context context) {
-            mContext = context;
+            mProvider = ApiLoader.getProvider(context)
+                    .createMediaSession2CommandGroup(context, this, null);
         }
 
         public CommandGroup(Context context, CommandGroup others) {
-            this(context);
-            mCommands.addAll(others.mCommands);
+            mProvider = ApiLoader.getProvider(context)
+                    .createMediaSession2CommandGroup(context, this, others);
         }
 
         public void addCommand(Command command) {
-            mCommands.add(command);
+            mProvider.addCommand_impl(command);
         }
 
         public void addAllPredefinedCommands() {
-            // TODO(jaewan): Is there any better way than this?
-            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));
+            mProvider.addAllPredefinedCommands_impl();
         }
 
         public void removeCommand(Command command) {
-            mCommands.remove(command);
+            mProvider.removeCommand_impl(command);
         }
 
         public boolean hasCommand(Command command) {
-            return mCommands.contains(command);
+            return mProvider.hasCommand_impl(command);
         }
 
         public boolean hasCommand(int code) {
-            if (code == 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 mProvider.hasCommand_impl(code);
+        }
+
+        @SystemApi
+        public CommandGroupProvider getProvider() {
+            return mProvider;
         }
 
         /**
@@ -240,13 +222,7 @@
          * @hide
          */
         public Bundle toBundle() {
-            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 mProvider.toBundle_impl();
         }
 
         /**
@@ -254,26 +230,8 @@
          * @hide
          */
         public static @Nullable CommandGroup fromBundle(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;
+            return ApiLoader.getProvider(context)
+                    .fromBundle_MediaSession2CommandGroup(context, commands);
         }
     }
 
diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java
index c0c0d80..f9e29d9 100644
--- a/media/java/android/media/update/MediaSession2Provider.java
+++ b/media/java/android/media/update/MediaSession2Provider.java
@@ -16,7 +16,6 @@
 
 package android.media.update;
 
-import android.media.AudioAttributes;
 import android.media.MediaItem2;
 import android.media.MediaPlayerInterface;
 import android.media.MediaPlayerInterface.PlaybackListener;
@@ -62,14 +61,6 @@
     void addPlaybackListener_impl(Executor executor, PlaybackListener listener);
     void removePlaybackListener_impl(PlaybackListener listener);
 
-    interface ControllerInfoProvider {
-        String getPackageName_impl();
-        int getUid_impl();
-        boolean isTrusted_impl();
-        int hashCode_impl();
-        boolean equals_impl(ControllerInfoProvider obj);
-    }
-
     interface CommandProvider {
         int getCommandCode_impl();
         String getCustomCommand_impl();
@@ -79,4 +70,21 @@
         boolean equals_impl(Object ob);
         int hashCode_impl();
     }
+
+    interface CommandGroupProvider {
+        void addCommand_impl(Command command);
+        void addAllPredefinedCommands_impl();
+        void removeCommand_impl(Command command);
+        boolean hasCommand_impl(Command command);
+        boolean hasCommand_impl(int code);
+        Bundle toBundle_impl();
+    }
+
+    interface ControllerInfoProvider {
+        String getPackageName_impl();
+        int getUid_impl();
+        boolean isTrusted_impl();
+        int hashCode_impl();
+        boolean equals_impl(ControllerInfoProvider obj);
+    }
 }
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index ef8c9a2..9648b27 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -37,6 +37,7 @@
 import android.media.SessionToken2;
 import android.media.VolumeProvider;
 import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
+import android.media.update.MediaSession2Provider.CommandGroupProvider;
 import android.media.update.MediaSession2Provider.CommandProvider;
 import android.media.update.MediaSession2Provider.ControllerInfoProvider;
 import android.os.Bundle;
@@ -64,12 +65,16 @@
     MediaSession2Provider createMediaSession2(Context context, MediaSession2 instance,
             MediaPlayerInterface player, String id, VolumeProvider volumeProvider, int ratingType,
             PendingIntent sessionActivity, Executor executor, SessionCallback callback);
-    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);
+    CommandGroupProvider createMediaSession2CommandGroup(Context context,
+            MediaSession2.CommandGroup instance, MediaSession2.CommandGroup others);
+    MediaSession2.CommandGroup fromBundle_MediaSession2CommandGroup(Context context, Bundle bundle);
+    ControllerInfoProvider createMediaSession2ControllerInfoProvider(Context context,
+            MediaSession2.ControllerInfo instance, int uid, int pid,
+            String packageName, IInterface callback);
+
 
     MediaController2Provider createMediaController2(Context context, MediaController2 instance,
             SessionToken2 token, Executor executor, ControllerCallback callback);