diff options
| author | 2022-05-24 23:37:29 -0600 | |
|---|---|---|
| committer | 2022-05-25 18:20:08 +0800 | |
| commit | 0cbe47f3c9821dd42f40c7da6e9f9393917a2724 (patch) | |
| tree | 0a9e187799511c0e5c10ed7a98d71b1c7ebe63d9 | |
| parent | 054f5c15c9b17413e9c5a4e013adbc10ab1f5ace (diff) | |
Make sure instance launch trace for an id only appears once
A consecutive launch may contain multiple activities with different
windowing modes or target displays. The separated transition should
not end the trace of the initial launch.
e.g. start A---------------------->A drawn
|-A starts B-->B drawn (on a different display)
There will still be 2 traces "launching: A" and "launching: B".
But there should be only one trace "launchingActivity" which is
ended by "A drawn".
Bug: 231612200
Test: atest ActivityMetricsLaunchObserverTests# \
testConsecutiveLaunchOnDifferentDisplay
Change-Id: Ied39e000ef6c8c60b56e228cbdc86b6f9dbe2e6c
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityMetricsLogger.java | 22 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java | 3 |
2 files changed, 19 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index f2bcd1dbf544..d6c0ab6b124b 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -192,11 +192,10 @@ class ActivityMetricsLogger { /** The sequence id for trace. It is used to map the traces before resolving intent. */ private static int sTraceSeqId; /** The trace format is "launchingActivity#$seqId:$state(:$packageName)". */ - final String mTraceName; + String mTraceName; LaunchingState() { if (!Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { - mTraceName = null; return; } // Use an id because the launching app is not yet known before resolving intent. @@ -205,8 +204,14 @@ class ActivityMetricsLogger { Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, mTraceName, 0); } - void stopTrace(boolean abort) { + void stopTrace(boolean abort, TransitionInfo endInfo) { if (mTraceName == null) return; + if (!abort && endInfo != mAssociatedTransitionInfo) { + // Multiple TransitionInfo can be associated with the same LaunchingState (e.g. a + // launching activity launches another activity in a different windowing mode or + // display). Only the original associated info can emit a "completed" trace. + return; + } Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, mTraceName, 0); final String launchResult; if (mAssociatedTransitionInfo == null) { @@ -218,6 +223,7 @@ class ActivityMetricsLogger { } // Put a supplement trace as the description of the async trace with the same id. Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, mTraceName + launchResult); + mTraceName = null; } @VisibleForTesting @@ -321,7 +327,11 @@ class ActivityMetricsLogger { mProcessSwitch = processSwitch; mTransitionDeviceUptimeMs = launchingState.mCurrentUpTimeMs; setLatestLaunchedActivity(r); - launchingState.mAssociatedTransitionInfo = this; + // The launching state can be reused by consecutive launch. Its original association + // shouldn't be changed by a separated transition. + if (launchingState.mAssociatedTransitionInfo == null) { + launchingState.mAssociatedTransitionInfo = this; + } if (options != null) { final SourceInfo sourceInfo = options.getSourceInfo(); if (sourceInfo != null) { @@ -908,7 +918,7 @@ class ActivityMetricsLogger { return; } if (DEBUG_METRICS) Slog.i(TAG, "abort launch cause=" + cause); - state.stopTrace(true /* abort */); + state.stopTrace(true /* abort */, null /* endInfo */); launchObserverNotifyIntentFailed(state.mCurrentTransitionStartTimeNs); } @@ -924,7 +934,7 @@ class ActivityMetricsLogger { Slog.i(TAG, "done abort=" + abort + " cause=" + cause + " timestamp=" + timestampNs + " info=" + info); } - info.mLaunchingState.stopTrace(abort); + info.mLaunchingState.stopTrace(abort, info); stopLaunchTrace(info); final Boolean isHibernating = mLastHibernationStates.remove(info.mLastLaunchedActivity.packageName); 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 2fea2284ff2a..5b909a343a59 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -532,6 +532,9 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { transitToDrawnAndVerifyOnLaunchFinished(mTopActivity); setLastExpectedStartedId(activityOnNewDisplay); transitToDrawnAndVerifyOnLaunchFinished(activityOnNewDisplay); + + assertWithMessage("The launching state must not include the separated launch") + .that(mLaunchingState.contains(activityOnNewDisplay)).isFalse(); } @Test |