From 2dcd75e60a4ccefc8cf316e69e81287485939b61 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 8 Mar 2022 23:12:19 +0800 Subject: [PATCH] Handle intermediate task overlay for metrics logger The corner case is introduced by intercepting trampoline activity launch with launching task overlay. E.g. trampoline -> permission prompt -> main -> permission prompt Because the prompt is overlay, there may not have visibility change. The first prompt may be cancelled by consecutive launch too earlier. And the second prompt which finishes immediately may miss to cancel. Bug: 222576471 Test: ActivityMetricsLaunchObserverTests# \ testOnActivityLaunchCancelled_finishedBeforeDrawn Change-Id: Ife39b7238169a1d54f3d60d1655868cc3cb73f25 --- .../android/server/wm/ActivityMetricsLogger.java | 6 +++++- .../wm/ActivityMetricsLaunchObserverTests.java | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index a8dd856c21916..c0cdec9ade7f7 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -657,7 +657,7 @@ class ActivityMetricsLogger { for (int i = mTransitionInfoList.size() - 2; i >= 0; i--) { final TransitionInfo prevInfo = mTransitionInfoList.get(i); if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.mVisibleRequested) { - abort(prevInfo, "nothing will be drawn"); + scheduleCheckActivityToBeDrawn(prevInfo.mLastLaunchedActivity, 0 /* delay */); } } } @@ -757,6 +757,10 @@ class ActivityMetricsLogger { /** Makes sure that the reference to the removed activity is cleared. */ void notifyActivityRemoved(@NonNull ActivityRecord r) { mLastTransitionInfo.remove(r); + final TransitionInfo info = getActiveTransitionInfo(r); + if (info != null) { + abort(info, "removed"); + } final int packageUid = r.info.applicationInfo.uid; final PackageCompatStateInfo compatStateInfo = mPackageUidToCompatStateInfo.get(packageUid); 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 d4d8b86850c65..7689e08bc3f36 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -256,6 +256,14 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity); verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity)); + + // If an activity is removed immediately before visibility update, it should cancel too. + final ActivityRecord removedImm = new ActivityBuilder(mAtm).setCreateTask(true).build(); + clearInvocations(mLaunchObserver); + onActivityLaunched(removedImm); + removedImm.removeImmediately(); + // Verify any() instead of proto because the field of record may be changed. + verifyAsync(mLaunchObserver).onActivityLaunchCancelled(any()); } @Test @@ -299,15 +307,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; + final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true).build(); + onActivityLaunched(prev); + prev.mVisibleRequested = false; mActivityOptions = ActivityOptions.makeBasic(); mActivityOptions.setSourceInfo(SourceInfo.TYPE_LAUNCHER, SystemClock.uptimeMillis() - 10); onIntentStarted(mTopActivity.intent); notifyActivityLaunched(START_SUCCESS, mTopActivity); verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt()); - verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity)); + verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(prev)); // The activity reports fully drawn before windows drawn, then the fully drawn event will // be pending (see {@link WindowingModeTransitionInfo#pendingFullyDrawn}).