diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 20958aa1c9b15..ce1592d87fcda 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -187,6 +187,10 @@ class ActivityMetricsLogger { return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.allDrawn(); } + boolean hasActiveTransitionInfo() { + return mAssociatedTransitionInfo != null; + } + boolean contains(ActivityRecord r) { return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.contains(r); } @@ -336,10 +340,11 @@ class ActivityMetricsLogger { } /** Only keep the records which can be drawn. */ - void updatePendingDraw() { + void updatePendingDraw(boolean keepInitializing) { for (int i = mPendingDrawActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mPendingDrawActivities.get(i); - if (!r.mVisibleRequested) { + if (!r.mVisibleRequested + && !(keepInitializing && r.isState(ActivityRecord.State.INITIALIZING))) { if (DEBUG_METRICS) Slog.i(TAG, "Discard pending draw " + r); mPendingDrawActivities.remove(i); } @@ -663,7 +668,7 @@ class ActivityMetricsLogger { // visible such as after the top task is finished. for (int i = mTransitionInfoList.size() - 2; i >= 0; i--) { final TransitionInfo prevInfo = mTransitionInfoList.get(i); - prevInfo.updatePendingDraw(); + prevInfo.updatePendingDraw(false /* keepInitializing */); if (prevInfo.allDrawn()) { abort(prevInfo, "nothing will be drawn"); } @@ -749,7 +754,9 @@ class ActivityMetricsLogger { info.mCurrentTransitionDelayMs = info.calculateDelay(timestampNs); info.mReason = activityToReason.valueAt(index); info.mLoggedTransitionStarting = true; - info.updatePendingDraw(); + // Do not remove activity in initializing state because the transition may be started + // by starting window. The initializing activity may be requested to visible soon. + info.updatePendingDraw(true /* keepInitializing */); if (info.allDrawn()) { done(false /* abort */, info, "notifyTransitionStarting - all windows drawn", timestampNs); diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 50ac4330facd3..e593c1c1e6562 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -2596,7 +2596,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } boolean matches(ActivityRecord r) { - return mTargetComponent.equals(r.mActivityComponent) || mLaunchingState.contains(r); + if (!mLaunchingState.hasActiveTransitionInfo()) { + return mTargetComponent.equals(r.mActivityComponent); + } + return mLaunchingState.contains(r); } void dump(PrintWriter pw, String prefix) { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index b282cd7ce1cbc..89a126b92bfa7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -404,6 +404,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { // Another round without setting visibility of the trampoline activity. onActivityLaunchedTrampoline(); + mTrampolineActivity.setState(ActivityRecord.State.PAUSING, "test"); notifyWindowsDrawn(mTopActivity); // If the transition can start, the invisible activities should be discarded and the launch // event be reported successfully. diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java index 0d177c14427b8..26a68821a672a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java @@ -49,6 +49,7 @@ import androidx.test.filters.MediumTest; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentMatchers; import java.util.concurrent.TimeUnit; @@ -108,16 +109,18 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { final ActivityMetricsLogger.LaunchingState launchingState = new ActivityMetricsLogger.LaunchingState(); spyOn(launchingState); - doReturn(true).when(launchingState).contains(eq(secondActivity)); + doReturn(true).when(launchingState).hasActiveTransitionInfo(); + doReturn(true).when(launchingState).contains( + ArgumentMatchers.argThat(r -> r == firstActivity || r == secondActivity)); // The test case already runs inside global lock, so above thread can only execute after // this waiting method that releases the lock. mSupervisor.waitActivityVisibleOrLaunched(taskToFrontWait, firstActivity, launchingState); // Assert that the thread is finished. assertTrue(condition.block(TIMEOUT_MS)); - assertEquals(taskToFrontWait.result, START_TASK_TO_FRONT); - assertEquals(taskToFrontWait.who, secondActivity.mActivityComponent); - assertEquals(taskToFrontWait.launchState, WaitResult.LAUNCH_STATE_HOT); + assertEquals(START_TASK_TO_FRONT, taskToFrontWait.result); + assertEquals(secondActivity.mActivityComponent, taskToFrontWait.who); + assertEquals(WaitResult.LAUNCH_STATE_HOT, taskToFrontWait.launchState); // START_TASK_TO_FRONT means that another component will be visible, so the component // should not be assigned as the first activity. assertNull(launchedComponent[0]);