From 64971a5106cfc8cde7b9ec24fb0f3c1c167b252a Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 25 Feb 2021 15:08:08 +0000 Subject: [PATCH] Media: Add MSM#getMediaKeyEventSession Add MediaSessionManager#getMediaKeyEventSession for system apps to get the current media key event session, which may be different from the first session in MediaSessionManager#getActiveSessions(). Bug: 181383356 Test: atest MediaSessionManagerTest Change-Id: I56ece75e352150693a5658e2660f39b5702d8612 --- core/api/system-current.txt | 2 + .../media/session/ISessionManager.aidl | 2 + .../media/session/MediaSessionManager.java | 40 +++++++++++- .../server/media/MediaSessionService.java | 64 +++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index a0e0f7133a257..0982277fe554e 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5433,6 +5433,8 @@ package android.media.session { public final class MediaSessionManager { method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventDispatchedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener); method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener); + method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.media.session.MediaSession.Token getMediaKeyEventSession(); + method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public String getMediaKeyEventSessionPackageName(); method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener); method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener); method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler); diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl index 96bffee117ea6..3b0f577d84cb8 100644 --- a/media/java/android/media/session/ISessionManager.aidl +++ b/media/java/android/media/session/ISessionManager.aidl @@ -39,6 +39,8 @@ interface ISessionManager { ISession createSession(String packageName, in ISessionCallback sessionCb, String tag, in Bundle sessionInfo, int userId); List getSessions(in ComponentName compName, int userId); + MediaSession.Token getMediaKeyEventSession(); + String getMediaKeyEventSessionPackageName(); void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent, boolean needWakeLock); boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName, diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 78db750d4a64f..269b70b667a07 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -194,6 +194,44 @@ public final class MediaSessionManager { return getActiveSessionsForUser(notificationListener, UserHandle.myUserId()); } + /** + * Gets the media key event session, which would receive a media key event unless specified. + * @return The media key event session, which would receive key events by default, unless + * the caller has specified the target. Can be {@code null}. + * @hide + */ + @SystemApi + @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL) + @Nullable + public MediaSession.Token getMediaKeyEventSession() { + try { + return mService.getMediaKeyEventSession(); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to get media key event session", ex); + } + return null; + } + + /** + * Gets the package name of the media key event session. + * @return The package name of the media key event session or the last session's media button + * receiver if the media key event session is {@code null}. + * @see #getMediaKeyEventSession() + * @hide + */ + @SystemApi + @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL) + @NonNull + public String getMediaKeyEventSessionPackageName() { + try { + String packageName = mService.getMediaKeyEventSessionPackageName(); + return (packageName != null) ? packageName : ""; + } catch (RemoteException ex) { + Log.e(TAG, "Failed to get media key event session", ex); + } + return ""; + } + /** * Get active sessions for the given user. *

@@ -856,7 +894,7 @@ public final class MediaSessionManager { } /** - * Add a {@link OnMediaKeyEventDispatchedListener}. + * Add a {@link OnMediaKeyEventSessionChangedListener}. * * @param executor The executor on which the listener should be invoked * @param listener A {@link OnMediaKeyEventSessionChangedListener}. diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index db2e9085bdb3a..a30d993136a7a 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1224,6 +1224,70 @@ public class MediaSessionService extends SystemService implements Monitor { } } + @Override + public MediaSession.Token getMediaKeyEventSession() { + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier(); + final long token = Binder.clearCallingIdentity(); + try { + if (!hasMediaControlPermission(pid, uid)) { + throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to" + + " get the media key event session"); + } + MediaSessionRecordImpl record; + synchronized (mLock) { + FullUserRecord user = getFullUserRecordLocked(userId); + if (user == null) { + Log.w(TAG, "No matching user record to get the media key event session" + + ", userId=" + userId); + return null; + } + record = user.getMediaButtonSessionLocked(); + } + if (record instanceof MediaSessionRecord) { + return ((MediaSessionRecord) record).getSessionToken(); + } + //TODO: Handle media session 2 case + return null; + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public String getMediaKeyEventSessionPackageName() { + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier(); + final long token = Binder.clearCallingIdentity(); + try { + if (!hasMediaControlPermission(pid, uid)) { + throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to" + + " get the media key event session package"); + } + MediaSessionRecordImpl record; + synchronized (mLock) { + FullUserRecord user = getFullUserRecordLocked(userId); + if (user == null) { + Log.w(TAG, "No matching user record to get the media key event session" + + " package , userId=" + userId); + return ""; + } + record = user.getMediaButtonSessionLocked(); + if (record instanceof MediaSessionRecord) { + return record.getPackageName(); + //TODO: Handle media session 2 case + } else if (user.mLastMediaButtonReceiverHolder != null) { + return user.mLastMediaButtonReceiverHolder.getPackageName(); + } + } + return ""; + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override public void addSessionsListener(IActiveSessionsListener listener, ComponentName componentName, int userId) throws RemoteException {