Loading services/core/java/com/android/server/wm/ActivityMetricsLogger.java +11 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); } Loading Loading @@ -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"); } Loading Loading @@ -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); Loading services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +4 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +1 −0 Original line number Diff line number Diff line Loading @@ -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. Loading services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +7 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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]); Loading Loading
services/core/java/com/android/server/wm/ActivityMetricsLogger.java +11 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); } Loading Loading @@ -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"); } Loading Loading @@ -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); Loading
services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +4 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading
services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +1 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +7 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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]); Loading