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

Commit 00f4a4bc authored by Bryce Lee's avatar Bryce Lee Committed by Android (Google) Code Review
Browse files

Merge "Consider lock state when determining next activity to become visible." into pi-dev

parents fa404791 c961e0a5
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -3802,7 +3802,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        // and the resumed activity is not yet visible, then hold off on
        // finishing until the resumed one becomes visible.

        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
        // The activity that we are finishing may be over the lock screen. In this case, we do not
        // want to consider activities that cannot be shown on the lock screen as running and should
        // proceed with finishing the activity if there is no valid next top running activity.
        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(
                true /* considerKeyguardState */);

        if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
                && next != null && !next.nowVisible) {
+37 −8
Original line number Diff line number Diff line
@@ -1210,6 +1210,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
    }

    ActivityRecord topRunningActivityLocked() {
        return topRunningActivityLocked(false /* considerKeyguardState */);
    }

    /**
     * Returns the top running activity in the focused stack. In the case the focused stack has no
     * such activity, the next focusable stack on top of a display is returned.
     * @param considerKeyguardState Indicates whether the locked state should be considered. if
     *                            {@code true} and the keyguard is locked, only activities that
     *                            can be shown on top of the keyguard will be considered.
     * @return The top running activity. {@code null} if none is available.
     */
    ActivityRecord topRunningActivityLocked(boolean considerKeyguardState) {
        final ActivityStack focusedStack = mFocusedStack;
        ActivityRecord r = focusedStack.topRunningActivityLocked();
        if (r != null) {
@@ -1228,16 +1240,33 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            if (display == null) {
                continue;
            }
            for (int j = display.getChildCount() - 1; j >= 0; --j) {
                final ActivityStack stack = display.getChildAt(j);
                if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
                    r = stack.topRunningActivityLocked();
                    if (r != null) {
                        return r;

            // TODO: We probably want to consider the top fullscreen stack as we could have a pinned
            // stack on top.
            final ActivityStack topStack = display.getTopStack();

            // Only consider focusable top stacks other than the current focused one.
            if (topStack == null || !topStack.isFocusable() || topStack == focusedStack) {
                continue;
            }

            final ActivityRecord topActivity = topStack.topRunningActivityLocked();

            // Skip if no top activity.
            if (topActivity == null) {
                continue;
            }

            final boolean keyguardLocked = getKeyguardController().isKeyguardLocked();

            // This activity can be considered the top running activity if we are not
            // considering the locked state, the keyguard isn't locked, or we can show when
            // locked.
            if (!considerKeyguardState || !keyguardLocked || topActivity.canShowWhenLocked()) {
                return topActivity;
            }
        }

        return null;
    }

+49 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -329,4 +330,52 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
                REMOVE_TASK_MODE_DESTROYING);
        assertFalse(pinnedStack.isFocusable());
    }

    /**
     * Verifies the correct activity is returned when querying the top running activity with an
     * empty focused stack.
     */
    @Test
    public void testNonFocusedTopRunningActivity() throws Exception {
        // Create stack to hold focus
        final ActivityStack focusedStack = mService.mStackSupervisor.getDefaultDisplay()
                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);

        final KeyguardController keyguard = mSupervisor.getKeyguardController();
        final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
                .setStack(stack).build();

        mSupervisor.mFocusedStack = focusedStack;

        doAnswer((InvocationOnMock invocationOnMock) -> {
            final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
            displayIds.put(0, mSupervisor.getDefaultDisplay().mDisplayId);
            return null;
        }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());

        // Make sure the top running activity is not affected when keyguard is not locked
        assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
        assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked(
                true /* considerKeyguardState */));

        // Check to make sure activity not reported when it cannot show on lock and lock is on.
        doReturn(true).when(keyguard).isKeyguardLocked();
        assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
        assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
                true /* considerKeyguardState */));

        // Add activity that should be shown on the keyguard.
        final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService)
                .setCreateTask(true)
                .setStack(stack)
                .setActivityFlags(FLAG_SHOW_WHEN_LOCKED)
                .build();

        // Ensure the show when locked activity is returned.
        assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked());
        assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked(
                true /* considerKeyguardState */));
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ public class ActivityTestsBase {
        private int mUid;
        private boolean mCreateTask;
        private ActivityStack mStack;
        private int mActivityFlags;

        ActivityBuilder(ActivityManagerService service) {
            mService = service;
@@ -152,6 +153,11 @@ public class ActivityTestsBase {
            return this;
        }

        ActivityBuilder setActivityFlags(int flags) {
            mActivityFlags = flags;
            return this;
        }

        ActivityBuilder setStack(ActivityStack stack) {
            mStack = stack;
            return this;
@@ -186,6 +192,8 @@ public class ActivityTestsBase {
            aInfo.applicationInfo = new ApplicationInfo();
            aInfo.applicationInfo.packageName = mComponent.getPackageName();
            aInfo.applicationInfo.uid = mUid;
            aInfo.flags |= mActivityFlags;

            final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
                    0 /* launchedFromPid */, 0, null, intent, null,
                    aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,