From a808b65309da2fce9e5410dc1cd64fc967415fe7 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Thu, 29 Apr 2021 20:14:41 +0800 Subject: [PATCH] Tell activity metrics logger whether a new activity is created That helps to distinguish hot/warm launch more accurately. In most cases it was no problem because the previous foreground activity needs to be pause first so the activity won't attach to process when executing the launch request. But if all activities are already paused and the launching activity can be resumed directly, ATS#realStartActivityLocked will be called immediately so the transition type becomes always hot launch. E.g. launch activity which can occlude keyguard from lockscreen. Also removed unused ActivityStarter#startResolvedActivity. Bug: 186692122 Test: ActivityMetricsLoggerTests ActivityMetricsLaunchObserverTests Change-Id: I2bcc4bb3325c2e69e27d0deef188272c943ab6ce --- .../server/wm/ActivityMetricsLogger.java | 14 ++++++---- .../android/server/wm/ActivityStarter.java | 28 ++----------------- .../server/wm/ActivityTaskSupervisor.java | 3 +- .../android/server/wm/RecentsAnimation.java | 2 +- .../ActivityMetricsLaunchObserverTests.java | 7 +++-- .../server/wm/ActivityStarterTests.java | 3 +- 6 files changed, 22 insertions(+), 35 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 561f1ad75c12c..09461132ef37e 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -247,13 +247,14 @@ class ActivityMetricsLogger { @Nullable static TransitionInfo create(@NonNull ActivityRecord r, @NonNull LaunchingState launchingState, @Nullable ActivityOptions options, - boolean processRunning, boolean processSwitch, int startResult) { + boolean processRunning, boolean processSwitch, boolean newActivityCreated, + int startResult) { if (startResult != START_SUCCESS && startResult != START_TASK_TO_FRONT) { return null; } final int transitionType; if (processRunning) { - transitionType = r.attachedToProcess() + transitionType = !newActivityCreated && r.attachedToProcess() ? TYPE_TRANSITION_HOT_LAUNCH : TYPE_TRANSITION_WARM_LAUNCH; } else { @@ -560,10 +561,12 @@ class ActivityMetricsLogger { * @param resultCode One of the {@link android.app.ActivityManager}.START_* flags, indicating * the result of the launch. * @param launchedActivity The activity that is being launched + * @param newActivityCreated Whether a new activity instance is created. * @param options The given options of the launching activity. */ void notifyActivityLaunched(@NonNull LaunchingState launchingState, int resultCode, - @Nullable ActivityRecord launchedActivity, @Nullable ActivityOptions options) { + boolean newActivityCreated, @Nullable ActivityRecord launchedActivity, + @Nullable ActivityOptions options) { if (launchedActivity == null) { // The launch is aborted, e.g. intent not resolved, class not found. abort(null /* info */, "nothing launched"); @@ -587,7 +590,8 @@ class ActivityMetricsLogger { if (DEBUG_METRICS) { Slog.i(TAG, "notifyActivityLaunched" + " resultCode=" + resultCode + " launchedActivity=" + launchedActivity + " processRunning=" + processRunning - + " processSwitch=" + processSwitch + " info=" + info); + + " processSwitch=" + processSwitch + + " newActivityCreated=" + newActivityCreated + " info=" + info); } if (launchedActivity.isReportedDrawn() && launchedActivity.isVisible()) { @@ -608,7 +612,7 @@ class ActivityMetricsLogger { } final TransitionInfo newInfo = TransitionInfo.create(launchedActivity, launchingState, - options, processRunning, processSwitch, resultCode); + options, processRunning, processSwitch, newActivityCreated, resultCode); if (newInfo == null) { abort(info, "unrecognized launch"); return; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 08a9f0928b8b3..0d3c74ef318b9 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -601,30 +601,6 @@ class ActivityStarter { || (mStartActivity != null && packageName.equals(mStartActivity.packageName)); } - /** - * Starts an activity based on the provided {@link ActivityRecord} and environment parameters. - * Note that this method is called internally as well as part of {@link #executeRequest}. - */ - void startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord, - IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, - int startFlags, boolean doResume, ActivityOptions options, Task inTask, - NeededUriGrants intentGrants) { - try { - final LaunchingState launchingState = mSupervisor.getActivityMetricsLogger() - .notifyActivityLaunching(r.intent, r.resultTo); - mLastStartReason = "startResolvedActivity"; - mLastStartActivityTimeMs = System.currentTimeMillis(); - mLastStartActivityRecord = r; - mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, - voiceInteractor, startFlags, doResume, options, inTask, - false /* restrictedBgActivity */, intentGrants); - mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, - mLastStartActivityResult, mLastStartActivityRecord, options); - } finally { - onExecutionComplete(); - } - } - /** * Resolve necessary information according the request parameters provided earlier, and execute * the request which begin the journey of starting an activity. @@ -707,11 +683,13 @@ class ActivityStarter { // used here because it may be cleared in setTargetRootTaskIfNeeded. final ActivityOptions originalOptions = mRequest.activityOptions != null ? mRequest.activityOptions.getOriginalOptions() : null; + // If the new record is the one that started, a new activity has created. + final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord; // Notify ActivityMetricsLogger that the activity has launched. // ActivityMetricsLogger will then wait for the windows to be drawn and populate // WaitResult. mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res, - mLastStartActivityRecord, originalOptions); + newActivityCreated, mLastStartActivityRecord, originalOptions); if (mRequest.waitResult != null) { mRequest.waitResult.result = res; res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord, diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index df1fec9ad0da5..8583061a39861 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -2542,7 +2542,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { targetActivity.applyOptionsAnimation(); } finally { mActivityMetricsLogger.notifyActivityLaunched(launchingState, - START_TASK_TO_FRONT, targetActivity, activityOptions); + START_TASK_TO_FRONT, false /* newActivityCreated */, targetActivity, + activityOptions); } mService.getActivityStartController().postStartActivityProcessingForLastStarter( diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 869133ae948c2..a10b5d6e81771 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -255,7 +255,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime); } mTaskSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, - START_TASK_TO_FRONT, targetActivity, options); + START_TASK_TO_FRONT, !hasExistingActivity, targetActivity, options); // Register for root task order changes mDefaultTaskDisplayArea.registerRootTaskOrderChangedListener(this); 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 2148589529f33..349270ff708a9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -77,6 +77,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { private ActivityRecord mTopActivity; private ActivityOptions mActivityOptions; private boolean mLaunchTopByTrampoline; + private boolean mNewActivityCreated = true; @Before public void setUpAMLO() { @@ -187,6 +188,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { .isEqualTo(WaitResult.LAUNCH_STATE_WARM); mTopActivity.app = app; + mNewActivityCreated = false; assertWithMessage("Hot launch").that(launchTemplate.applyAsInt(false /* doRelaunch */)) .isEqualTo(WaitResult.LAUNCH_STATE_HOT); @@ -194,6 +196,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { .isEqualTo(WaitResult.LAUNCH_STATE_RELAUNCH); mTopActivity.app = null; + mNewActivityCreated = true; doReturn(null).when(mAtm).getProcessController(app.mName, app.mUid); assertWithMessage("Cold launch").that(launchTemplate.applyAsInt(false /* doRelaunch */)) .isEqualTo(WaitResult.LAUNCH_STATE_COLD); @@ -313,8 +316,8 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { } private void notifyActivityLaunched(int resultCode, ActivityRecord activity) { - mActivityMetricsLogger.notifyActivityLaunched(mLaunchingState, resultCode, activity, - mActivityOptions); + mActivityMetricsLogger.notifyActivityLaunched(mLaunchingState, resultCode, + mNewActivityCreated, activity, mActivityOptions); } private void notifyTransitionStarting(ActivityRecord activity) { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index e6ac52d2bf6f0..0a36af2d586ac 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -870,7 +870,8 @@ public class ActivityStarterTests extends WindowTestsBase { verify(secondaryTaskContainer, times(2)).createRootTask(anyInt(), anyInt(), anyBoolean()); // The metrics logger should receive the same result and non-null options. verify(mActivityMetricsLogger).notifyActivityLaunched(any() /* launchingState */, - eq(result), eq(singleTaskActivity), notNull() /* options */); + eq(result), eq(false) /* newActivityCreated */, eq(singleTaskActivity), + notNull() /* options */); } @Test