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

Commit 5ce93da6 authored by Evan Rosky's avatar Evan Rosky
Browse files

Remove redundant sleep-token tracking

We ended up keeping multiple lists of sleep tokens
around which is wasteful and also makes it harder to
reason about how sleep management works.

At the end of the day, we just need a list of tokens per
display. This CL removes the extra lists and tracking.
Additionally, this revealed that the Acquirer was
re-entering the lock when it didn't need to. This is
important since cause/effect tracking is based on this
atomicity so now we can safely track causes of sleep/wake.

Bug: 423701190
Test: code-removal, so existing tests
Flag: EXEMPT: mechanical refactor
Change-Id: Iac6638ca217eb7f1c641d97b02bbd469e109b5fa
parent e8378edc
Loading
Loading
Loading
Loading
+0 −39
Original line number Diff line number Diff line
@@ -4597,7 +4597,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            mTaskOrganizerController.dump(pw, "  ");
            mVisibleActivityProcessTracker.dump(pw, "  ");
            mActiveUids.dump(pw, "  ");
            pw.println("  SleepTokens=" + mRootWindowContainer.mSleepTokens);
            if (mDemoteTopAppReasons != 0) {
                pw.println("  mDemoteTopAppReasons=" + mDemoteTopAppReasons);
            }
@@ -4763,13 +4762,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        final long sleepToken = proto.start(ActivityManagerServiceDumpProcessesProto.SLEEP_STATUS);
        proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.WAKEFULNESS,
                PowerManagerInternal.wakefulnessToProtoEnum(wakeFullness));
        final int tokenSize = mRootWindowContainer.mSleepTokens.size();
        for (int i = 0; i < tokenSize; i++) {
            final RootWindowContainer.SleepToken st =
                    mRootWindowContainer.mSleepTokens.valueAt(i);
            proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS,
                    st.toString());
        }
        proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEPING, mSleeping);
        proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SHUTTING_DOWN,
                mShuttingDown);
@@ -5313,36 +5305,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        EventLogTags.writeWmSetResumedActivity(r.mUserId, r.shortComponentName, reason);
    }

    final class SleepTokenAcquirer {
        private final String mTag;
        private final SparseArray<RootWindowContainer.SleepToken> mSleepTokens =
                new SparseArray<>();

        SleepTokenAcquirer(@NonNull String tag) {
            mTag = tag;
        }

        void acquire(int displayId) {
            synchronized (mGlobalLock) {
                if (!mSleepTokens.contains(displayId)) {
                    mSleepTokens.append(displayId,
                            mRootWindowContainer.createSleepToken(mTag, displayId));
                    updateSleepIfNeededLocked();
                }
            }
        }

        void release(int displayId) {
            synchronized (mGlobalLock) {
                final RootWindowContainer.SleepToken token = mSleepTokens.get(displayId);
                if (token != null) {
                    mRootWindowContainer.removeSleepToken(token);
                    mSleepTokens.remove(displayId);
                }
            }
        }
    }

    void updateSleepIfNeededLocked() {
        final boolean shouldSleep = !mRootWindowContainer.hasAwakeDisplay();
        final boolean wasSleeping = mSleeping;
@@ -7123,7 +7085,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                if (dumpPackage == null) {
                    pw.println("  mWakefulness="
                            + PowerManagerInternal.wakefulnessToString(wakefulness));
                    pw.println("  mSleepTokens=" + mRootWindowContainer.mSleepTokens);
                    if (mRunningVoice != null) {
                        pw.println("  mRunningVoice=" + mRunningVoice);
                        pw.println("  mVoiceWakeLock" + mVoiceWakeLock);
+47 −11
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_IME;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SCREEN_ON;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SLEEP_TOKEN;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WALLPAPER;
import static com.android.internal.protolog.WmProtoLogGroups.WM_SHOW_TRANSACTIONS;
import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
@@ -315,6 +316,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                }
            };

    // The tag for the token to put root tasks on the displays to sleep.
    static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";

    final ActivityTaskManagerService mAtmService;

    /**
@@ -740,7 +744,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    /** Array of all UIDs that are present on the display. */
    private IntArray mDisplayAccessUIDs = new IntArray();

    /** All tokens used to put activities on this root task to sleep (including mOffToken) */
    /** All tokens used to put activities on this display to sleep (including mOffToken) */
    final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>();

    private boolean mSleeping;
@@ -3486,7 +3490,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mDisplayRotation.onDisplayRemoved();
            mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId);
            mRootWindowContainer.mTaskSupervisor
                    .getKeyguardController().onDisplayRemoved(mDisplayId);
                    .getKeyguardController().onDisplayRemoved(this);
            mWallpaperController.resetLargestDisplay(mDisplay);
            mWmService.mDisplayWindowSettings.onDisplayRemoved(this);
            getDisplayUiContext().unregisterComponentCallbacks(mSysUiContextConfigCallback);
