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

Commit 8b96e849 authored by Chaitanya Cheemala's avatar Chaitanya Cheemala Committed by Android (Google) Code Review
Browse files

Revert "Implement Paused state logic for FGS"

This reverts commit f11b5016.

Reason for revert: Likely culprit for b/333370745  - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted.

Change-Id: Ib2fb1ee00703587dfdb31ef3b5e568e3bf2dfc81
parent f11b5016
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -80,7 +80,4 @@ interface ISessionManager {
    boolean hasCustomMediaSessionPolicyProvider(String componentName);
    int getSessionPolicies(in MediaSession.Token token);
    void setSessionPolicies(in MediaSession.Token token, int policies);

    // For testing of temporarily engaged sessions.
    void expireTempEngagedSessions();
}
+0 −5
Original line number Diff line number Diff line
@@ -156,11 +156,6 @@ public class MediaSession2Record extends MediaSessionRecordImpl {
        }
    }

    @Override
    public void expireTempEngaged() {
        // 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) {
+2 −97
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import static android.media.session.MediaController.PlaybackInfo.PLAYBACK_TYPE_L
import static android.media.session.MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -86,8 +85,6 @@ import com.android.server.LocalServices;
import com.android.server.uri.UriGrantsManagerInternal;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -228,49 +225,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde

    private int mPolicies;

    private @UserEngagementState int mUserEngagementState = USER_DISENGAGED;

    @IntDef({USER_PERMANENTLY_ENGAGED, USER_TEMPORARY_ENGAGED, USER_DISENGAGED})
    @Retention(RetentionPolicy.SOURCE)
    private @interface UserEngagementState {}

    /**
     * Indicates that the session is active and in one of the user engaged states.
     *
     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
     */
    private static final int USER_PERMANENTLY_ENGAGED = 0;

    /**
     * Indicates that the session is active and in {@link PlaybackState#STATE_PAUSED} state.
     *
     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
     */
    private static final int USER_TEMPORARY_ENGAGED = 1;

    /**
     * Indicates that the session is either not active or in one of the user disengaged states
     *
     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
     */
    private static final int USER_DISENGAGED = 2;

    /**
     * Indicates the duration of the temporary engaged states.
     *
     * <p>Some {@link MediaSession} states like {@link PlaybackState#STATE_PAUSED} are temporarily
     * engaged, meaning the corresponding session is only considered in an engaged state for the
     * duration of this timeout, and only if coming from an engaged state.
     *
     * <p>For example, if a session is transitioning from a user-engaged state {@link
     * PlaybackState#STATE_PLAYING} to a temporary user-engaged state {@link
     * PlaybackState#STATE_PAUSED}, then the session will be considered in a user-engaged state for
     * the duration of this timeout, starting at the transition instant. However, a temporary
     * user-engaged state is not considered user-engaged when transitioning from a non-user engaged
     * state {@link PlaybackState#STATE_STOPPED}.
     */
    private static final int TEMP_USER_ENGAGED_TIMEOUT = 600000;

    public MediaSessionRecord(
            int ownerPid,
            int ownerUid,
@@ -594,7 +548,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
            mSessionCb.mCb.asBinder().unlinkToDeath(this, 0);
            mDestroyed = true;
            mPlaybackState = null;
            updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
            mHandler.post(MessageHandler.MSG_DESTROYED);
        }
    }
