From 7ad39875fddac6b90695d411fff41c2032ccf8ab Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Thu, 3 Jan 2019 15:49:43 +0900 Subject: [PATCH] MediaSession2: Tell framework about new MediaSession2 Bug: 122234817 Test: Build and flash manually. Change-Id: If210762c51d33e72ea09e6328eea435b68d2eaa4 --- media/java/android/media/MediaSession2.java | 16 +++++++++++- media/java/android/media/Session2Token.aidl | 19 ++++++++++++++ media/java/android/media/Session2Token.java | 5 ++-- .../media/session/ISessionManager.aidl | 2 ++ .../media/session/MediaSessionManager.java | 26 +++++++++++++++++++ .../server/media/MediaSessionService.java | 16 ++++++++++++ 6 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 media/java/android/media/Session2Token.aidl diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java index 4712cddf3522e..1ee851f5a0689 100644 --- a/media/java/android/media/MediaSession2.java +++ b/media/java/android/media/MediaSession2.java @@ -464,7 +464,21 @@ public class MediaSession2 implements AutoCloseable { if (mId == null) { mId = ""; } - return new MediaSession2(mContext, mId, mSessionActivity, mCallbackExecutor, mCallback); + MediaSession2 session2 = new MediaSession2(mContext, mId, mSessionActivity, + mCallbackExecutor, mCallback); + + // Notify framework about the newly create session after the constructor is finished. + // Otherwise, framework may access the session before the initialization is finished. + try { + MediaSessionManager manager = (MediaSessionManager) mContext.getSystemService( + Context.MEDIA_SESSION_SERVICE); + manager.notifySession2Created(session2.getSessionToken()); + } catch (Exception e) { + session2.close(); + throw e; + } + + return session2; } } diff --git a/media/java/android/media/Session2Token.aidl b/media/java/android/media/Session2Token.aidl new file mode 100644 index 0000000000000..c5980e9e77fd5 --- /dev/null +++ b/media/java/android/media/Session2Token.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2019 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 android.media; + +parcelable Session2Token; diff --git a/media/java/android/media/Session2Token.java b/media/java/android/media/Session2Token.java index 7642faae00c7a..4634c69636752 100644 --- a/media/java/android/media/Session2Token.java +++ b/media/java/android/media/Session2Token.java @@ -102,7 +102,8 @@ public final class Session2Token implements Parcelable { private final ComponentName mComponentName; /** - * Constructor for the token. + * Constructor for the token with type {@link #TYPE_SESSION_SERVICE} or + * {@link #TYPE_LIBRARY_SERVICE}. * * @param context The context. * @param serviceComponent The component name of the service. @@ -119,7 +120,7 @@ public final class Session2Token implements Parcelable { final int uid = getUid(manager, serviceComponent.getPackageName()); // TODO: Uncomment below to stop hardcode type. - final int type = TYPE_SESSION; + final int type = TYPE_SESSION_SERVICE; // final int type; // if (isInterfaceDeclared(manager, MediaLibraryService2.SERVICE_INTERFACE, // serviceComponent)) { diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl index d6c226f8b6d03..51148e2f1af44 100644 --- a/media/java/android/media/session/ISessionManager.aidl +++ b/media/java/android/media/session/ISessionManager.aidl @@ -17,6 +17,7 @@ package android.media.session; import android.content.ComponentName; import android.media.IRemoteVolumeController; +import android.media.Session2Token; import android.media.session.IActiveSessionsListener; import android.media.session.ICallback; import android.media.session.IOnMediaKeyListener; @@ -32,6 +33,7 @@ import android.view.KeyEvent; */ interface ISessionManager { ISession createSession(String packageName, in ISessionCallback cb, String tag, int userId); + void notifySession2Created(in Session2Token sessionToken); List getSessions(in ComponentName compName, int userId); void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent, boolean needWakeLock); diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 4221d66edb99c..ef5cf008de885 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -26,6 +26,8 @@ import android.content.ComponentName; import android.content.Context; import android.media.AudioManager; import android.media.IRemoteVolumeController; +import android.media.MediaSession2; +import android.media.Session2Token; import android.media.browse.MediaBrowser; import android.os.Handler; import android.os.IBinder; @@ -101,6 +103,30 @@ public final class MediaSessionManager { return mService.createSession(mContext.getPackageName(), cbStub, tag, userId); } + /** + * Notifies that a new {@link MediaSession2} with type {@link Session2Token#TYPE_SESSION} is + * created. + *

+ * Do not use this API directly, but create a new instance through the + * {@link MediaSession2.Builder} instead. + * + * @param token newly created session2 token + * @hide + */ + public void notifySession2Created(@NonNull Session2Token token) { + if (token == null) { + throw new IllegalArgumentException("token shouldn't be null"); + } + if (token.getType() != Session2Token.TYPE_SESSION) { + throw new IllegalArgumentException("token's type should be TYPE_SESSION"); + } + try { + mService.notifySession2Created(token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + /** * Get a list of controllers for all ongoing sessions. The controllers will * be provided in priority order with the most important controller at index diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index d51da995a37d5..052d5797c1e71 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -40,6 +40,7 @@ import android.media.AudioPlaybackConfiguration; import android.media.AudioSystem; import android.media.IAudioService; import android.media.IRemoteVolumeController; +import android.media.Session2Token; import android.media.session.IActiveSessionsListener; import android.media.session.ICallback; import android.media.session.IOnMediaKeyListener; @@ -894,6 +895,21 @@ public class MediaSessionService extends SystemService implements Monitor { } } + @Override + public void notifySession2Created(Session2Token sessionToken) throws RemoteException { + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + if (DEBUG) { + Log.d(TAG, "Session2 is created " + sessionToken); + } + // TODO: Keep the session. + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override public List getSessions(ComponentName componentName, int userId) { final int pid = Binder.getCallingPid();