@@ -6170,9 +6174,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        final int displayState = mDisplayInfo.state;
        if (displayId != DEFAULT_DISPLAY) {
            if (displayState == Display.STATE_OFF) {
                mRootWindowContainer.mDisplayOffTokenAcquirer.acquire(mDisplayId);
                addSleepToken(DISPLAY_OFF_SLEEP_TOKEN_TAG);
            } else if (displayState == Display.STATE_ON) {
                mRootWindowContainer.mDisplayOffTokenAcquirer.release(mDisplayId);
                removeSleepToken(DISPLAY_OFF_SLEEP_TOKEN_TAG);
            }
            ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
                    "Content Recording: Display %d state was (%d), is now (%d), so update "
@@ -6508,8 +6512,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mDisplayPolicy.release();

        if (!mAllSleepTokens.isEmpty()) {
            mAllSleepTokens.forEach(token ->
                    mRootWindowContainer.mSleepTokens.remove(token.mHashKey));
            mAllSleepTokens.clear();
            mAtmService.updateSleepIfNeededLocked();
        }
@@ -6549,6 +6551,44 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return mWmService.mDisplayWindowSettings.getRemoveContentModeLocked(this);
    }

    boolean hasSleepToken(String tag) {
        for (int i = mAllSleepTokens.size() - 1; i >= 0; i--) {
            if (tag.equals(mAllSleepTokens.get(i).mTag)) {
                return true;
            }
        }
        return false;
    }

    boolean addSleepTokenOnly(String tag) {
        if (hasSleepToken(tag)) return false;
        mAllSleepTokens.add(new RootWindowContainer.SleepToken(tag));
        ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Add SleepToken: tag=%s, displayId=%d", tag, mDisplayId);
        return true;
    }

    void addSleepToken(String tag) {
        if (!addSleepTokenOnly(tag)) return;
        mAtmService.updateSleepIfNeededLocked();
    }

    void removeSleepToken(String tag) {
        ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Remove SleepToken: tag=%s, displayId=%d",
                tag, mDisplayId);
        int idx = mAllSleepTokens.size() - 1;
        for (; idx >= 0; idx--) {
            if (tag.equals(mAllSleepTokens.get(idx).mTag)) break;
        }
        if (idx < 0) {
            Slog.d(TAG, "Remove non-existent sleep token: " + tag + " from " + Debug.getCallers(6));
            return;
        }
        mAllSleepTokens.remove(idx);
        if (mAllSleepTokens.isEmpty()) {
            mAtmService.updateSleepIfNeededLocked();
        }
    }

    boolean shouldSleep() {
        return (getRootTaskCount() == 0 || !mAllSleepTokens.isEmpty())
                && (mAtmService.mRunningVoice == null);
@@ -6556,11 +6596,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

    /** Returns {@code} if the screen is not in a fully interactive state. */
    boolean isScreenSleeping() {
        for (int i = mAllSleepTokens.size() - 1; i >= 0; i--) {
            if (mAllSleepTokens.get(i).isScreenOff()) {
                return true;
            }
        }
        if (hasSleepToken(DISPLAY_OFF_SLEEP_TOKEN_TAG)) return true;
        // If AOD is active, there may be only keyguard sleep token but awake state is false.
        // Then still treat the case as sleeping.
        return !mAllSleepTokens.isEmpty() && !mDisplayPolicy.isAwake();
+3 −3
Original line number Diff line number Diff line
@@ -836,7 +836,7 @@ public class DisplayPolicy {
                // acquire sleep token if screen is off.
                if (!mScreenOnEarly && !mScreenOnFully && !mDisplayContent.isSleeping()) {
                    Slog.w(TAG, "Late acquire sleep token for " + mDisplayContent);
                    mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId);
                    mDisplayContent.addSleepToken(DisplayContent.DISPLAY_OFF_SLEEP_TOKEN_TAG);
                }
            }
        }
