From 1314b9bd1a7925ea4c80e8889ca9318cd64dcb61 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 25 Jun 2021 21:59:34 +0800 Subject: [PATCH] Clear invisible transition info If 2 independent launch events happen in a short time, e.g. the first activity is only added to the stack with initial states, and only the latter is actually launched. Then the invisible transition info (the activity occluded by the latter) should be dropped. Otherwise when returning to it from back stack, the transition time will still be counted from the time it added. Bug: 192043869 Test: ActivityMetricsLaunchObserverTests#testOnReportFullyDrawn Change-Id: I6c6ae59fce2f7e417c606489fb331d9ab6ad4f0a --- .../android/server/wm/ActivityMetricsLogger.java | 15 ++++++++++++++- .../wm/ActivityMetricsLaunchObserverTests.java | 14 +++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index f6217bc2ffd24..24ea26e116f51 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -638,12 +638,24 @@ class ActivityMetricsLogger { launchObserverNotifyIntentFailed(); } if (launchedActivity.mDisplayContent.isSleeping()) { - // It is unknown whether the activity can be drawn or not, e.g. ut depends on the + // It is unknown whether the activity can be drawn or not, e.g. it depends on the // keyguard states and the attributes or flags set by the activity. If the activity // keeps invisible in the grace period, the tracker will be cancelled so it won't get // a very long launch time that takes unlocking as the end of launch. scheduleCheckActivityToBeDrawn(launchedActivity, UNKNOWN_VISIBILITY_CHECK_DELAY_MS); } + + // If the previous transitions are no longer visible, abort them to avoid counting the + // launch time when resuming from back stack. E.g. launch 2 independent tasks in a short + // time, the transition info of the first task should not keep active until it becomes + // 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(); + if (prevInfo.allDrawn()) { + abort(prevInfo, "nothing will be drawn"); + } + } } /** @@ -864,6 +876,7 @@ class ActivityMetricsLogger { final Boolean isHibernating = mLastHibernationStates.remove(info.mLastLaunchedActivity.packageName); if (abort) { + mLastTransitionInfo.remove(info.mLastLaunchedActivity); mSupervisor.stopWaitingForActivityVisible(info.mLastLaunchedActivity); launchObserverNotifyActivityLaunchCancelled(info); } else { 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 38466ebaa0cfd..32a4774ca4f2a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -270,9 +270,16 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { @Test public void testOnReportFullyDrawn() { + // Create an invisible event that should be cancelled after the next event starts. + onActivityLaunched(mTrampolineActivity); + mTrampolineActivity.mVisibleRequested = false; + mActivityOptions = ActivityOptions.makeBasic(); mActivityOptions.setSourceInfo(SourceInfo.TYPE_LAUNCHER, SystemClock.uptimeMillis() - 10); - onActivityLaunched(mTopActivity); + onIntentStarted(mTopActivity.intent); + notifyActivityLaunched(START_SUCCESS, mTopActivity); + verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt()); + verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity)); // The activity reports fully drawn before windows drawn, then the fully drawn event will // be pending (see {@link WindowingModeTransitionInfo#pendingFullyDrawn}). @@ -287,6 +294,10 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong()); verifyOnActivityLaunchFinished(mTopActivity); verifyNoMoreInteractions(mLaunchObserver); + + final ActivityMetricsLogger.TransitionInfoSnapshot fullyDrawnInfo = mActivityMetricsLogger + .logAppTransitionReportedDrawn(mTopActivity, false /* restoredFromBundle */); + assertWithMessage("Invisible event must be dropped").that(fullyDrawnInfo).isNull(); } private void onActivityLaunchedTrampoline() { @@ -480,6 +491,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { @Test public void testConsecutiveLaunchWithDifferentWindowingMode() { mTopActivity.setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); + mTrampolineActivity.mVisibleRequested = true; onActivityLaunched(mTrampolineActivity); mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent, mTrampolineActivity /* caller */, mTrampolineActivity.getUid());