From faf29141fcbd0b9a6ff2119b82bea51fbfedd8af Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 4 Jun 2021 00:42:31 +0800 Subject: [PATCH] Discard invisible pending draw activity if transition starts A launching activity may never have visibility set. If another drawn activity in the same launch sequence can trigger to start transition, the launch event should still be done successfully. E.g. warm launch from notification with a trampoline activity. The trampoline activity keeps the initial invisible state because lockscreen hasn't gone. And only the target activity will be set to visible and drawn to start transition. Fixes: 189882294 Test: atest ActivityMetricsLaunchObserverTests# \ testDoNotCountInvisibleActivityToBeDrawn Change-Id: I1cd5d016c70e5f7865d3d44c8d7ceaa97d5a34ea --- .../android/server/wm/ActivityMetricsLogger.java | 15 +++++++++++++-- .../wm/ActivityMetricsLaunchObserverTests.java | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index a781520c48d93..2b6a83896cc63 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -102,7 +102,6 @@ import com.android.server.apphibernation.AppHibernationManagerInternal; import com.android.server.apphibernation.AppHibernationService; import java.util.ArrayList; -import java.util.LinkedList; import java.util.concurrent.TimeUnit; /** @@ -216,7 +215,7 @@ class ActivityMetricsLogger { /** whether the process of the launching activity didn't have any active activity. */ final boolean mProcessSwitch; /** The activities that should be drawn. */ - final LinkedList mPendingDrawActivities = new LinkedList<>(); + final ArrayList mPendingDrawActivities = new ArrayList<>(2); /** The latest activity to have been launched. */ @NonNull ActivityRecord mLastLaunchedActivity; @@ -328,6 +327,17 @@ class ActivityMetricsLogger { return mPendingDrawActivities.isEmpty(); } + /** Only keep the records which can be drawn. */ + void updatePendingDraw() { + for (int i = mPendingDrawActivities.size() - 1; i >= 0; i--) { + final ActivityRecord r = mPendingDrawActivities.get(i); + if (!r.mVisibleRequested) { + if (DEBUG_METRICS) Slog.i(TAG, "Discard pending draw " + r); + mPendingDrawActivities.remove(i); + } + } + } + /** * @return {@code true} if the transition info should be sent to MetricsLogger, StatsLog, or * LaunchObserver. @@ -701,6 +711,7 @@ class ActivityMetricsLogger { info.mCurrentTransitionDelayMs = info.calculateDelay(timestampNs); info.mReason = activityToReason.valueAt(index); info.mLoggedTransitionStarting = true; + info.updatePendingDraw(); if (info.allDrawn()) { done(false /* abort */, info, "notifyTransitionStarting - all windows drawn", timestampNs); 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 beff3862df010..82c459c6868a4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -353,8 +353,22 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { mTrampolineActivity.setVisibility(false); notifyWindowsDrawn(mTopActivity); - assertWithMessage("Trampoline activity is invisble so there should be no undrawn windows") + assertWithMessage("Trampoline activity is invisible so there should be no undrawn windows") .that(mLaunchingState.allDrawn()).isTrue(); + + // Since the activity is drawn, the launch event should be reported. + notifyTransitionStarting(mTopActivity); + verifyOnActivityLaunchFinished(mTopActivity); + mLaunchTopByTrampoline = false; + clearInvocations(mLaunchObserver); + + // Another round without setting visibility of the trampoline activity. + onActivityLaunchedTrampoline(); + notifyWindowsDrawn(mTopActivity); + // If the transition can start, the invisible activities should be discarded and the launch + // event be reported successfully. + notifyTransitionStarting(mTopActivity); + verifyOnActivityLaunchFinished(mTopActivity); } @Test