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

Commit a6313651 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix freeze wrong display when finishing activity"

parents a0f7b04b e10cea50
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -873,6 +873,52 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
        return null;
    }

    ActivityRecord topRunningActivity() {
        return topRunningActivity(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 this 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 topRunningActivity(boolean considerKeyguardState) {
        ActivityRecord topRunning = null;
        final ActivityStack focusedStack = getFocusedStack();
        if (focusedStack != null) {
            topRunning = focusedStack.topRunningActivityLocked();
        }

        // Look in other focusable stacks.
        if (topRunning == null) {
            for (int i = mStacks.size() - 1; i >= 0; --i) {
                final ActivityStack stack = mStacks.get(i);
                // Only consider focusable stacks other than the current focused one.
                if (stack == focusedStack || !stack.isFocusable()) {
                    continue;
                }
                topRunning = stack.topRunningActivityLocked();
                if (topRunning != null) {
                    break;
                }
            }
        }

        // 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 (topRunning != null && considerKeyguardState
                && mSupervisor.getKeyguardController().isKeyguardLocked()
                && !topRunning.canShowWhenLocked()) {
            return null;
        }

        return topRunning;
    }

    int getIndexOf(ActivityStack stack) {
        return mStacks.indexOf(stack);
    }
+10 −8
Original line number Diff line number Diff line
@@ -3877,8 +3877,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        // 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 */);
        final ActivityDisplay display = getDisplay();
        final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */);

        if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
                && next != null && !next.nowVisible) {
@@ -3902,23 +3902,25 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);

        r.setState(FINISHING, "finishCurrentActivityLocked");
        final boolean finishingActivityInNonFocusedStack
                = r.getStack() != mStackSupervisor.getTopDisplayFocusedStack()
                && prevState == PAUSED && mode == FINISH_AFTER_VISIBLE;
        final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE
                && prevState == PAUSED && (r.getStack() != display.getFocusedStack()
                        || (next == null && display.topRunningActivity() == null));

        if (mode == FINISH_IMMEDIATELY
                || (prevState == PAUSED
                    && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
                || finishingActivityInNonFocusedStack
                || finishingInNonFocusedStackOrNoRunning
                || prevState == STOPPING
                || prevState == STOPPED
                || prevState == ActivityState.INITIALIZING) {
            r.makeFinishingLocked();
            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);

            if (finishingActivityInNonFocusedStack) {
            if (finishingInNonFocusedStackOrNoRunning) {
                // Finishing activity that was in paused state and it was in not currently focused
                // stack, need to make something visible in its place.
                // stack, need to make something visible in its place. Also if the display does not
                // have running activity, the configuration may need to be updated for restoring
                // original orientation of the display.
                mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
            }
+2 −62
Original line number Diff line number Diff line
@@ -1214,75 +1214,15 @@ 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 = getTopDisplayFocusedStack();
        ActivityRecord r = focusedStack.topRunningActivityLocked();
        if (r != null && isValidTopRunningActivity(r, considerKeyguardState)) {
            return r;
        }

        // Look in other non-focused and non-home stacks.
        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
            final ActivityDisplay display = mActivityDisplays.get(i);

            // 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;
            }


            // 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 (isValidTopRunningActivity(topActivity, considerKeyguardState)) {
            final ActivityRecord topActivity = mActivityDisplays.get(i).topRunningActivity();
            if (topActivity != null) {
                return topActivity;
            }
        }

        return null;
    }

    /**
     * Verifies an {@link ActivityRecord} can be the top activity based on keyguard state and
     * whether we are considering it.
     */
    private boolean isValidTopRunningActivity(ActivityRecord record,
            boolean considerKeyguardState) {
        if (!considerKeyguardState) {
            return true;
        }

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

        if (!keyguardLocked) {
            return true;
        }

        return record.canShowWhenLocked();
    }

    @VisibleForTesting
    void getRunningTasks(int maxNum, List<RunningTaskInfo> list,
            @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode,
+56 −0
Original line number Diff line number Diff line
@@ -20,11 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
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.ActivityStackSupervisor.ON_TOP;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;

import android.platform.test.annotations.Presubmit;

@@ -131,4 +134,57 @@ public class ActivityDisplayTests extends ActivityTestsBase {
        new ActivityBuilder(mService).setTask(fullscreenTask).build();
        return fullscreenStack;
    }

    /**
     * Verifies the correct activity is returned when querying the top running activity.
     */
    @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();

        // Make sure the top running activity is not affected when keyguard is not locked.
        assertTopRunningActivity(activity, display);

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

        // Change focus to stack with activity.
        stack.moveToFront("focusChangeToTestStack");
        assertEquals(stack, display.getFocusedStack());
        assertEquals(activity, display.topRunningActivity());
        assertNull(display.topRunningActivity(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.
        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.
        assertTopRunningActivity(showWhenLockedActivity, display);
    }

    private static void assertTopRunningActivity(ActivityRecord top, ActivityDisplay display) {
        assertEquals(top, display.topRunningActivity());
        assertEquals(top, display.topRunningActivity(true /* considerKeyguardState */));
    }
}
+0 −57
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT
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 com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
@@ -306,62 +305,6 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
        assertFalse(pinnedStack.isFocusable());
    }

    /**
     * Verifies the correct activity is returned when querying the top running activity.
     */
    @Test
    public void testTopRunningActivity() throws Exception {
        // Create stack to hold focus
        final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
        final ActivityStack emptyStack = display.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();

        // 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 */));

        // Change focus to stack with activity.
        stack.moveToFront("focusChangeToTestStack");
        assertEquals(stack, display.getFocusedStack());
        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 */));

        // Change focus back to empty stack
        emptyStack.moveToFront("focusChangeToEmptyStack");
        assertEquals(emptyStack, display.getFocusedStack());
        // Looking for running activity only in top and focused stack, so nothing should be returned
        // from empty stack.
        assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked());
        assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
                true /* considerKeyguardState */));
    }

    /**
     * Verify that split-screen primary stack will be chosen if activity is launched that targets
     * split-screen secondary, but a matching existing instance is found on top of split-screen
Loading