summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author tonihei <tonihei@google.com> 2024-10-29 10:34:45 +0000
committer tonihei <tonihei@google.com> 2024-11-05 14:42:30 +0000
commit5adc3f5a0d45df9b8b6aaaaf9ca6fd2aff8e895e (patch)
treee012c41e1b87bdc947743eeaaab757d7ff8f3df5
parent0d7fcc1daaf588fb3c17cbfcd1f0cd333ddbc7f8 (diff)
Interrupt temporarily engaged timer while priority session is active
Session are expected to enter a temporarily engaged state (e.g. PAUSED) while the global priority session is active, typically due a transient audio focus loss. While the global priority session is active, we can keep the temporary engaged state without a timeout because the session is expected to go back to an engaged state after the priority session became inactive. Test: atest cts/tests/app/src/android/app/cts/ActivityManagerFgsDelegateTest.java Flag: com.android.media.flags.enable_notifying_activity_manager_with_media_session_status_change Bug: 295518668 Change-Id: Ia815d9d84baeea9e92f6daa940571e2f69386b40
-rw-r--r--services/core/java/com/android/server/media/MediaSession2Record.java5
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java38
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecordImpl.java4
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java37
4 files changed, 76 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java
index 89555a9f1de4..c8a87994ee16 100644
--- a/services/core/java/com/android/server/media/MediaSession2Record.java
+++ b/services/core/java/com/android/server/media/MediaSession2Record.java
@@ -161,6 +161,11 @@ public class MediaSession2Record extends MediaSessionRecordImpl {
}
@Override
+ public void onGlobalPrioritySessionActiveChanged(boolean isGlobalPrioritySessionActive) {
+ // NA as MediaSession2 doesn't support UserEngagementStates for FGS.
+ }
+
+ @Override
public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
KeyEvent ke, int sequenceId, ResultReceiver cb) {
// TODO(jaewan): Implement.
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index a34ccedf4f8b..0d779af22c2d 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -234,7 +234,9 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
private final Runnable mUserEngagementTimeoutExpirationRunnable =
() -> {
synchronized (mLock) {
- updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
+ updateUserEngagedStateIfNeededLocked(
+ /* isTimeoutExpired= */ true,
+ /* isGlobalPrioritySessionActive= */ false);
}
};
@@ -600,7 +602,8 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
mSessionCb.mCb.asBinder().unlinkToDeath(this, 0);
mDestroyed = true;
mPlaybackState = null;
- updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
+ updateUserEngagedStateIfNeededLocked(
+ /* isTimeoutExpired= */ true, /* isGlobalPrioritySessionActive= */ false);
mHandler.post(MessageHandler.MSG_DESTROYED);
}
}
@@ -617,6 +620,24 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
mHandler.post(mUserEngagementTimeoutExpirationRunnable);
}
+ @Override
+ public void onGlobalPrioritySessionActiveChanged(boolean isGlobalPrioritySessionActive) {
+ mHandler.post(
+ () -> {
+ synchronized (mLock) {
+ if (isGlobalPrioritySessionActive) {
+ mHandler.removeCallbacks(mUserEngagementTimeoutExpirationRunnable);
+ } else {
+ if (mUserEngagementState == USER_TEMPORARILY_ENGAGED) {
+ mHandler.postDelayed(
+ mUserEngagementTimeoutExpirationRunnable,
+ TEMP_USER_ENGAGED_TIMEOUT_MS);
+ }
+ }
+ }
+ });
+ }
+
/**
* Sends media button.
*
@@ -1107,7 +1128,8 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
}
@GuardedBy("mLock")
- private void updateUserEngagedStateIfNeededLocked(boolean isTimeoutExpired) {
+ private void updateUserEngagedStateIfNeededLocked(
+ boolean isTimeoutExpired, boolean isGlobalPrioritySessionActive) {
if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
return;
}
@@ -1128,7 +1150,7 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
}
mUserEngagementState = newUserEngagedState;
- if (newUserEngagedState == USER_TEMPORARILY_ENGAGED) {
+ if (newUserEngagedState == USER_TEMPORARILY_ENGAGED && !isGlobalPrioritySessionActive) {
mHandler.postDelayed(
mUserEngagementTimeoutExpirationRunnable, TEMP_USER_ENGAGED_TIMEOUT_MS);
} else {
@@ -1183,9 +1205,11 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
.logFgsApiEnd(ActivityManager.FOREGROUND_SERVICE_API_TYPE_MEDIA_PLAYBACK,
callingUid, callingPid);
}
+ boolean isGlobalPrioritySessionActive = mService.isGlobalPrioritySessionActive();
synchronized (mLock) {
mIsActive = active;
- updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
+ updateUserEngagedStateIfNeededLocked(
+ /* isTimeoutExpired= */ false, isGlobalPrioritySessionActive);
}
long token = Binder.clearCallingIdentity();
try {
@@ -1342,9 +1366,11 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
boolean shouldUpdatePriority = ALWAYS_PRIORITY_STATES.contains(newState)
|| (!TRANSITION_PRIORITY_STATES.contains(oldState)
&& TRANSITION_PRIORITY_STATES.contains(newState));
+ boolean isGlobalPrioritySessionActive = mService.isGlobalPrioritySessionActive();
synchronized (mLock) {
mPlaybackState = state;
- updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
+ updateUserEngagedStateIfNeededLocked(
+ /* isTimeoutExpired= */ false, isGlobalPrioritySessionActive);
}
final long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
index 15f90d4fdd0e..6c3b1234935a 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
@@ -206,6 +206,10 @@ public abstract class MediaSessionRecordImpl {
*/
public abstract void expireTempEngaged();
+ /** Notifies record that the global priority session active state changed. */
+ public abstract void onGlobalPrioritySessionActiveChanged(
+ boolean isGlobalPrioritySessionActive);
+
@Override
public final boolean equals(Object o) {
if (this == o) return true;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1ebc856af2d8..2b29fbd9c5b5 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -362,6 +362,7 @@ public class MediaSessionService extends SystemService implements Monitor {
+ record.isActive());
}
user.pushAddressedPlayerChangedLocked();
+ mHandler.post(this::notifyGlobalPrioritySessionActiveChanged);
} else {
if (!user.mPriorityStack.contains(record)) {
Log.w(TAG, "Unknown session updated. Ignoring.");
@@ -394,11 +395,16 @@ public class MediaSessionService extends SystemService implements Monitor {
// Currently only media1 can become global priority session.
void setGlobalPrioritySession(MediaSessionRecord record) {
+ boolean globalPrioritySessionActiveChanged = false;
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(record.getUserId());
if (mGlobalPrioritySession != record) {
Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
+ " to " + record);
+ globalPrioritySessionActiveChanged =
+ (mGlobalPrioritySession == null && record.isActive())
+ || (mGlobalPrioritySession != null
+ && mGlobalPrioritySession.isActive() != record.isActive());
mGlobalPrioritySession = record;
if (user != null && user.mPriorityStack.contains(record)) {
// Handle the global priority session separately.
@@ -409,6 +415,30 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
}
+ if (globalPrioritySessionActiveChanged) {
+ mHandler.post(this::notifyGlobalPrioritySessionActiveChanged);
+ }
+ }
+
+ /** Returns whether the global priority session is active. */
+ boolean isGlobalPrioritySessionActive() {
+ synchronized (mLock) {
+ return isGlobalPriorityActiveLocked();
+ }
+ }
+
+ private void notifyGlobalPrioritySessionActiveChanged() {
+ if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+ return;
+ }
+ synchronized (mLock) {
+ boolean isGlobalPriorityActive = isGlobalPriorityActiveLocked();
+ for (Set<MediaSessionRecordImpl> records : mUserEngagedSessionsForFgs.values()) {
+ for (MediaSessionRecordImpl record : records) {
+ record.onGlobalPrioritySessionActiveChanged(isGlobalPriorityActive);
+ }
+ }
+ }
}
private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
@@ -646,8 +676,11 @@ public class MediaSessionService extends SystemService implements Monitor {
if (mGlobalPrioritySession == session) {
mGlobalPrioritySession = null;
- if (session.isActive() && user != null) {
- user.pushAddressedPlayerChangedLocked();
+ if (session.isActive()) {
+ if (user != null) {
+ user.pushAddressedPlayerChangedLocked();
+ }
+ mHandler.post(this::notifyGlobalPrioritySessionActiveChanged);
}
} else {
if (user != null) {