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

Commit f2835df0 authored by Louis Chang's avatar Louis Chang
Browse files

Make stacks without running activities being invisible

Stacks that don't have any running activities and not starting
one on it should be invisible, no matter they are the top
stack or not.

Use home stack as the focused stack if the display has no
focusable and visiable stack because we eventually need to
start home activity on it.

Bug: 117745438
Test: Manual test with the same reproduce steps
      atest com.android.server.am
Change-Id: Iceb9ad7b7fa388b5829bb0d18f3627905d5410d7
parent 0215e993
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -356,7 +356,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
        return getOrCreateStack(windowingMode, activityType, onTop);
    }

    private int getNextStackId() {
    @VisibleForTesting
    int getNextStackId() {
        return sNextFreeStackId++;
    }

+30 −30
Original line number Diff line number Diff line
@@ -48,6 +48,26 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;

import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStackProto.BOUNDS;
import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
import static com.android.server.am.ActivityStackProto.FULLSCREEN;
import static com.android.server.am.ActivityStackProto.ID;
import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityStackProto.TASKS;
import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_APP;
@@ -66,7 +86,6 @@ import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LE
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_APP;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
@@ -81,29 +100,10 @@ import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStackProto.BOUNDS;
import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
import static com.android.server.am.ActivityStackProto.FULLSCREEN;
import static com.android.server.am.ActivityStackProto.ID;
import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityStackProto.TASKS;
import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;

import static com.android.server.am.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
import static java.lang.Integer.MAX_VALUE;

import android.app.Activity;
@@ -1807,13 +1807,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
            return false;
        }

        final ActivityRecord top = topRunningActivityLocked();
        if (top == null && isInStackLocked(starting) == null && !isTopStackOnDisplay()) {
            // Shouldn't be visible if you don't have any running activities, not starting one, and
            // not the top stack on display.
            return false;
        }

        final ActivityDisplay display = getDisplay();
        boolean gotSplitScreenStack = false;
        boolean gotOpaqueSplitScreenPrimary = false;
@@ -1822,9 +1815,16 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        final boolean isAssistantType = isActivityTypeAssistant();
        for (int i = display.getChildCount() - 1; i >= 0; --i) {
            final ActivityStack other = display.getChildAt(i);
            final boolean hasRunningActivities = other.topRunningActivityLocked() != null;
            if (other == this) {
                // Should be visible if there is no other stack occluding it.
                return true;
                // Should be visible if there is no other stack occluding it, unless it doesn't
                // have any running activities, not starting one and not home stack.
                return hasRunningActivities || isInStackLocked(starting) != null
                        || isActivityTypeHome();
            }

            if (!hasRunningActivities) {
                continue;
            }

            final int otherWindowingMode = other.getWindowingMode();
+13 −17
Original line number Diff line number Diff line
@@ -60,8 +60,7 @@ public class ActivityDisplayTests extends ActivityTestsBase {
    public void testLastFocusedStackIsUpdatedWhenMovingStack() {
        // Create a stack at bottom.
        final ActivityDisplay display = mSupervisor.getDefaultDisplay();
        final ActivityStack stack = display.createStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, !ON_TOP);
        final ActivityStack stack = new StackBuilder(mSupervisor).setOnTop(!ON_TOP).build();
        final ActivityStack prevFocusedStack = display.getFocusedStack();

        stack.moveToFront("moveStackToFront");
@@ -140,16 +139,14 @@ public class ActivityDisplayTests extends ActivityTestsBase {
     */
    @Test
    public void testTopRunningActivity() {
        // Create stack to hold focus.
        final ActivityDisplay display = mSupervisor.getDefaultDisplay();
        final ActivityStack emptyStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, true /* onTop */);

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

        // Create empty stack on top.
        final ActivityStack emptyStack =
                new StackBuilder(mSupervisor).setCreateActivity(false).build();

        // Make sure the top running activity is not affected when keyguard is not locked.
        assertTopRunningActivity(activity, display);
@@ -159,8 +156,8 @@ public class ActivityDisplayTests extends ActivityTestsBase {
        assertEquals(activity, display.topRunningActivity());
        assertNull(display.topRunningActivity(true /* considerKeyguardState */));

        // Change focus to stack with activity.
        stack.moveToFront("focusChangeToTestStack");
        // Move stack with activity to top.
        stack.moveToFront("testStackToFront");
        assertEquals(stack, display.getFocusedStack());
        assertEquals(activity, display.topRunningActivity());
        assertNull(display.topRunningActivity(true /* considerKeyguardState */));
@@ -175,11 +172,10 @@ public class ActivityDisplayTests extends ActivityTestsBase {
        // Ensure the show when locked activity is returned.
        assertTopRunningActivity(showWhenLockedActivity, display);

        // Change focus back to empty stack.
        emptyStack.moveToFront("focusChangeToEmptyStack");
        assertEquals(emptyStack, display.getFocusedStack());
        // If there is no running activity in focused stack, the running activity in next focusable
        // stack should be returned.
        // Move empty stack to front. The running activity in focusable stack which below the
        // empty stack should be returned.
        emptyStack.moveToFront("emptyStackToFront");
        assertEquals(stack, display.getFocusedStack());
        assertTopRunningActivity(showWhenLockedActivity, display);
    }

+3 −4
Original line number Diff line number Diff line
@@ -79,10 +79,9 @@ public class ActivityRecordTests extends ActivityTestsBase {
        super.setUp();

        setupActivityTaskManagerService();
        mStack = mSupervisor.getDefaultDisplay().createStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
        mActivity = new ActivityBuilder(mService).setTask(mTask).build();
        mStack = new StackBuilder(mSupervisor).build();
        mTask = mStack.getChildAt(0);
        mActivity = mTask.getTopActivity();
    }

    @Test
+4 −7
Original line number Diff line number Diff line
@@ -359,15 +359,12 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
    public void testFindTaskToMoveToFrontWhenRecentsOnTop() throws Exception {
        // Create stack/task on default display.
        final ActivityDisplay display = mSupervisor.getDefaultDisplay();
        final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
        final TestActivityStack targetStack = new StackBuilder(mSupervisor).setOnTop(false).build();
        final TaskRecord targetTask = targetStack.getChildAt(0);

        // Create Recents on top of the display.
        final ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_RECENTS, true /* onTop */);
        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
        new ActivityBuilder(mService).setTask(task).build();
        final ActivityStack stack =
                new StackBuilder(mSupervisor).setActivityType(ACTIVITY_TYPE_RECENTS).build();

        final String reason = "findTaskToMoveToFront";
        mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
Loading