@@ -606,12 +559,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
        }
    }

    @Override
    public void expireTempEngaged() {
        mHandler.removeCallbacks(mHandleTempEngagedSessionTimeout);
        updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
    }

    /**
     * Sends media button.
     *
@@ -1171,11 +1118,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
                }
            };

    private final Runnable mHandleTempEngagedSessionTimeout =
            () -> {
                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
            };

    @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
    private static boolean componentNameExists(
            @NonNull ComponentName componentName, @NonNull Context context, int userId) {
@@ -1192,40 +1134,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
        return !resolveInfos.isEmpty();
    }

    private void updateUserEngagedStateIfNeededLocked(boolean isTimeoutExpired) {
        int oldUserEngagedState = mUserEngagementState;
        int newUserEngagedState;
        if (!isActive() || mPlaybackState == null) {
            newUserEngagedState = USER_DISENGAGED;
        } else if (isActive() && mPlaybackState.isActive()) {
            newUserEngagedState = USER_PERMANENTLY_ENGAGED;
        } else if (mPlaybackState.getState() == PlaybackState.STATE_PAUSED) {
            newUserEngagedState =
                    oldUserEngagedState == USER_PERMANENTLY_ENGAGED || !isTimeoutExpired
                            ? USER_TEMPORARY_ENGAGED
                            : USER_DISENGAGED;
        } else {
            newUserEngagedState = USER_DISENGAGED;
        }
        if (oldUserEngagedState == newUserEngagedState) {
            return;
        }

        if (newUserEngagedState == USER_TEMPORARY_ENGAGED) {
            mHandler.postDelayed(mHandleTempEngagedSessionTimeout, TEMP_USER_ENGAGED_TIMEOUT);
        } else if (oldUserEngagedState == USER_TEMPORARY_ENGAGED) {
            mHandler.removeCallbacks(mHandleTempEngagedSessionTimeout);
        }

        boolean wasUserEngaged = oldUserEngagedState != USER_DISENGAGED;
        boolean isNowUserEngaged = newUserEngagedState != USER_DISENGAGED;
        mUserEngagementState = newUserEngagedState;
        if (wasUserEngaged != isNowUserEngaged) {
            mService.onSessionUserEngagementStateChange(
                    /* mediaSessionRecord= */ this, /* isUserEngaged= */ isNowUserEngaged);
        }
    }

    private final class SessionStub extends ISession.Stub {
        @Override
        public void destroySession() throws RemoteException {
@@ -1263,10 +1171,8 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
                        .logFgsApiEnd(ActivityManager.FOREGROUND_SERVICE_API_TYPE_MEDIA_PLAYBACK,
                                callingUid, callingPid);
            }
            synchronized (mLock) {

            mIsActive = active;
                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
            }
            long token = Binder.clearCallingIdentity();
            try {
                mService.onSessionActiveStateChanged(MediaSessionRecord.this, mPlaybackState);
@@ -1424,7 +1330,6 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
                    && TRANSITION_PRIORITY_STATES.contains(newState));
            synchronized (mLock) {
                mPlaybackState = state;
                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
            }
            final long token = Binder.clearCallingIdentity();
            try {
+0 −6
Original line number Diff line number Diff line
@@ -196,12 +196,6 @@ public abstract class MediaSessionRecordImpl {
     */
    public abstract boolean isClosed();

    /**
     * Note: This method is only used for testing purposes If the session is temporary engaged, the
     * timeout will expire and it will become disengaged.
     */
    public abstract void expireTempEngaged();

    @Override
    public final boolean equals(Object o) {
        if (this == o) return true;
+60 −85
Original line number Diff line number Diff line
@@ -367,13 +367,11 @@ public class MediaSessionService extends SystemService implements Monitor {
            }
            boolean isUserEngaged = isUserEngaged(record, playbackState);

            Log.d(
                    TAG,
                    "onSessionActiveStateChanged:"
                            + " record="
                            + record
                            + " playbackState="
                            + playbackState);
            Log.d(TAG, "onSessionActiveStateChanged: "
                    + "record=" + record
                    + "playbackState=" + playbackState
                    + "allowRunningInForeground=" + isUserEngaged);
            setForegroundServiceAllowance(record, /* allowRunningInForeground= */ isUserEngaged);
            reportMediaInteractionEvent(record, isUserEngaged);
            mHandler.postSessionsChanged(record);
        }
@@ -481,13 +479,11 @@ public class MediaSessionService extends SystemService implements Monitor {
            }
            user.mPriorityStack.onPlaybackStateChanged(record, shouldUpdatePriority);
            boolean isUserEngaged = isUserEngaged(record, playbackState);
            Log.d(
                    TAG,
                    "onSessionPlaybackStateChanged:"
                            + " record="
                            + record
                            + " playbackState="
                            + playbackState);
            Log.d(TAG, "onSessionPlaybackStateChanged: "
                    + "record=" + record
                    + "playbackState=" + playbackState
                    + "allowRunningInForeground=" + isUserEngaged);
            setForegroundServiceAllowance(record, /* allowRunningInForeground= */ isUserEngaged);
            reportMediaInteractionEvent(record, isUserEngaged);
        }
    }
@@ -654,54 +650,33 @@ public class MediaSessionService extends SystemService implements Monitor {
        session.close();

        Log.d(TAG, "destroySessionLocked: record=" + session);

        setForegroundServiceAllowance(session, /* allowRunningInForeground= */ false);
        reportMediaInteractionEvent(session, /* userEngaged= */ false);
        mHandler.postSessionsChanged(session);
    }

    void onSessionUserEngagementStateChange(
            MediaSessionRecordImpl mediaSessionRecord, boolean isUserEngaged) {
        if (isUserEngaged) {
            addUserEngagedSession(mediaSessionRecord);
            startFgsIfSessionIsLinkedToNotification(mediaSessionRecord);
        } else {
            removeUserEngagedSession(mediaSessionRecord);
            stopFgsIfNoSessionIsLinkedToNotification(mediaSessionRecord);
        }
    }

    private void addUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
        synchronized (mLock) {
            int uid = mediaSessionRecord.getUid();
            mUserEngagedSessionsForFgs.putIfAbsent(uid, new HashSet<>());
            mUserEngagedSessionsForFgs.get(uid).add(mediaSessionRecord);
        }
    }

    private void removeUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
        synchronized (mLock) {
            int uid = mediaSessionRecord.getUid();
            Set<MediaSessionRecordImpl> mUidUserEngagedSessionsForFgs =
                    mUserEngagedSessionsForFgs.get(uid);
            if (mUidUserEngagedSessionsForFgs == null) {
    private void setForegroundServiceAllowance(
            MediaSessionRecordImpl record, boolean allowRunningInForeground) {
        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
            return;
        }

            mUidUserEngagedSessionsForFgs.remove(mediaSessionRecord);
            if (mUidUserEngagedSessionsForFgs.isEmpty()) {
                mUserEngagedSessionsForFgs.remove(uid);
        ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                record.getForegroundServiceDelegationOptions();
        if (foregroundServiceDelegationOptions == null) {
            return;
        }
        if (allowRunningInForeground) {
            onUserSessionEngaged(record);
        } else {
            onUserDisengaged(record);
        }
    }

    private void startFgsIfSessionIsLinkedToNotification(
            MediaSessionRecordImpl mediaSessionRecord) {
        Log.d(TAG, "startFgsIfSessionIsLinkedToNotification: record=" + mediaSessionRecord);
        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
            return;
        }
    private void onUserSessionEngaged(MediaSessionRecordImpl mediaSessionRecord) {
        synchronized (mLock) {
            int uid = mediaSessionRecord.getUid();
            mUserEngagedSessionsForFgs.putIfAbsent(uid, new HashSet<>());
            mUserEngagedSessionsForFgs.get(uid).add(mediaSessionRecord);
            for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid, Set.of())) {
                if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
                    mActivityManagerInternal.startForegroundServiceDelegate(
@@ -713,34 +688,30 @@ public class MediaSessionService extends SystemService implements Monitor {
        }
    }

    private void stopFgsIfNoSessionIsLinkedToNotification(
            MediaSessionRecordImpl mediaSessionRecord) {
        Log.d(TAG, "stopFgsIfNoSessionIsLinkedToNotification: record=" + mediaSessionRecord);
        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
            return;
        }
    private void onUserDisengaged(MediaSessionRecordImpl mediaSessionRecord) {
        synchronized (mLock) {
            int uid = mediaSessionRecord.getUid();
            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                    mediaSessionRecord.getForegroundServiceDelegationOptions();
            if (foregroundServiceDelegationOptions == null) {
                return;
            if (mUserEngagedSessionsForFgs.containsKey(uid)) {
                mUserEngagedSessionsForFgs.get(uid).remove(mediaSessionRecord);
                if (mUserEngagedSessionsForFgs.get(uid).isEmpty()) {
                    mUserEngagedSessionsForFgs.remove(uid);
                }
            }

            for (MediaSessionRecordImpl record :
            boolean shouldStopFgs = true;
            for (MediaSessionRecordImpl sessionRecord :
                    mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                for (Notification mediaNotification :
                        mMediaNotifications.getOrDefault(uid, Set.of())) {
                    if (record.isLinkedToNotification(mediaNotification)) {
                        // A user engaged session linked with a media notification is found.
                        // We shouldn't call stop FGS in this case.
                        return;
                for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid,
                        Set.of())) {
                    if (sessionRecord.isLinkedToNotification(mediaNotification)) {
                        shouldStopFgs = false;
                    }
                }
            }

            if (shouldStopFgs) {
                mActivityManagerInternal.stopForegroundServiceDelegate(
                    foregroundServiceDelegationOptions);
                        mediaSessionRecord.getForegroundServiceDelegationOptions());
            }
        }
    }

@@ -2531,6 +2502,7 @@ public class MediaSessionService extends SystemService implements Monitor {
            }
            MediaSessionRecord session = null;
            MediaButtonReceiverHolder mediaButtonReceiverHolder = null;

            if (mCustomMediaKeyDispatcher != null) {
                MediaSession.Token token = mCustomMediaKeyDispatcher.getMediaSession(
                        keyEvent, uid, asSystemService);
@@ -2658,18 +2630,6 @@ public class MediaSessionService extends SystemService implements Monitor {
                    && streamType <= AudioManager.STREAM_NOTIFICATION;
        }

        @Override
        public void expireTempEngagedSessions() {
            synchronized (mLock) {
                for (Set<MediaSessionRecordImpl> uidSessions :
                        mUserEngagedSessionsForFgs.values()) {
                    for (MediaSessionRecordImpl sessionRecord : uidSessions) {
                        sessionRecord.expireTempEngaged();
                    }
                }
            }
        }

        private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
            private final String mPackageName;
            private final int mPid;
@@ -3167,6 +3127,7 @@ public class MediaSessionService extends SystemService implements Monitor {
            super.onNotificationPosted(sbn);
            Notification postedNotification = sbn.getNotification();
            int uid = sbn.getUid();

            if (!postedNotification.isMediaNotification()) {
                return;
            }
@@ -3177,8 +3138,8 @@ public class MediaSessionService extends SystemService implements Monitor {
                        mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                    ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                            mediaSessionRecord.getForegroundServiceDelegationOptions();
                    if (foregroundServiceDelegationOptions != null
                            && mediaSessionRecord.isLinkedToNotification(postedNotification)) {
                    if (mediaSessionRecord.isLinkedToNotification(postedNotification)
                            && foregroundServiceDelegationOptions != null) {
                        mActivityManagerInternal.startForegroundServiceDelegate(
                                foregroundServiceDelegationOptions,
                                /* connection= */ null);
@@ -3212,7 +3173,21 @@ public class MediaSessionService extends SystemService implements Monitor {
                    return;
                }

                stopFgsIfNoSessionIsLinkedToNotification(notificationRecord);
                boolean shouldStopFgs = true;
                for (MediaSessionRecordImpl mediaSessionRecord :
                        mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                    for (Notification mediaNotification :
                            mMediaNotifications.getOrDefault(uid, Set.of())) {
                        if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
                            shouldStopFgs = false;
                        }
                    }
                }
                if (shouldStopFgs
                        && notificationRecord.getForegroundServiceDelegationOptions() != null) {
                    mActivityManagerInternal.stopForegroundServiceDelegate(
                            notificationRecord.getForegroundServiceDelegationOptions());
                }
            }
        }

Loading