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

Commit 34acc145 authored by Andrii Kulian's avatar Andrii Kulian
Browse files

Simplify finishing flow for activities waiting for next one to resume

The finishing code used to have custom logic that handled the case
when an activity is paused in focused stack and needs to be added to
the list of finishing activities instead of being destroyed
immediately. This is needed to make sure that the next activity is
resumed first before we stop and destroy the finishing one. It will
eventually be destroyed when the next activity reports idle.

This CLs instead unconditionally marks the activity as finishing and
invokes RootActivityContainer#resumeFocusedStacksTopActivities(). If
any activity is made resumed as a result of this call - then all we
need to do is to wait for it to report idle. If no activity was made
resumed - it means that we can go ahead and request destruction
immediately.

Bug: 137329632
Bug: 142125019
Test: WM CTS
Change-Id: I28c08f06ce74502053d141a21ae81e1b99df7228
parent c62ba18c
Loading
Loading
Loading
Loading
+23 −14
Original line number Diff line number Diff line
@@ -1858,25 +1858,27 @@ final class ActivityRecord extends ConfigurationContainer {
        // implied that the current finishing activity should be added into stopping list rather
        // than destroy immediately.
        final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.visible);
        final ActivityStack stack = getActivityStack();
        final boolean notFocusedStack = stack != mRootActivityContainer.getTopDisplayFocusedStack();
        final boolean notGlobalFocusedStack =
                getActivityStack() != mRootActivityContainer.getTopDisplayFocusedStack();
        if (isVisible && isNextNotYetVisible) {
            // Add this activity to the list of stopping activities. It will be processed and
            // destroyed when the next activity reports idle.
            addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
                    "completeFinishing");
            if (DEBUG_STATES) {
                Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (finish requested)");
            }
            setState(STOPPING, "completeFinishing");
            if (notFocusedStack) {
            if (notGlobalFocusedStack) {
                // Ensuring visibility and configuration only for non-focused stacks since this
                // method call is relatively expensive and not necessary for focused stacks.
                mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
            }
        } else if (isVisible && isState(PAUSED) && getActivityStack().isFocusedStackOnDisplay()
                && !inPinnedWindowingMode()) {
            // TODO(b/137329632): Currently non-focused stack is handled differently.
            addToFinishingAndWaitForIdle();
        } else if (addToFinishingAndWaitForIdle()) {
            // We added this activity to the finishing list and something else is becoming resumed.
            // The activity will complete finishing when the next activity reports idle. No need to
            // do anything else here.
        } else {
            // Not waiting for the next one to become visible - finish right away.
            // Not waiting for the next one to become visible, and nothing else will be resumed in
            // place of this activity - requesting destruction right away.
            activityRemoved = destroyIfPossible(reason);
        }

@@ -1933,13 +1935,20 @@ final class ActivityRecord extends ConfigurationContainer {
        return activityRemoved;
    }

    /**
     * Add this activity to the list of finishing and trigger resuming of activities in focused
     * stacks.
     * @return {@code true} if some other activity is being resumed as a result of this call.
     */
    @VisibleForTesting
    void addToFinishingAndWaitForIdle() {
    boolean addToFinishingAndWaitForIdle() {
        if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
        setState(FINISHING, "addToFinishingAndWaitForIdle");
        if (!mStackSupervisor.mFinishingActivities.contains(this)) {
            mStackSupervisor.mFinishingActivities.add(this);
        }
        resumeKeyDispatchingLocked();
        mRootActivityContainer.resumeFocusedStacksTopActivities();
        return mRootActivityContainer.resumeFocusedStacksTopActivities();
    }

    /**
+7 −0
Original line number Diff line number Diff line
@@ -22,8 +22,11 @@ import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static org.mockito.ArgumentMatchers.any;

import android.hardware.display.DisplayManagerGlobal;
import android.view.Display;
import android.view.DisplayInfo;
@@ -85,6 +88,10 @@ class TestActivityDisplay extends ActivityDisplay {
            displayRotation.setRotation(rotation);
            return true;
        }).when(displayRotation).updateRotationUnchecked(anyBoolean());

        final InputMonitor inputMonitor = mDisplayContent.getInputMonitor();
        spyOn(inputMonitor);
        doNothing().when(inputMonitor).resumeDispatchingLw(any());
    }

    @SuppressWarnings("TypeParameterUnusedInFormals")