@@ -885,7 +885,7 @@ public class DisplayPolicy {
    public void screenTurningOn(ScreenOnListener screenOnListener) {
        WindowProcessController visibleDozeUiProcess = null;
        synchronized (mLock) {
            mService.mRoot.mDisplayOffTokenAcquirer.release(mDisplayContent.mDisplayId);
            mDisplayContent.removeSleepToken(DisplayContent.DISPLAY_OFF_SLEEP_TOKEN_TAG);
            mScreenOnEarly = true;
            mScreenOnFully = false;
            mKeyguardDrawComplete = false;
@@ -914,7 +914,7 @@ public class DisplayPolicy {
    public void screenTurnedOff(boolean acquireSleepToken) {
        synchronized (mLock) {
            if (acquireSleepToken) {
                mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId);
                mDisplayContent.addSleepToken(DisplayContent.DISPLAY_OFF_SLEEP_TOKEN_TAG);
            }
            mScreenOnEarly = false;
            mScreenOnFully = false;
+20 −24
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_W
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.internal.perfetto.protos.Windowmanagerservice.KeyguardPerDisplayProto;
import android.os.IBinder;
@@ -91,7 +92,6 @@ class KeyguardController {
    private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
    private final ActivityTaskManagerService mService;
    private RootWindowContainer mRootWindowContainer;
    private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
    private boolean mWaitingForWakeTransition;
    private Transition.ReadyCondition mWaitAodHide = null;

@@ -99,7 +99,6 @@ class KeyguardController {
            ActivityTaskSupervisor taskSupervisor) {
        mService = service;
        mTaskSupervisor = taskSupervisor;
        mSleepTokenAcquirer = mService.new SleepTokenAcquirer(KEYGUARD_SLEEP_TOKEN_TAG);
    }

    void setWindowManager(WindowManagerService windowManager) {
@@ -463,19 +462,20 @@ class KeyguardController {
     * @param topActivity the activity that controls the state whether keyguard should
     *      be occluded. That is the activity to be shown on top of keyguard if it requests so.
     */
    private void handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity) {
    private void handleOccludedChanged(@NonNull DisplayContent dc,
            @Nullable ActivityRecord topActivity) {
        final int displayId = dc.mDisplayId;
        // TODO(b/113840485): Handle app transition for individual display, and apply occluded
        // state change to secondary displays.
        // For now, only default display fully supports occluded change. Other displays only
        // updates keyguard sleep token on that display.
        if (displayId != DEFAULT_DISPLAY) {
            updateKeyguardSleepToken(displayId);
            updateKeyguardSleepToken(dc);
            return;
        }

        final TransitionController tc = mRootWindowContainer.mTransitionController;
        final KeyguardDisplayState state = getDisplayState(displayId);
        final DisplayContent dc = mRootWindowContainer.getDisplayContent(displayId);

        final boolean locked = isKeyguardLocked(displayId);
        final boolean executeTransition = !tc.isShellTransitionsEnabled();
@@ -517,7 +517,7 @@ class KeyguardController {
                    mWindowManager.mPolicy.applyKeyguardOcclusionChange();
                }
            }
            updateKeyguardSleepToken(displayId);
            updateKeyguardSleepToken(dc);
            if (executeTransition) {
                dc.executeAppTransition();
            }
@@ -583,33 +583,32 @@ class KeyguardController {
        for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
             displayNdx >= 0; displayNdx--) {
            final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
            updateKeyguardSleepToken(display.mDisplayId);
            updateKeyguardSleepToken(display);
        }
    }

    private void updateKeyguardSleepToken(int displayId) {
        final KeyguardDisplayState state = getDisplayState(displayId);
        if (isKeyguardUnoccludedOrAodShowing(displayId)) {
            state.mSleepTokenAcquirer.acquire(displayId);
    private void updateKeyguardSleepToken(DisplayContent display) {
        if (isKeyguardUnoccludedOrAodShowing(display.mDisplayId)) {
            display.addSleepToken(KEYGUARD_SLEEP_TOKEN_TAG);
        } else {
            state.mSleepTokenAcquirer.release(displayId);
            display.removeSleepToken(KEYGUARD_SLEEP_TOKEN_TAG);
        }
    }

    private KeyguardDisplayState getDisplayState(int displayId) {
        KeyguardDisplayState state = mDisplayStates.get(displayId);
        if (state == null) {
            state = new KeyguardDisplayState(mService, displayId, mSleepTokenAcquirer);
            state = new KeyguardDisplayState(mService, displayId);
            mDisplayStates.append(displayId, state);
        }
        return state;
    }

    void onDisplayRemoved(int displayId) {
        final KeyguardDisplayState state = mDisplayStates.get(displayId);
    void onDisplayRemoved(@NonNull DisplayContent dc) {
        final KeyguardDisplayState state = mDisplayStates.get(dc.mDisplayId);
        if (state != null) {
            state.onRemoved();
            mDisplayStates.remove(displayId);
            state.onRemoved(dc);
            mDisplayStates.remove(dc.mDisplayId);
        }
    }

@@ -701,20 +700,17 @@ class KeyguardController {

        private boolean mRequestDismissKeyguard;
        private final ActivityTaskManagerService mService;
        private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;

        KeyguardDisplayState(ActivityTaskManagerService service, int displayId,
                ActivityTaskManagerService.SleepTokenAcquirer acquirer) {
        KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
            mService = service;
            mDisplayId = displayId;
            mSleepTokenAcquirer = acquirer;
        }

        void onRemoved() {
        void onRemoved(@NonNull DisplayContent dc) {
            mTopOccludesActivity = null;
            mDismissingKeyguardActivity = null;
            mTopTurnScreenOnActivity = null;
            mSleepTokenAcquirer.release(mDisplayId);
            dc.removeSleepToken(KEYGUARD_SLEEP_TOKEN_TAG);
        }

        void writeEventLog(String reason) {
@@ -804,7 +800,7 @@ class KeyguardController {
                controller.scheduleGoingAwayTimeout(mDisplayId);
            }
            if (occludedChanged) {
                controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
                controller.handleOccludedChanged(display, mTopOccludesActivity);
            }

            // Collect the participants for shell transition, so that transition won't happen too
+4 −67
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import static android.window.DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SLEEP_TOKEN;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_STATES;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_TASKS;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WALLPAPER;
@@ -210,12 +209,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    // Map from the PID to the top most app which has a focused window of the process.
    final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>();

    // The tag for the token to put root tasks on the displays to sleep.
    private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";

    /** The token acquirer to put root tasks on the displays to sleep */
    final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer;

    /**
     * The modes which affect which tasks are returned when calling
     * {@link RootWindowContainer#anyTaskForId(int)}.
@@ -260,13 +253,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    @Nullable
    DeviceStateAutoRotateSettingController mDeviceStateAutoRotateSettingController;

    /**
     * A list of tokens that cause the top activity to be put to sleep.
     * They are used by components that may hide and block interaction with underlying
     * activities.
     */
    final SparseArray<SleepToken> mSleepTokens = new SparseArray<>();

    // Whether tasks have moved and we need to rank the tasks before next OOM scoring
    private boolean mTaskLayersChanged = true;
    private int mTmpTaskLayerRank;
@@ -454,7 +440,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        mService = service.mAtmService;
        mTaskSupervisor = mService.mTaskSupervisor;
        mTaskSupervisor.mRootWindowContainer = this;
        mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG);
        mDeviceStateController = new DeviceStateController(service.mContext, service.mGlobalLock);
        mDisplayRotationCoordinator = new DisplayRotationCoordinator();
        mDeviceStateAutoRotateSettingController =
@@ -2947,46 +2932,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>

    void prepareForShutdown() {
        for (int i = 0; i < getChildCount(); i++) {
            createSleepToken("shutdown", getChildAt(i).mDisplayId);
        }
    }

    SleepToken createSleepToken(String tag, int displayId) {
        final DisplayContent display = getDisplayContent(displayId);
        if (display == null) {
            throw new IllegalArgumentException("Invalid display: " + displayId);
        }

        final int tokenKey = makeSleepTokenKey(tag, displayId);
        SleepToken token = mSleepTokens.get(tokenKey);
        if (token == null) {
            token = new SleepToken(tag, displayId);
            mSleepTokens.put(tokenKey, token);
            display.mAllSleepTokens.add(token);
            ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Create SleepToken: tag=%s, displayId=%d",
                    tag, displayId);
        } else {
            throw new RuntimeException("Create the same sleep token twice: " + token);
        }
        return token;
    }

    void removeSleepToken(SleepToken token) {
        if (mSleepTokens.removeReturnOld(token.mHashKey) == null) {
            Slog.d(TAG, "Remove non-exist sleep token: " + token + " from " + Debug.getCallers(6));
        }
        final DisplayContent display = getDisplayContent(token.mDisplayId);
        if (display == null) {
            Slog.d(TAG, "Remove sleep token for non-existing display: " + token + " from "
                    + Debug.getCallers(6));
            return;
        }

        ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Remove SleepToken: tag=%s, displayId=%d",
                token.mTag, token.mDisplayId);
        display.mAllSleepTokens.remove(token);
        if (display.mAllSleepTokens.isEmpty()) {
            mService.updateSleepIfNeededLocked();
            getChildAt(i).addSleepTokenOnly("shutdown");
        }
    }

@@ -3955,26 +3901,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    }

    static final class SleepToken {
        private final String mTag;
        final String mTag;
        private final long mAcquireTime;
        private final int mDisplayId;
        final int mHashKey;

        SleepToken(String tag, int displayId) {
        SleepToken(String tag) {
            mTag = tag;
            mDisplayId = displayId;
            mAcquireTime = SystemClock.uptimeMillis();
            mHashKey = makeSleepTokenKey(mTag, mDisplayId);
        }

        boolean isScreenOff() {
            return DISPLAY_OFF_SLEEP_TOKEN_TAG.equals(mTag);
        }

        @Override
        public String toString() {
            return "{\"" + mTag + "\", display " + mDisplayId
                    + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
            return "{\"" + mTag + "\", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
        }

        void writeTagToProto(ProtoOutputStream proto, long fieldId) {