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

Commit 18abd0ef authored by David Stevens's avatar David Stevens
Browse files

Fix activity manager timeout during shutdown

Flip the return value for ActivityStack.goToSleepIfPossible from true if
something needs to be done to true if the stack successfully went to
sleep. An incorrect check in ActivityStack.checkReadyForSleep was
causing ActivityStackSupervisor to sometimes not get notified when a
stack finished stopping during shutdown. Also, no-delay calls to
ActivityStackSupervisor#checkReadyForSleepLocked would fail to put
activities to sleep.

BUG: 64756886
Test: go/run-boottest
Change-Id: Icec590ed9a0e0f035881b7eb03a280787dcfced1
parent b70a55a7
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -1184,7 +1184,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
     * function get called again when those actions complete.
     *
     * @param shuttingDown true when the called because the device is shutting down.
     * @return true if something must be done before going to sleep.
     * @return true if the stack finished going to sleep, false if the stack only started the
     * process of going to sleep (checkReadyForSleep will be called when that process finishes).
     */
    boolean goToSleepIfPossible(boolean shuttingDown) {
        boolean shouldSleep = true;
@@ -1235,10 +1236,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
            goToSleep();
        }

        return !shouldSleep;
        return shouldSleep;
    }

    private void goToSleep() {
    void goToSleep() {
        ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);

        // Make sure any paused or stopped but visible activities are now sleeping.
+20 −22
Original line number Diff line number Diff line
@@ -3173,15 +3173,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        boolean timedout = false;
        final long endTime = System.currentTimeMillis() + timeout;
        while (true) {
            boolean cantShutdown = false;
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    cantShutdown |=
                            stacks.get(stackNdx).goToSleepIfPossible(true /* shuttingDown */);
                }
            }
            if (cantShutdown) {
            if (!putStacksToSleepLocked(true /* allowDelay */, true /* shuttingDown */)) {
                long timeRemaining = endTime - System.currentTimeMillis();
                if (timeRemaining > 0) {
                    try {
@@ -3268,20 +3260,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            return;
        }

        if (allowDelay) {
            boolean dontSleep = false;
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
                final ArrayList<ActivityStack> stacks = display.mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    dontSleep |= stacks.get(stackNdx).goToSleepIfPossible(false /* shuttingDown */);
                }
            }

            if (dontSleep) {
        if (!putStacksToSleepLocked(allowDelay, false /* shuttingDown */)) {
            return;
        }
        }

        // Send launch end powerhint before going sleep
        mService.mActivityStarter.sendPowerHintForLaunchEndIfNeeded();
@@ -3296,6 +3277,23 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        }
    }

    // Tries to put all activity stacks to sleep. Returns true if all stacks were
    // successfully put to sleep.
    private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) {
        boolean allSleep = true;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                if (allowDelay) {
                    allSleep &= stacks.get(stackNdx).goToSleepIfPossible(shuttingDown);
                } else {
                    stacks.get(stackNdx).goToSleep();
                }
            }
        }
        return allSleep;
    }

    boolean reportResumedActivityLocked(ActivityRecord r) {
        final ActivityStack stack = r.getStack();
        if (isFocusedStack(stack)) {
+2 −2
Original line number Diff line number Diff line
@@ -17,9 +17,9 @@
package com.android.server.am;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.app.ActivityManager;
import android.content.ComponentName;
@@ -81,7 +81,7 @@ public class ActivityStackTests extends ActivityTestsBase {
        final boolean waiting = testStack.goToSleepIfPossible(false);

        // Ensure we report not being ready for sleep.
        assertTrue(waiting);
        assertFalse(waiting);

        // Make sure the resumed activity is untouched.
        assertEquals(testStack.mResumedActivity, activityRecord);