diff options
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); } } |