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

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

Merge "Fix focused stack adjustment when finishing top activity"

parents 485167c5 1e7ba58e
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -1699,6 +1699,12 @@ final class ActivityRecord extends ConfigurationContainer {
            return FINISH_RESULT_CANCELLED;
        }

        final ActivityStack stack = getActivityStack();
        final boolean mayAdjustFocus = (isState(RESUMED) || stack.mResumedActivity == null)
                // It must be checked before {@link #makeFinishingLocked} is called, because a stack
                // is not visible if it only contains finishing activities.
                && mRootActivityContainer.isTopDisplayFocusedStack(stack);

        mAtmService.mWindowManager.deferSurfaceLayout();
        try {
            makeFinishingLocked();
@@ -1720,8 +1726,12 @@ final class ActivityRecord extends ConfigurationContainer {

            pauseKeyDispatchingLocked();

            final ActivityStack stack = getActivityStack();
            stack.adjustFocusedActivityStack(this, "finishIfPossible");
            // We are finishing the top focused activity and its stack has nothing to be focused so
            // the next focusable stack should be focused.
            if (mayAdjustFocus
                    && (stack.topRunningActivityLocked() == null || !stack.isFocusable())) {
                stack.adjustFocusToNextFocusableStack("finish-top");
            }

            finishActivityResults(resultCode, resultData);

@@ -3012,7 +3022,6 @@ final class ActivityRecord extends ConfigurationContainer {
                    if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this);
                    if (finishIfPossible("stop-no-history", false /* oomAdj */)
                            != FINISH_RESULT_CANCELLED) {
                        // {@link adjustFocusedActivityStack} must have been already called.
                        resumeKeyDispatchingLocked();
                        return;
                    }
@@ -3028,7 +3037,6 @@ final class ActivityRecord extends ConfigurationContainer {
        if (!attachedToProcess()) {
            return;
        }
        stack.adjustFocusedActivityStack(this, "stopActivity");
        resumeKeyDispatchingLocked();
        try {
            stopped = false;
+4 −44
Original line number Diff line number Diff line
@@ -3542,50 +3542,6 @@ class ActivityStack extends ConfigurationContainer {
        return taskTop;
    }

    void adjustFocusedActivityStack(ActivityRecord r, String reason) {
        if (!mRootActivityContainer.isTopDisplayFocusedStack(this) ||
                ((mResumedActivity != r) && (mResumedActivity != null))) {
            return;
        }

        final ActivityRecord next = topRunningActivityLocked();
        final String myReason = reason + " adjustFocus";

        if (next == r) {
            final ActivityRecord top = mRootActivityContainer.topRunningActivity();
            if (top != null) {
                top.moveFocusableActivityToTop(myReason);
            }
            return;
        }

        if (next != null && isFocusable()) {
            // Keep focus in stack if we have a top running activity and are focusable.
            return;
        }

        // Task is not guaranteed to be non-null. For example, destroying the
        // {@link ActivityRecord} will disassociate the task from the activity.
        final TaskRecord task = r.getTaskRecord();

        if (task == null) {
            throw new IllegalStateException("activity no longer associated with task:" + r);
        }

        // Move focus to next focusable stack if possible.
        final ActivityStack nextFocusableStack = adjustFocusToNextFocusableStack(myReason);
        if (nextFocusableStack != null) {
            final ActivityRecord top = nextFocusableStack.topRunningActivityLocked();
            if (top != null && top == mRootActivityContainer.getTopResumedActivity()) {
                mService.setResumedActivityUncheckLocked(top, reason);
            }
            return;
        }

        // Whatever...go home.
        getDisplay().moveHomeActivityToTop(myReason);
    }

    /**
     * Find next proper focusable stack and make it focused.
     * @return The stack that now got the focus, {@code null} if none found.
@@ -3620,6 +3576,10 @@ class ActivityStack extends ConfigurationContainer {
        // Top display focused stack is changed, update top resumed activity if needed.
        if (stack.mResumedActivity != null) {
            mStackSupervisor.updateTopResumedActivityIfNeeded();
            // Set focused app directly because if the next focused activity is already resumed
            // (e.g. the next top activity is on a different display), there won't have activity
            // state change to update it.
            mService.setResumedActivityUncheckLocked(stack.mResumedActivity, reason);
        }
        return stack;
    }
+26 −0
Original line number Diff line number Diff line
@@ -799,6 +799,32 @@ public class ActivityRecordTests extends ActivityTestsBase {
        assertFalse(mActivity.isInStackLocked());
    }

    /**
     * Verify that when finishing the top focused activity on top display, the stack order will be
     * changed by adjusting focus.
     */
    @Test
    public void testFinishActivityIfPossible_adjustStackOrder() {
        // Prepare the stacks with order (top to bottom): mStack, stack1, stack2.
        final ActivityStack stack1 = new StackBuilder(mRootActivityContainer).build();
        mStack.moveToFront("test");
        // The stack2 is needed here for moving back to simulate the
        // {@link ActivityDisplay#mPreferredTopFocusableStack} is cleared, so
        // {@link ActivityDisplay#getFocusedStack} will rely on the order of focusable-and-visible
        // stacks. Then when mActivity is finishing, its stack will be invisible (no running
        // activities in the stack) that is the key condition to verify.
        final ActivityStack stack2 = new StackBuilder(mRootActivityContainer).build();
        stack2.moveToBack("test", stack2.getChildAt(0));

        assertTrue(mStack.isTopStackOnDisplay());

        mActivity.setState(RESUMED, "test");
        mActivity.finishIfPossible(0 /* resultCode */, null /* resultData */, "test",
                false /* oomAdj */, false /* pauseImmediately */);

        assertTrue(stack1.isTopStackOnDisplay());
    }

    /**
     * Verify that resumed activity is paused due to finish request.
     */