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

Commit 5daa3121 authored by Bryce Lee's avatar Bryce Lee
Browse files

Do not pause resumed activity in resumeTopActivityUncheckedLocked.

A number of operations occur between setting the resumed activity and
notifying the activity to resume. One of these steps is updating the
configuration, which can cause the device to pause the resumed
activity. Since the activity has not been told to resume, this leads
to a pause before resume.

This changelist addresses the issue by checking whether we are in the
middle of resuming the top activity before attempting to stop the
currently set resumed activity.

Change-Id: I3b5b61de6b1b5a35b7773912b4e63d6c69096c04
Fixes: 35637717
Test: bit FrameworksServicesTests:com.android.server.am.ActivityStackTests#testNoPauseDuringResumeTopActivity
parent 8ffd8f78
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -1152,6 +1152,18 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "Sleep => pause with userLeaving=false");

            // If we are in the middle of resuming the top activity in
            // {@link #resumeTopActivityUncheckedLocked}, mResumedActivity will be set but not
            // resumed yet. We must not proceed pausing the activity here. This method will be
            // called again if necessary as part of
            // {@link ActivityStackSupervisor#checkReadyForSleepLocked}.
            if (mStackSupervisor.inResumeTopActivity) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "In the middle of resuming top activity "
                        + mResumedActivity);
                return true;
            }

            startPausingLocked(false, true, null, false);
            return true;
        }
@@ -1229,6 +1241,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
            }
        }
        ActivityRecord prev = mResumedActivity;

        if (prev == null) {
            if (resuming == null) {
                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
@@ -2191,6 +2204,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        // When resuming the top activity, it may be necessary to pause the top activity (for
        // example, returning to the lock screen. We suppress the normal pause logic in
        // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end.
        // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure
        // any necessary pause logic occurs.
        mStackSupervisor.checkReadyForSleepLocked();

        return result;
    }

+24 −0
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package com.android.server.am;

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

import android.content.ComponentName;
import android.platform.test.annotations.Presubmit;
@@ -50,6 +52,7 @@ public class ActivityStackTests extends ActivityTestsBase {
                "testEmptyTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
        assertNull(task.getWindowContainerController());
    }

    @Test
    public void testOccupiedTaskCleanupOnRemove() throws Exception {
        final ActivityManagerService service = createActivityManagerService();
@@ -60,4 +63,25 @@ public class ActivityStackTests extends ActivityTestsBase {
                "testOccupiedTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
        assertNotNull(task.getWindowContainerController());
    }

    @Test
    public void testNoPauseDuringResumeTopActivity() throws Exception {
        final ActivityManagerService service = createActivityManagerService();
        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
        final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
        final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID);

        // Simulate the a resumed activity set during
        // {@link ActivityStack#resumeTopActivityUncheckedLocked}.
        service.mStackSupervisor.inResumeTopActivity = true;
        testStack.mResumedActivity = activityRecord;

        final boolean waiting = testStack.checkReadyForSleepLocked();

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

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