MediaSession2: Move binder interfaces into the updatable

Test: Run all MediaComponents tests once
Change-Id: I159e03156ae5e14c79279c7a30f54e65abbcd097
diff --git a/packages/MediaComponents/Android.mk b/packages/MediaComponents/Android.mk
index 61d73a0..7c7718e 100644
--- a/packages/MediaComponents/Android.mk
+++ b/packages/MediaComponents/Android.mk
@@ -27,7 +27,10 @@
 # TODO: Use System SDK once public APIs are approved
 # LOCAL_SDK_VERSION := system_current
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-Iaidl-files-under, src)
+
 LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
 
 LOCAL_MULTILIB := first
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
new file mode 100644
index 0000000..fc62a68
--- /dev/null
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media;
+
+import android.os.Bundle;
+import android.os.ResultReceiver;
+
+import com.android.media.IMediaSession2Callback;
+
+/**
+ * Interface to MediaSession2.
+ * <p>
+ * 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.
+ */
+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
+    //               Add id for individual calls to address this.
+
+    // TODO(jaewan): We may consider to add another binder just for the connection
+    //               not to expose other methods to the controller whose connection wasn't accepted.
+    //               But this would be enough for now because it's the same as existing
+    //               MediaBrowser and MediaBrowserService.
+    void connect(String callingPackage, IMediaSession2Callback callback);
+    void release(IMediaSession2Callback caller);
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // send command
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    void sendCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args);
+    void sendTransportControlCommand(IMediaSession2Callback caller,
+            int commandCode, in Bundle args);
+    void sendCustomCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args,
+            in ResultReceiver receiver);
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Get library service specific
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
+}
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
new file mode 100644
index 0000000..34aaa87
--- /dev/null
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media;
+
+import android.os.Bundle;
+import android.os.ResultReceiver;
+
+import com.android.media.IMediaSession2;
+
+/**
+ * Interface from MediaSession2 to MediaSession2Record.
+ * <p>
+ * 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.
+ */
+oneway interface IMediaSession2Callback {
+    void onPlaybackStateChanged(in Bundle state);
+    void onPlaylistParamsChanged(in Bundle params);
+
+    /**
+     * Called only when the controller is created with service's token.
+     *
+     * @param sessionBinder {@code null} if the connect is rejected or is disconnected. a session
+     *     binder if the connect is accepted.
+     * @param commands initially allowed commands.
+     */
+    // TODO(jaewan): Also need to pass flags for allowed actions for permission check.
+    //               For example, a media can allow setRating only for whitelisted apps
+    //               it's better for controller to know such information in advance.
+    //               Follow-up TODO: Add similar functions to the session.
+    // TODO(jaewan): Is term 'accepted/rejected' correct? For permission, 'grant' is used.
+    void onConnectionChanged(IMediaSession2 sessionBinder, in Bundle commandGroup);
+
+    void onCustomLayoutChanged(in List<Bundle> commandButtonlist);
+
+    void sendCustomCommand(in Bundle command, in Bundle args, in ResultReceiver receiver);
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Browser sepcific
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    void onGetRootResult(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
+}
diff --git a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
index 511eed1..d21edae 100644
--- a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
@@ -17,7 +17,6 @@
 package com.android.media;
 
 import android.content.Context;
-import android.media.IMediaSession2;
 import android.media.MediaBrowser2;
 import android.media.MediaBrowser2.BrowserCallback;
 import android.media.MediaSession2.CommandButton;
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 16e1d21..57624e2 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -21,8 +21,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.media.IMediaSession2;
-import android.media.IMediaSession2Callback;
 import android.media.MediaController2.PlaybackInfo;
 import android.media.MediaItem2;
 import android.media.MediaSession2;
diff --git a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
index a5c9129..4b1b9de 100644
--- a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
@@ -18,7 +18,6 @@
 
 import android.app.PendingIntent;
 import android.content.Context;
-import android.content.Intent;
 import android.media.MediaLibraryService2;
 import android.media.MediaLibraryService2.MediaLibrarySession;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index 3b6b4e7..dfcc982 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -27,8 +27,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
-import android.media.AudioAttributes;
-import android.media.IMediaSession2Callback;
 import android.media.MediaItem2;
 import android.media.MediaLibraryService2;
 import android.media.MediaPlayerInterface;
@@ -108,17 +106,17 @@
         mSessionStub = new MediaSession2Stub(this);
 
         // Infer type from the id and package name.
-        String sessionService = getServiceName(context, MediaSessionService2.SERVICE_INTERFACE, id);
         String libraryService = getServiceName(context, MediaLibraryService2.SERVICE_INTERFACE, id);
+        String sessionService = getServiceName(context, MediaSessionService2.SERVICE_INTERFACE, id);
         if (sessionService != null && libraryService != null) {
             throw new IllegalArgumentException("Ambiguous session type. Multiple"
                     + " session services define the same id=" + id);
-        } else if (sessionService != null) {
-            mSessionToken = new SessionToken2(context, Process.myUid(), TYPE_SESSION_SERVICE,
-                    mContext.getPackageName(), sessionService, id, mSessionStub);
         } else if (libraryService != null) {
             mSessionToken = new SessionToken2(context, Process.myUid(), TYPE_LIBRARY_SERVICE,
                     mContext.getPackageName(), libraryService, id, mSessionStub);
+        } else if (sessionService != null) {
+            mSessionToken = new SessionToken2(context, Process.myUid(), TYPE_SESSION_SERVICE,
+                    mContext.getPackageName(), sessionService, id, mSessionStub);
         } else {
             mSessionToken = new SessionToken2(context, Process.myUid(), TYPE_SESSION,
                     mContext.getPackageName(), null, id, mSessionStub);
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 428f856..4451b3c 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -16,8 +16,6 @@
 
 package com.android.media;
 
-import android.media.IMediaSession2;
-import android.media.IMediaSession2Callback;
 import android.media.MediaLibraryService2.BrowserRoot;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
 import android.media.MediaSession2;
@@ -35,7 +33,9 @@
 import android.support.annotation.GuardedBy;
 import android.util.ArrayMap;
 import android.util.Log;
+
 import com.android.media.MediaSession2Impl.ControllerInfoImpl;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
index 70e8750..72b4da1 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
@@ -20,8 +20,6 @@
 
 import android.app.NotificationManager;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.media.MediaPlayerInterface.PlaybackListener;
 import android.media.MediaSession2;
 import android.media.MediaSessionService2;
diff --git a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
index c9ac434..8457d90 100644
--- a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
@@ -25,7 +25,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
-import android.media.IMediaSession2;
 import android.media.MediaLibraryService2;
 import android.media.MediaSessionService2;
 import android.media.SessionToken2;
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index d9a0605..fff59cc 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -21,7 +21,6 @@
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.media.DataSourceDesc;
-import android.media.IMediaSession2;
 import android.media.MediaBrowser2;
 import android.media.MediaBrowser2.BrowserCallback;
 import android.media.MediaController2;
@@ -36,7 +35,6 @@
 import android.media.MediaSession2.ControllerInfo;
 import android.media.MediaSession2.SessionCallback;
 import android.media.MediaSessionService2;
-import android.media.IMediaSession2Callback;
 import android.media.SessionPlayer2;
 import android.media.SessionToken2;
 import android.media.VolumeProvider;
@@ -59,6 +57,8 @@
 import android.widget.MediaControlView2;
 import android.widget.VideoView2;
 
+import com.android.media.IMediaSession2;
+import com.android.media.IMediaSession2Callback;
 import com.android.media.MediaBrowser2Impl;
 import com.android.media.MediaController2Impl;
 import com.android.media.MediaItem2Impl;