AML: Abort launching metrics if no activities will be drawn
Otherwise it may report a large launch time on an invisible
activity that depends on when to trigger next transition.
Bug: 123355661
Test: atest ActivityMetricsLaunchObserverTests# \
testOnActivityLaunchCancelled_finishedBeforeDrawn
Change-Id: I6f936929a5ed6ade0e6350d9fde8229d6aaad558
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 9d41d97..04c2083 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -403,8 +403,7 @@
if (launchedActivity != null && launchedActivity.mDrawn) {
// Launched activity is already visible. We cannot measure windows drawn delay.
- reset(true /* abort */, info, "launched activity already visible",
- 0L /* timestampNs */);
+ abort(info, "launched activity already visible");
return;
}
@@ -422,8 +421,7 @@
if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
|| windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
// Failed to launch or it was not a process switch, so we don't care about the timing.
- reset(true /* abort */, info, "failed to launch or not a process switch",
- 0L /* timestampNs */);
+ abort(info, "failed to launch or not a process switch");
return;
} else if (otherWindowModesLaunching) {
// Don't log this windowing mode but continue with the other windowing modes.
@@ -469,8 +467,7 @@
final WindowingModeTransitionInfoSnapshot infoSnapshot =
new WindowingModeTransitionInfoSnapshot(info);
if (allWindowsDrawn() && mLoggedTransitionStarting) {
- reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn",
- timestampNs /* timestampNs */);
+ reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn", timestampNs);
}
return infoSnapshot;
}
@@ -544,10 +541,11 @@
mHandler.obtainMessage(MSG_CHECK_VISIBILITY, args).sendToTarget();
}
- private boolean hasVisibleNonFinishingActivity(TaskRecord t) {
+ /** @return {@code true} if the given task has an activity will be drawn. */
+ private static boolean hasActivityToBeDrawn(TaskRecord t) {
for (int i = t.getChildCount() - 1; i >= 0; --i) {
final ActivityRecord r = t.getChildAt(i);
- if (r.visible && !r.finishing) {
+ if (r.visible && !r.mDrawn && !r.finishing) {
return true;
}
}
@@ -574,19 +572,20 @@
return;
}
- // Check if there is any activity in the task that is visible and not finishing. If the
- // launched activity finished before it is drawn and if there is another activity in
- // the task then that activity will be draw on screen.
- if (hasVisibleNonFinishingActivity(t)) {
+ // 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
+ // should be cancelled.
+ if (hasActivityToBeDrawn(t)) {
return;
}
if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible activity=" + r);
logAppTransitionCancel(info);
- mWindowingModeTransitionInfo.remove(r.getWindowingMode());
- if (mWindowingModeTransitionInfo.size() == 0) {
- reset(true /* abort */, info, "notifyVisibilityChanged to invisible",
- 0L /* timestampNs */);
+ // Abort if this is the only one active transition.
+ if (mWindowingModeTransitionInfo.size() == 1
+ && mWindowingModeTransitionInfo.get(r.getWindowingMode()) != null) {
+ abort(info, "notifyVisibilityChanged to invisible");
}
}
}
@@ -622,19 +621,25 @@
&& mWindowingModeTransitionInfo.size() > 0;
}
+ /** Aborts tracking of current launch metrics. */
+ private void abort(WindowingModeTransitionInfo info, String cause) {
+ reset(true /* abort */, info, cause, 0L /* timestampNs */);
+ }
+
private void reset(boolean abort, WindowingModeTransitionInfo info, String cause,
- long timestampNs) {
+ long timestampNs) {
+ final boolean isAnyTransitionActive = isAnyTransitionActive();
if (DEBUG_METRICS) {
- Slog.i(TAG,
- "reset abort=" + abort + ",cause=" + cause + ",timestamp=" + timestampNs);
+ Slog.i(TAG, "reset abort=" + abort + " cause=" + cause + " timestamp=" + timestampNs
+ + " active=" + isAnyTransitionActive);
}
- if (!abort && isAnyTransitionActive()) {
+ if (!abort && isAnyTransitionActive) {
logAppTransitionMultiEvents();
}
stopLaunchTrace(info);
// Ignore reset-after reset.
- if (isAnyTransitionActive()) {
+ if (isAnyTransitionActive) {
// LaunchObserver callbacks.
if (abort) {
launchObserverNotifyActivityLaunchCancelled(info);