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
This commit is contained in:
Riddle Hsu
2021-04-29 20:14:41 +08:00
parent 285e375408
commit a808b65309
6 changed files with 22 additions and 35 deletions

View File

@@ -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;

View File

@@ -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,

View File

@@ -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(

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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