summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/media/MediaSession2Record.java8
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java35
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecordImpl.java13
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java124
4 files changed, 81 insertions, 99 deletions
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java
index c8a87994ee16..e7b79abed73a 100644
--- a/services/core/java/com/android/server/media/MediaSession2Record.java
+++ b/services/core/java/com/android/server/media/MediaSession2Record.java
@@ -16,7 +16,6 @@
package com.android.server.media;
-import android.app.ForegroundServiceDelegationOptions;
import android.app.Notification;
import android.media.MediaController2;
import android.media.Session2CommandGroup;
@@ -98,11 +97,8 @@ public class MediaSession2Record extends MediaSessionRecordImpl {
}
@Override
- public ForegroundServiceDelegationOptions getForegroundServiceDelegationOptions() {
- // For an app to be eligible for FGS delegation, it needs a media session liked to a media
- // notification. Currently, notifications cannot be linked to MediaSession2 so it is not
- // supported.
- return null;
+ public boolean hasLinkedNotificationSupport() {
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 668ee2adbd9f..5f7c86f7b670 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -29,7 +29,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.ForegroundServiceDelegationOptions;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.compat.CompatChanges;
@@ -184,8 +183,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
private final UriGrantsManagerInternal mUgmInternal;
private final Context mContext;
- private final ForegroundServiceDelegationOptions mForegroundServiceDelegationOptions;
-
private final Object mLock = new Object();
// This field is partially guarded by mLock. Writes and non-atomic iterations (for example:
// index-based-iterations) must be guarded by mLock. But it is safe to acquire an iterator
@@ -306,32 +303,10 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
mPolicies = policies;
mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
- mForegroundServiceDelegationOptions = createForegroundServiceDelegationOptions();
-
// May throw RemoteException if the session app is killed.
mSessionCb.mCb.asBinder().linkToDeath(this, 0);
}
- private ForegroundServiceDelegationOptions createForegroundServiceDelegationOptions() {
- return new ForegroundServiceDelegationOptions.Builder()
- .setClientPid(mOwnerPid)
- .setClientUid(getUid())
- .setClientPackageName(getPackageName())
- .setClientAppThread(null)
- .setSticky(false)
- .setClientInstanceName(
- "MediaSessionFgsDelegate_"
- + getUid()
- + "_"
- + mOwnerPid
- + "_"
- + getPackageName())
- .setForegroundServiceTypes(0)
- .setDelegationService(
- ForegroundServiceDelegationOptions.DELEGATION_SERVICE_MEDIA_PLAYBACK)
- .build();
- }
-
/**
* Get the session binder for the {@link MediaSession}.
*
@@ -389,6 +364,11 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
return mUserId;
}
+ @Override
+ public boolean hasLinkedNotificationSupport() {
+ return true;
+ }
+
/**
* Check if this session has system priorty and should receive media buttons
* before any other sessions.
@@ -752,11 +732,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
return mPackageName + "/" + mTag + "/" + getUniqueId() + " (userId=" + mUserId + ")";
}
- @Override
- public ForegroundServiceDelegationOptions getForegroundServiceDelegationOptions() {
- return mForegroundServiceDelegationOptions;
- }
-
private void postAdjustLocalVolume(final int stream, final int direction, final int flags,
final String callingOpPackageName, final int callingPid, final int callingUid,
final boolean asSystemService, final boolean useSuggested,
diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
index 6c3b1234935a..396660816b45 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
@@ -16,10 +16,8 @@
package com.android.server.media;
-import android.app.ForegroundServiceDelegationOptions;
import android.app.Notification;
import android.media.AudioManager;
-import android.media.session.PlaybackState;
import android.os.ResultReceiver;
import android.view.KeyEvent;
@@ -63,13 +61,14 @@ public abstract class MediaSessionRecordImpl {
public abstract int getUserId();
/**
- * Get the {@link ForegroundServiceDelegationOptions} needed for notifying activity manager
- * service with changes in the {@link PlaybackState} for this session.
+ * Returns whether this session supports linked notifications.
*
- * @return the {@link ForegroundServiceDelegationOptions} needed for notifying the activity
- * manager service with changes in the {@link PlaybackState} for this session.
+ * <p>A notification is linked to a media session if it contains
+ * {@link android.app.Notification#EXTRA_MEDIA_SESSION}.
+ *
+ * @return {@code true} if this session supports linked notifications, {@code false} otherwise.
*/
- public abstract ForegroundServiceDelegationOptions getForegroundServiceDelegationOptions();
+ public abstract boolean hasLinkedNotificationSupport();
/**
* Check if this session has system priority and should receive media buttons before any other
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 2b29fbd9c5b5..e091fc62451b 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -30,7 +30,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.ForegroundServiceDelegationOptions;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -185,9 +184,9 @@ public class MediaSessionService extends SystemService implements Monitor {
/**
* Maps uid with all user engaged session records associated to it. It's used for calling
- * ActivityManagerInternal startFGS and stopFGS. This collection doesn't contain
- * MediaSession2Record(s). When the media session is paused, There exists a timeout before
- * calling stopFGS unlike usage logging which considers it disengaged immediately.
+ * ActivityManagerInternal internal api to set fgs active/inactive. This collection doesn't
+ * contain MediaSession2Record(s). When the media session is paused, There exists a timeout
+ * before setting FGS inactive unlike usage logging which considers it disengaged immediately.
*/
@GuardedBy("mLock")
private final Map<Integer, Set<MediaSessionRecordImpl>> mUserEngagedSessionsForFgs =
@@ -195,7 +194,7 @@ public class MediaSessionService extends SystemService implements Monitor {
/* Maps uid with all media notifications associated to it */
@GuardedBy("mLock")
- private final Map<Integer, Set<Notification>> mMediaNotifications = new HashMap<>();
+ private final Map<Integer, Set<StatusBarNotification>> mMediaNotifications = new HashMap<>();
/**
* Holds all {@link MediaSessionRecordImpl} which we've reported as being {@link
@@ -700,10 +699,10 @@ public class MediaSessionService extends SystemService implements Monitor {
MediaSessionRecordImpl mediaSessionRecord, boolean isUserEngaged) {
if (isUserEngaged) {
addUserEngagedSession(mediaSessionRecord);
- startFgsIfSessionIsLinkedToNotification(mediaSessionRecord);
+ setFgsActiveIfSessionIsLinkedToNotification(mediaSessionRecord);
} else {
removeUserEngagedSession(mediaSessionRecord);
- stopFgsIfNoSessionIsLinkedToNotification(mediaSessionRecord);
+ setFgsInactiveIfNoSessionIsLinkedToNotification(mediaSessionRecord);
}
}
@@ -737,17 +736,20 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- private void startFgsIfSessionIsLinkedToNotification(
+ private void setFgsActiveIfSessionIsLinkedToNotification(
MediaSessionRecordImpl mediaSessionRecord) {
- Log.d(TAG, "startFgsIfSessionIsLinkedToNotification: record=" + mediaSessionRecord);
+ Log.d(TAG, "setFgsIfSessionIsLinkedToNotification: record=" + mediaSessionRecord);
if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
return;
}
+ if (!mediaSessionRecord.hasLinkedNotificationSupport()) {
+ return;
+ }
synchronized (mLock) {
int uid = mediaSessionRecord.getUid();
- for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid, Set.of())) {
- if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
- startFgsDelegateLocked(mediaSessionRecord);
+ for (StatusBarNotification sbn : mMediaNotifications.getOrDefault(uid, Set.of())) {
+ if (mediaSessionRecord.isLinkedToNotification(sbn.getNotification())) {
+ setFgsActiveLocked(mediaSessionRecord, sbn);
return;
}
}
@@ -755,81 +757,92 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@GuardedBy("mLock")
- private void startFgsDelegateLocked(MediaSessionRecordImpl mediaSessionRecord) {
- ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
- mediaSessionRecord.getForegroundServiceDelegationOptions();
- if (foregroundServiceDelegationOptions == null) {
- return; // This record doesn't support FGS. Typically a MediaSession2 record.
- }
+ private void setFgsActiveLocked(MediaSessionRecordImpl mediaSessionRecord,
+ StatusBarNotification sbn) {
if (!mFgsAllowedMediaSessionRecords.add(mediaSessionRecord)) {
- return; // This record is already FGS-started.
+ return; // This record already is FGS-activated.
}
final long token = Binder.clearCallingIdentity();
try {
+ final String packageName = sbn.getPackageName();
+ final int uid = sbn.getUid();
+ final int notificationId = sbn.getId();
Log.i(
TAG,
TextUtils.formatSimple(
- "startFgsDelegate: pkg=%s uid=%d",
- foregroundServiceDelegationOptions.mClientPackageName,
- foregroundServiceDelegationOptions.mClientUid));
- mActivityManagerInternal.startForegroundServiceDelegate(
- foregroundServiceDelegationOptions, /* connection= */ null);
+ "setFgsActiveLocked: pkg=%s uid=%d notification=%d",
+ packageName, uid, notificationId));
+ mActivityManagerInternal.notifyActiveMediaForegroundService(packageName,
+ sbn.getUser().getIdentifier(), notificationId);
} finally {
Binder.restoreCallingIdentity(token);
}
}
- private void stopFgsIfNoSessionIsLinkedToNotification(
+ @Nullable
+ private StatusBarNotification getLinkedNotification(
+ int uid, MediaSessionRecordImpl record) {
+ synchronized (mLock) {
+ for (StatusBarNotification sbn :
+ mMediaNotifications.getOrDefault(uid, Set.of())) {
+ if (record.isLinkedToNotification(sbn.getNotification())) {
+ return sbn;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void setFgsInactiveIfNoSessionIsLinkedToNotification(
MediaSessionRecordImpl mediaSessionRecord) {
- Log.d(TAG, "stopFgsIfNoSessionIsLinkedToNotification: record=" + mediaSessionRecord);
+ Log.d(TAG, "setFgsIfNoSessionIsLinkedToNotification: record=" + mediaSessionRecord);
if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
return;
}
+ if (!mediaSessionRecord.hasLinkedNotificationSupport()) {
+ return;
+ }
synchronized (mLock) {
- int uid = mediaSessionRecord.getUid();
- ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
- mediaSessionRecord.getForegroundServiceDelegationOptions();
- if (foregroundServiceDelegationOptions == null) {
- return;
- }
-
+ final int uid = mediaSessionRecord.getUid();
for (MediaSessionRecordImpl record :
mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
- for (Notification mediaNotification :
+ for (StatusBarNotification sbn :
mMediaNotifications.getOrDefault(uid, Set.of())) {
- if (record.isLinkedToNotification(mediaNotification)) {
+ if (record.isLinkedToNotification(sbn.getNotification())) {
// A user engaged session linked with a media notification is found.
// We shouldn't call stop FGS in this case.
return;
}
}
}
-
- stopFgsDelegateLocked(mediaSessionRecord);
+ final StatusBarNotification linkedNotification =
+ getLinkedNotification(uid, mediaSessionRecord);
+ if (linkedNotification != null) {
+ setFgsInactiveLocked(mediaSessionRecord, linkedNotification);
+ }
}
}
@GuardedBy("mLock")
- private void stopFgsDelegateLocked(MediaSessionRecordImpl mediaSessionRecord) {
- ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
- mediaSessionRecord.getForegroundServiceDelegationOptions();
- if (foregroundServiceDelegationOptions == null) {
- return; // This record doesn't support FGS. Typically a MediaSession2 record.
- }
+ private void setFgsInactiveLocked(MediaSessionRecordImpl mediaSessionRecord,
+ StatusBarNotification sbn) {
if (!mFgsAllowedMediaSessionRecords.remove(mediaSessionRecord)) {
- return; // This record is not FGS-started. No need to stop it.
+ return; // This record is not FGS-active. No need to set inactive.
}
final long token = Binder.clearCallingIdentity();
try {
+ final String packageName = sbn.getPackageName();
+ final int userId = sbn.getUser().getIdentifier();
+ final int uid = sbn.getUid();
+ final int notificationId = sbn.getId();
Log.i(
TAG,
TextUtils.formatSimple(
- "stopFgsDelegate: pkg=%s uid=%d",
- foregroundServiceDelegationOptions.mClientPackageName,
- foregroundServiceDelegationOptions.mClientUid));
- mActivityManagerInternal.stopForegroundServiceDelegate(
- foregroundServiceDelegationOptions);
+ "setFgsInactiveLocked: pkg=%s uid=%d notification=%d",
+ packageName, uid, notificationId));
+ mActivityManagerInternal.notifyInactiveMediaForegroundService(packageName,
+ userId, notificationId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3259,18 +3272,18 @@ public class MediaSessionService extends SystemService implements Monitor {
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
super.onNotificationPosted(sbn);
- Notification postedNotification = sbn.getNotification();
int uid = sbn.getUid();
+ final Notification postedNotification = sbn.getNotification();
if (!postedNotification.isMediaNotification()) {
return;
}
synchronized (mLock) {
mMediaNotifications.putIfAbsent(uid, new HashSet<>());
- mMediaNotifications.get(uid).add(postedNotification);
+ mMediaNotifications.get(uid).add(sbn);
for (MediaSessionRecordImpl mediaSessionRecord :
mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
if (mediaSessionRecord.isLinkedToNotification(postedNotification)) {
- startFgsDelegateLocked(mediaSessionRecord);
+ setFgsActiveLocked(mediaSessionRecord, sbn);
return;
}
}
@@ -3286,9 +3299,9 @@ public class MediaSessionService extends SystemService implements Monitor {
return;
}
synchronized (mLock) {
- Set<Notification> uidMediaNotifications = mMediaNotifications.get(uid);
+ Set<StatusBarNotification> uidMediaNotifications = mMediaNotifications.get(uid);
if (uidMediaNotifications != null) {
- uidMediaNotifications.remove(removedNotification);
+ uidMediaNotifications.remove(sbn);
if (uidMediaNotifications.isEmpty()) {
mMediaNotifications.remove(uid);
}
@@ -3300,8 +3313,7 @@ public class MediaSessionService extends SystemService implements Monitor {
if (notificationRecord == null) {
return;
}
-
- stopFgsIfNoSessionIsLinkedToNotification(notificationRecord);
+ setFgsInactiveIfNoSessionIsLinkedToNotification(notificationRecord);
}
}