diff options
| author | 2021-11-01 20:11:59 -0600 | |
|---|---|---|
| committer | 2021-11-01 12:48:08 +0000 | |
| commit | 395a7572f7a6aa910b42ee6aefd4ae392637e99c (patch) | |
| tree | 05c29a51af3d4433ba7f5d5c1aaa79eece566ef4 | |
| parent | cc110e6aeaef998b0a09b295eb247ad0a5b99896 (diff) | |
Only consider the last launched activity for metrics logger
Otherwise the logger needs to make sure that every visibility changes
belonging to the launch event are handled. Especially when there are
trampoline activities, such as if they are removed without visibility
change, then the launch time and trace may be unexpectedly long.
This simplifies the logic to track undrawn transition info. In general,
the occluded/behind activities are not important to the metrics.
Bug: 204488635
Test: atest ActivityMetricsLaunchObserverTests#testConsecutiveLaunch
Change-Id: I6c7e94a1a43acf642da77a23f400159d78144599
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityMetricsLogger.java | 80 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java | 1 |
2 files changed, 20 insertions, 61 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index c715c39c7359..d1374362505f 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -190,7 +190,7 @@ class ActivityMetricsLogger { @VisibleForTesting boolean allDrawn() { - return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.allDrawn(); + return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.mIsDrawn; } boolean hasActiveTransitionInfo() { @@ -224,8 +224,8 @@ class ActivityMetricsLogger { final boolean mProcessRunning; /** whether the process of the launching activity didn't have any active activity. */ final boolean mProcessSwitch; - /** The activities that should be drawn. */ - final ArrayList<ActivityRecord> mPendingDrawActivities = new ArrayList<>(2); + /** Whether the last launched activity has reported drawn. */ + boolean mIsDrawn; /** The latest activity to have been launched. */ @NonNull ActivityRecord mLastLaunchedActivity; @@ -318,10 +318,7 @@ class ActivityMetricsLogger { mLastLaunchedActivity.mLaunchRootTask = null; } mLastLaunchedActivity = r; - if (!r.noDisplay && !r.isReportedDrawn()) { - if (DEBUG_METRICS) Slog.i(TAG, "Add pending draw " + r); - mPendingDrawActivities.add(r); - } + mIsDrawn = r.isReportedDrawn(); } /** Returns {@code true} if the incoming activity can belong to this transition. */ @@ -332,29 +329,7 @@ class ActivityMetricsLogger { /** @return {@code true} if the activity matches a launched activity in this transition. */ boolean contains(ActivityRecord r) { - return r != null && (r == mLastLaunchedActivity || mPendingDrawActivities.contains(r)); - } - - /** Called when the activity is drawn or won't be drawn. */ - void removePendingDrawActivity(ActivityRecord r) { - if (DEBUG_METRICS) Slog.i(TAG, "Remove pending draw " + r); - mPendingDrawActivities.remove(r); - } - - boolean allDrawn() { - return mPendingDrawActivities.isEmpty(); - } - - /** Only keep the records which can be drawn. */ - void updatePendingDraw(boolean keepInitializing) { - for (int i = mPendingDrawActivities.size() - 1; i >= 0; i--) { - final ActivityRecord r = mPendingDrawActivities.get(i); - if (!r.mVisibleRequested - && !(keepInitializing && r.isState(ActivityRecord.State.INITIALIZING))) { - if (DEBUG_METRICS) Slog.i(TAG, "Discard pending draw " + r); - mPendingDrawActivities.remove(i); - } - } + return r == mLastLaunchedActivity; } /** @@ -377,7 +352,7 @@ class ActivityMetricsLogger { @Override public String toString() { return "TransitionInfo{" + Integer.toHexString(System.identityHashCode(this)) - + " a=" + mLastLaunchedActivity + " ua=" + mPendingDrawActivities + "}"; + + " a=" + mLastLaunchedActivity + " d=" + mIsDrawn + "}"; } } @@ -683,8 +658,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(false /* keepInitializing */); - if (prevInfo.allDrawn()) { + if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.mVisibleRequested) { abort(prevInfo, "nothing will be drawn"); } } @@ -711,17 +685,16 @@ class ActivityMetricsLogger { if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn " + r); final TransitionInfo info = getActiveTransitionInfo(r); - if (info == null || info.allDrawn()) { - if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn no activity to be drawn"); + if (info == null || info.mIsDrawn) { + if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn not pending drawn " + info); return null; } // Always calculate the delay because the caller may need to know the individual drawn time. info.mWindowsDrawnDelayMs = info.calculateDelay(timestampNs); - info.removePendingDrawActivity(r); - info.updatePendingDraw(false /* keepInitializing */); + info.mIsDrawn = true; final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info); - if (info.mLoggedTransitionStarting && info.allDrawn()) { - done(false /* abort */, info, "notifyWindowsDrawn - all windows drawn", timestampNs); + if (info.mLoggedTransitionStarting) { + done(false /* abort */, info, "notifyWindowsDrawn", timestampNs); } if (r.mWmService.isRecentsAnimationTarget(r)) { r.mWmService.getRecentsAnimationController().logRecentsAnimationStartTime( @@ -770,12 +743,8 @@ class ActivityMetricsLogger { info.mCurrentTransitionDelayMs = info.calculateDelay(timestampNs); info.mReason = activityToReason.valueAt(index); info.mLoggedTransitionStarting = true; - // 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); + if (info.mIsDrawn) { + done(false /* abort */, info, "notifyTransitionStarting drawn", timestampNs); } } } @@ -828,12 +797,9 @@ class ActivityMetricsLogger { return; } if (!r.mVisibleRequested || r.finishing) { - info.removePendingDrawActivity(r); - if (info.mLastLaunchedActivity == r) { - // Check if the tracker can be cancelled because the last launched activity may be - // no longer visible. - scheduleCheckActivityToBeDrawn(r, 0 /* delay */); - } + // Check if the tracker can be cancelled because the last launched activity may be + // no longer visible. + scheduleCheckActivityToBeDrawn(r, 0 /* delay */); } } @@ -852,17 +818,12 @@ class ActivityMetricsLogger { // If we have an active transition that's waiting on a certain activity that will be // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary. - // We have no active transitions. + // We have no active transitions. Or the notified activity whose visibility changed is + // no longer the launched activity, then we can still wait to get onWindowsDrawn. if (info == null) { return; } - // The notified activity whose visibility changed is no longer the launched activity. - // We can still wait to get onWindowsDrawn. - if (info.mLastLaunchedActivity != r) { - return; - } - // If the task of the launched activity contains any activity to be drawn, then the // window drawn event should report later to complete the transition. Otherwise all // activities in this task may be finished, invisible or drawn, so the transition event @@ -945,7 +906,6 @@ class ActivityMetricsLogger { } logAppTransitionFinished(info, isHibernating != null ? isHibernating : false); } - info.mPendingDrawActivities.clear(); mTransitionInfoList.remove(info); } @@ -1122,7 +1082,7 @@ class ActivityMetricsLogger { if (info == null) { return null; } - if (!info.allDrawn() && info.mPendingFullyDrawn == null) { + if (!info.mIsDrawn && info.mPendingFullyDrawn == null) { // There are still undrawn activities, postpone reporting fully drawn until all of its // windows are drawn. So that is closer to an usable state. info.mPendingFullyDrawn = () -> { 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 0b918025bb50..d4d8b86850c6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -477,7 +477,6 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { @Test public void testConsecutiveLaunch() { - mTrampolineActivity.setState(ActivityRecord.State.INITIALIZING, "test"); onActivityLaunched(mTrampolineActivity); mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent, mTrampolineActivity /* caller */, mTrampolineActivity.getUid()); |