From bbce3333fcca8b36af3b16eaee46f2334f259ea4 Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Fri, 4 Jan 2019 03:34:38 +0900 Subject: [PATCH] MediaSessionManager: Add getSession2Tokens() This currently only returns tokens with the TYPE_SESSION. Follow up CLs will change this to also return tokens with other types. Bug: 122234817 Test: Build and flash manually. Change-Id: Ia2f67983393696439020d5ea58976b9ed1662566 --- .../media/session/ISessionManager.aidl | 1 + .../media/session/MediaSessionManager.java | 38 ++++++++++++ .../server/media/MediaSessionService.java | 59 +++++++++++++++++-- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl index 51148e2f1af44..0de97f1a64799 100644 --- a/media/java/android/media/session/ISessionManager.aidl +++ b/media/java/android/media/session/ISessionManager.aidl @@ -35,6 +35,7 @@ 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); + List getSession2Tokens(int userId); void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent, boolean needWakeLock); void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService, diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index ef5cf008de885..40c38cc7aaab7 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -178,6 +178,44 @@ public final class MediaSessionManager { return controllers; } + /** + * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the + * current user. + *

+ * Although this API can be used without any restriction, each session owners can accept or + * reject your uses of {@link MediaSession2}. + * + * @return A list of {@link Session2Token}. + * @hide + */ + // TODO: unhide + @NonNull + public List getSession2Tokens() { + return getSession2Tokens(UserHandle.myUserId()); + } + + /** + * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the + * given user. + *

+ * If you want to get tokens for another user, you must hold the + * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. + * + * @param userId The user id to fetch sessions for. + * @return A list of {@link Session2Token} + * @hide + */ + // TODO: unhide + @NonNull + public List getSession2Tokens(int userId) { + try { + return mService.getSession2Tokens(userId); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get session tokens", e); + } + return new ArrayList<>(); + } + /** * Add a listener to be notified when the list of active sessions * changes.This requires the diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 7f2e047d7b990..f423a731eeacc 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -114,10 +114,11 @@ public class MediaSessionService extends SystemService implements Monitor { @GuardedBy("mLock") private final ArrayList mSessionsListeners = new ArrayList(); + // Map user id as index to list of Session2Tokens // TODO: Keep session2 info in MediaSessionStack for prioritizing both session1 and session2 in // one place. @GuardedBy("mLock") - private final List mSession2Tokens = new ArrayList<>(); + private final SparseArray> mSession2TokensPerUser = new SparseArray<>(); private KeyguardManager mKeyguardManager; private IAudioService mAudioService; @@ -305,10 +306,13 @@ public class MediaSessionService extends SystemService implements Monitor { updateUser(); } + // Called when the user with the userId is removed. @Override public void onStopUser(int userId) { if (DEBUG) Log.d(TAG, "onStopUser: " + userId); synchronized (mLock) { + // TODO: Also handle removing user in updateUser() because adding/switching user is + // handled in updateUser(). FullUserRecord user = getFullUserRecordLocked(userId); if (user != null) { if (user.mFullUserId == userId) { @@ -318,6 +322,7 @@ public class MediaSessionService extends SystemService implements Monitor { user.destroySessionsForUserLocked(userId); } } + mSession2TokensPerUser.remove(userId); updateUser(); } } @@ -363,6 +368,9 @@ public class MediaSessionService extends SystemService implements Monitor { mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id)); } } + if (mSession2TokensPerUser.get(userInfo.id) == null) { + mSession2TokensPerUser.put(userInfo.id, new ArrayList<>()); + } } } // Ensure that the current full user exists. @@ -372,6 +380,9 @@ public class MediaSessionService extends SystemService implements Monitor { Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId); mCurrentFullUserRecord = new FullUserRecord(currentFullUserId); mUserRecords.put(currentFullUserId, mCurrentFullUserRecord); + if (mSession2TokensPerUser.get(currentFullUserId) == null) { + mSession2TokensPerUser.put(currentFullUserId, new ArrayList<>()); + } } mFullUserIds.put(currentFullUserId, currentFullUserId); } @@ -732,9 +743,15 @@ public class MediaSessionService extends SystemService implements Monitor { pw.println(indent + "Restored MediaButtonReceiverComponentType: " + mRestoredMediaButtonReceiverComponentType); mPriorityStack.dump(pw, indent); - pw.println(indent + "Session2Tokens - " + mSession2Tokens.size()); - for (Session2Token session2Token : mSession2Tokens) { - pw.println(indent + " " + session2Token); + pw.println(indent + "Session2Tokens:"); + for (int i = 0; i < mSession2TokensPerUser.size(); i++) { + List list = mSession2TokensPerUser.valueAt(i); + if (list == null || list.size() == 0) { + continue; + } + for (Session2Token token : list) { + pw.println(indent + " " + token); + } } } @@ -955,6 +972,34 @@ public class MediaSessionService extends SystemService implements Monitor { } } + @Override + public List getSession2Tokens(int userId) { + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + + try { + // Check that they can make calls on behalf of the user and + // get the final user id + int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId, + true /* allowAll */, true /* requireFull */, "getSession2Tokens", + null /* optional packageName */); + List result = new ArrayList<>(); + synchronized (mLock) { + if (resolvedUserId == UserHandle.USER_ALL) { + for (int i = 0; i < mSession2TokensPerUser.size(); i++) { + result.addAll(mSession2TokensPerUser.valueAt(i)); + } + } else { + result.addAll(mSession2TokensPerUser.get(userId)); + } + } + return result; + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override public void addSessionsListener(IActiveSessionsListener listener, ComponentName componentName, int userId) throws RemoteException { @@ -1965,14 +2010,16 @@ public class MediaSessionService extends SystemService implements Monitor { @Override public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) { synchronized (mLock) { - mSession2Tokens.add(mToken); + int userId = UserHandle.getUserId(mToken.getUid()); + mSession2TokensPerUser.get(userId).add(mToken); } } @Override public void onDisconnected(MediaController2 controller) { synchronized (mLock) { - mSession2Tokens.remove(mToken); + int userId = UserHandle.getUserId(mToken.getUid()); + mSession2TokensPerUser.get(userId).remove(mToken); } } }