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

Commit 9839809a authored by Toni Heidenreich's avatar Toni Heidenreich Committed by Automerger Merge Worker
Browse files

Merge changes Ia815d9d8,I30ce0527 into main am: f1e6d28a am: 3e8c752d

parents d50a3ea1 3e8c752d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -160,6 +160,11 @@ public class MediaSession2Record extends MediaSessionRecordImpl {
        // NA as MediaSession2 doesn't support UserEngagementStates for FGS.
    }

    @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) {
+49 −29
Original line number Diff line number Diff line
@@ -230,51 +230,49 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
    private final Runnable mUserEngagementTimeoutExpirationRunnable =
            () -> {
                synchronized (mLock) {
                    updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
                    updateUserEngagedStateIfNeededLocked(
                            /* isTimeoutExpired= */ true,
                            /* isGlobalPrioritySessionActive= */ false);
                }
            };

    @GuardedBy("mLock")
    private @UserEngagementState int mUserEngagementState = USER_DISENGAGED;

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

    /**
     * Indicates that the session is active and in one of the user engaged states.
     * Indicates that the session is {@linkplain MediaSession#isActive() active} and in one of the
     * {@linkplain PlaybackState#isActive() active 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.
     * Indicates that the session is {@linkplain MediaSession#isActive() active} and has recently
     * switched to one of the {@linkplain PlaybackState#isActive() inactive states}.
     *
     * @see #updateUserEngagedStateIfNeededLocked(boolean)
     */
    private static final int USER_TEMPORARY_ENGAGED = 1;
    private static final int USER_TEMPORARILY_ENGAGED = 1;

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

    /**
     * Indicates the duration of the temporary engaged states, in milliseconds.
     * Indicates the duration of the temporary engaged state, in milliseconds.
     *
     * <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}.
     * <p>When switching to an {@linkplain PlaybackState#isActive() inactive state}, the user is
     * treated as 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.
     */
    private static final int TEMP_USER_ENGAGED_TIMEOUT_MS = 600000;

@@ -598,7 +596,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);
        }
    }
@@ -615,6 +614,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.
     *
@@ -1063,21 +1080,20 @@ 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;
        }
        int oldUserEngagedState = mUserEngagementState;
        int newUserEngagedState;
        if (!isActive() || mPlaybackState == null || mDestroyed) {
        if (!isActive() || mPlaybackState == null) {
            newUserEngagedState = USER_DISENGAGED;
        } else if (isActive() && mPlaybackState.isActive()) {
        } else if (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 if (oldUserEngagedState == USER_PERMANENTLY_ENGAGED
                || (oldUserEngagedState == USER_TEMPORARILY_ENGAGED && !isTimeoutExpired)) {
            newUserEngagedState = USER_TEMPORARILY_ENGAGED;
        } else {
            newUserEngagedState = USER_DISENGAGED;
        }
@@ -1086,7 +1102,7 @@ public class MediaSessionRecord extends MediaSessionRecordImpl implements IBinde
        }

        mUserEngagementState = newUserEngagedState;
        if (newUserEngagedState == USER_TEMPORARY_ENGAGED) {
        if (newUserEngagedState == USER_TEMPORARILY_ENGAGED && !isGlobalPrioritySessionActive) {
            mHandler.postDelayed(
                    mUserEngagementTimeoutExpirationRunnable, TEMP_USER_ENGAGED_TIMEOUT_MS);
        } else {
@@ -1141,9 +1157,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 {
@@ -1300,9 +1318,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 {
+4 −0
Original line number Diff line number Diff line
@@ -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;
+35 −2
Original line number Diff line number Diff line
@@ -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,9 +676,12 @@ public class MediaSessionService extends SystemService implements Monitor {

        if (mGlobalPrioritySession == session) {
            mGlobalPrioritySession = null;
            if (session.isActive() && user != null) {
            if (session.isActive()) {
                if (user != null) {
                    user.pushAddressedPlayerChangedLocked();
                }
                mHandler.post(this::notifyGlobalPrioritySessionActiveChanged);
            }
        } else {
            if (user != null) {
                user.mPriorityStack.removeSession(session);