Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74317074 authored by Santiago Seifert's avatar Santiago Seifert
Browse files

Avoid multiple calls to start/stop FGS for the same session record

Shouldn't be an issue, as they should both be idempotent operations, but
following the principle of robustness, this CL avoids calling
startingFGSDelegate (or stop) multiple times in a row for the same
session.

Bug: b/295518668
Test: atest CtsMediaBetterTogetherTestCases
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
Change-Id: Ie4a4d2e3b49329f5c4480f1ca4c2531b86fe39a2
parent 209e664c
Loading
Loading
Loading
Loading
+35 −11
Original line number Original line Diff line number Diff line
@@ -197,6 +197,16 @@ public class MediaSessionService extends SystemService implements Monitor {
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final Map<Integer, Set<Notification>> mMediaNotifications = new HashMap<>();
    private final Map<Integer, Set<Notification>> mMediaNotifications = new HashMap<>();


    /**
     * Holds all {@link MediaSessionRecordImpl} which we've reported as being {@link
     * ActivityManagerInternal#startForegroundServiceDelegate user engaged}.
     *
     * <p>This map simply prevents invoking {@link
     * ActivityManagerInternal#startForegroundServiceDelegate} more than once per session.
     */
    @GuardedBy("mLock")
    private final Set<MediaSessionRecordImpl> mFgsAllowedMediaSessionRecords = new HashSet<>();

    // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
    // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
    // It's always not null after the MediaSessionService is started.
    // It's always not null after the MediaSessionService is started.
    private FullUserRecord mCurrentFullUserRecord;
    private FullUserRecord mCurrentFullUserRecord;
@@ -704,15 +714,23 @@ public class MediaSessionService extends SystemService implements Monitor {
            int uid = mediaSessionRecord.getUid();
            int uid = mediaSessionRecord.getUid();
            for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid, Set.of())) {
            for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid, Set.of())) {
                if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
                if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
                    startFgsDelegate(mediaSessionRecord.getForegroundServiceDelegationOptions());
                    startFgsDelegateLocked(mediaSessionRecord);
                    return;
                    return;
                }
                }
            }
            }
        }
        }
    }
    }


    private void startFgsDelegate(
    @GuardedBy("mLock")
            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions) {
    private void startFgsDelegateLocked(MediaSessionRecordImpl mediaSessionRecord) {
        ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                mediaSessionRecord.getForegroundServiceDelegationOptions();
        if (foregroundServiceDelegationOptions == null) {
            return; // This record doesn't support FGS. Typically a MediaSession2 record.
        }
        if (!mFgsAllowedMediaSessionRecords.add(mediaSessionRecord)) {
            return; // This record is already FGS-started.
        }
        final long token = Binder.clearCallingIdentity();
        final long token = Binder.clearCallingIdentity();
        try {
        try {
            Log.i(
            Log.i(
@@ -754,12 +772,21 @@ public class MediaSessionService extends SystemService implements Monitor {
                }
                }
            }
            }


            stopFgsDelegate(foregroundServiceDelegationOptions);
            stopFgsDelegateLocked(mediaSessionRecord);
        }
    }

    @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.
        }
        }
        if (!mFgsAllowedMediaSessionRecords.remove(mediaSessionRecord)) {
            return; // This record is not FGS-started. No need to stop it.
        }
        }


    private void stopFgsDelegate(
            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions) {
        final long token = Binder.clearCallingIdentity();
        final long token = Binder.clearCallingIdentity();
        try {
        try {
            Log.i(
            Log.i(
@@ -3209,11 +3236,8 @@ public class MediaSessionService extends SystemService implements Monitor {
                mMediaNotifications.get(uid).add(postedNotification);
                mMediaNotifications.get(uid).add(postedNotification);
                for (MediaSessionRecordImpl mediaSessionRecord :
                for (MediaSessionRecordImpl mediaSessionRecord :
                        mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                        mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                    ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                    if (mediaSessionRecord.isLinkedToNotification(postedNotification)) {
                            mediaSessionRecord.getForegroundServiceDelegationOptions();
                        startFgsDelegateLocked(mediaSessionRecord);
                    if (foregroundServiceDelegationOptions != null
                            && mediaSessionRecord.isLinkedToNotification(postedNotification)) {
                        startFgsDelegate(foregroundServiceDelegationOptions);
                        return;
                        return;
                    }
                    }
                }
                }