diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c54ccd4d68447..7bbdcb62ccbc6 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -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"); - mStackSupervisor.mFinishingActivities.add(this); + if (!mStackSupervisor.mFinishingActivities.contains(this)) { + mStackSupervisor.mFinishingActivities.add(this); + } resumeKeyDispatchingLocked(); - mRootActivityContainer.resumeFocusedStacksTopActivities(); + return mRootActivityContainer.resumeFocusedStacksTopActivities(); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java index 778f0ca3c7826..9c3ff654ddf01 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java @@ -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")