From 101b4d5e74f5840a9ac3a6cbfa9f62f2ce048a06 Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Thu, 18 May 2017 13:23:11 +0900 Subject: [PATCH] Allow media apps to receive media key events after the phone call This CL makes the global priority session (i.e. media session of the Telecom) to be received media key events only if it's active. This makes the global priority session as an exception of the media button handling logic, which sends the media key events to the lastly played media app. Bug: 37910759 Test: Run CTS tests (MediaSessionTest, MediaSessionManagerTest, and CtsMediaHostTestCases) and manual test (Media apps receives the media keys after the phone call, and was able to answer/end the call) Change-Id: I080dfcae9c9690628ed339ad9325633d818a9591 --- .../server/media/MediaSessionService.java | 101 +++++++++++------- .../server/media/MediaSessionStack.java | 9 +- 2 files changed, 62 insertions(+), 48 deletions(-) diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index e0017b502ee04..38c615791d9f0 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -171,19 +171,63 @@ public class MediaSessionService extends SystemService implements Monitor { public void updateSession(MediaSessionRecord record) { synchronized (mLock) { FullUserRecord user = getFullUserRecordLocked(record.getUserId()); - if (user == null || !user.mPriorityStack.contains(record)) { - Log.d(TAG, "Unknown session updated. Ignoring."); + if (user == null) { + Log.w(TAG, "Unknown session updated. Ignoring."); return; } - user.mPriorityStack.onSessionStateChange(record); if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) { - mGlobalPrioritySession = record; + if (mGlobalPrioritySession != record) { + Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession + + " to " + record); + mGlobalPrioritySession = record; + if (user != null && user.mPriorityStack.contains(record)) { + // Handle the global priority session separately. + // Otherwise, it will be the media button session even after it becomes + // inactive because it has been the lastly played media app. + user.mPriorityStack.removeSession(record); + } + } + if (DEBUG_KEY_EVENT) { + Log.d(TAG, "Global priority session is updated, active=" + record.isActive()); + } user.pushAddressedPlayerChangedLocked(); + } else { + if (!user.mPriorityStack.contains(record)) { + Log.w(TAG, "Unknown session updated. Ignoring."); + return; + } + user.mPriorityStack.onSessionStateChange(record); } mHandler.postSessionsChanged(record.getUserId()); } } + private List getActiveSessionsLocked(int userId) { + List records; + if (userId == UserHandle.USER_ALL) { + records = new ArrayList<>(); + int size = mUserRecords.size(); + for (int i = 0; i < size; i++) { + records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId)); + } + } else { + FullUserRecord user = getFullUserRecordLocked(userId); + if (user == null) { + Log.w(TAG, "getSessions failed. Unknown user " + userId); + return new ArrayList<>(); + } + records = user.mPriorityStack.getActiveSessions(userId); + } + + // Return global priority session at the first whenever it's asked. + if (isGlobalPriorityActiveLocked() + && (userId == UserHandle.USER_ALL + || userId == mGlobalPrioritySession.getUserId())) { + records.add(0, mGlobalPrioritySession); + } + return records; + } + /** * Tells the system UI that volume has changed on an active remote session. */ @@ -339,16 +383,16 @@ public class MediaSessionService extends SystemService implements Monitor { if (DEBUG) { Log.d(TAG, "Destroying " + session); } - int userId = session.getUserId(); - FullUserRecord user = getFullUserRecordLocked(userId); - if (user != null) { - user.removeSessionLocked(session); - } + FullUserRecord user = getFullUserRecordLocked(session.getUserId()); if (mGlobalPrioritySession == session) { mGlobalPrioritySession = null; if (session.isActive() && user != null) { user.pushAddressedPlayerChangedLocked(); } + } else { + if (user != null) { + user.mPriorityStack.removeSession(session); + } } try { @@ -484,7 +528,7 @@ public class MediaSessionService extends SystemService implements Monitor { throw new RuntimeException("Media Session owner died prematurely.", e); } - user.addSessionLocked(session); + user.mPriorityStack.addSession(session); mHandler.postSessionsChanged(userId); if (DEBUG) { @@ -509,7 +553,7 @@ public class MediaSessionService extends SystemService implements Monitor { Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId); return; } - List records = user.mPriorityStack.getActiveSessions(userId); + List records = getActiveSessionsLocked(userId); int size = records.size(); ArrayList tokens = new ArrayList(); for (int i = 0; i < size; i++) { @@ -637,14 +681,6 @@ public class MediaSessionService extends SystemService implements Monitor { } } - public void addSessionLocked(MediaSessionRecord session) { - mPriorityStack.addSession(session); - } - - public void removeSessionLocked(MediaSessionRecord session) { - mPriorityStack.removeSession(session); - } - public void dumpLocked(PrintWriter pw, String prefix) { pw.print(prefix + "Record for full_user=" + mFullUserId); // Dump managed profile user ids associated with this user. @@ -816,27 +852,9 @@ public class MediaSessionService extends SystemService implements Monitor { int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid); ArrayList binders = new ArrayList(); synchronized (mLock) { - if (resolvedUserId == UserHandle.USER_ALL) { - int size = mUserRecords.size(); - for (int i = 0; i < size; i++) { - List records = - mUserRecords.valueAt(i).mPriorityStack.getActiveSessions( - resolvedUserId); - for (MediaSessionRecord record : records) { - binders.add(record.getControllerBinder().asBinder()); - } - } - } else { - FullUserRecord user = getFullUserRecordLocked(resolvedUserId); - if (user == null) { - Log.w(TAG, "getSessions failed. Unknown user " + userId); - return binders; - } - List records = user.mPriorityStack - .getActiveSessions(resolvedUserId); - for (MediaSessionRecord record : records) { - binders.add(record.getControllerBinder().asBinder()); - } + List records = getActiveSessionsLocked(resolvedUserId); + for (MediaSessionRecord record : records) { + binders.add(record.getControllerBinder().asBinder()); } } return binders; @@ -1292,6 +1310,9 @@ public class MediaSessionService extends SystemService implements Monitor { synchronized (mLock) { pw.println(mSessionsListeners.size() + " sessions listeners."); pw.println("Global priority session is " + mGlobalPrioritySession); + if (mGlobalPrioritySession != null) { + mGlobalPrioritySession.dump(pw, " "); + } pw.println("User Records:"); int count = mUserRecords.size(); for (int i = 0; i < count; i++) { diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index f474769bfd319..f03f630d0e57a 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -310,7 +310,6 @@ class MediaSessionStack { * Get a priority sorted list of sessions. Can filter to only return active * sessions or sessions. *

Here's the priority order. - *

  • System priority session (session with FLAG_EXCLUSIVE_GLOBAL_PRIORITY)
  • *
  • Active sessions whose PlaybackState is active
  • *
  • Active sessions whose PlaybackState is inactive
  • *
  • Inactive sessions
  • @@ -344,13 +343,7 @@ class MediaSessionStack { continue; } - if (session.isSystemPriority()) { - // System priority sessions are special and always go at the - // front. We expect there to only be one of these at a time. - result.add(0, session); - lastPlaybackActiveIndex++; - lastActiveIndex++; - } else if (session.isPlaybackActive()) { + if (session.isPlaybackActive()) { result.add(lastPlaybackActiveIndex++, session); lastActiveIndex++; } else {