Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4207adf authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Update to cold launch if the process is restarted during launching

The current common case is that the process of the resuming activity
is just unfrozen but its binder buffer is full (someone still sends
async binder call to it when it is frozen) and the process could
be killed because binder transaction failed. Then the process will
attach again so the launch type can be corrected to COLD to avoid
disturb the distribution of metrics.

Bug: 291599121
Test: atest ActivityMetricsLaunchObserverTests#testLaunchState
Change-Id: I26252410508d21aacacd35bd6cc305dc7a0fc9f9
parent 39759a9e
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -285,9 +285,9 @@ class ActivityMetricsLogger {
        final LaunchingState mLaunchingState;

        /** The type can be cold (new process), warm (new activity), or hot (bring to front). */
        final int mTransitionType;
        int mTransitionType;
        /** Whether the process was already running when the transition started. */
        final boolean mProcessRunning;
        boolean mProcessRunning;
        /** whether the process of the launching activity didn't have any active activity. */
        final boolean mProcessSwitch;
        /** The process state of the launching activity prior to the launch */
@@ -972,6 +972,19 @@ class ActivityMetricsLogger {
            // App isn't attached to record yet, so match with info.
            if (info.mLastLaunchedActivity.info.applicationInfo == appInfo) {
                info.mBindApplicationDelayMs = info.calculateCurrentDelay();
                if (info.mProcessRunning) {
                    // It was HOT/WARM launch, but the process was died somehow right after the
                    // launch request.
                    info.mProcessRunning = false;
                    info.mTransitionType = TYPE_TRANSITION_COLD_LAUNCH;
                    final String msg = "Process " + info.mLastLaunchedActivity.info.processName
                            + " restarted";
                    Slog.i(TAG, msg);
                    if (info.mLaunchingState.mTraceName != null) {
                        Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, msg + "#"
                                + LaunchingState.sTraceSeqId);
                    }
                }
            }
        }
    }
+13 −7
Original line number Diff line number Diff line
@@ -182,12 +182,12 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {

    @Test
    public void testLaunchState() {
        final ToIntFunction<Boolean> launchTemplate = doRelaunch -> {
        final ToIntFunction<Runnable> launchTemplate = action -> {
            clearInvocations(mLaunchObserver);
            onActivityLaunched(mTopActivity);
            notifyTransitionStarting(mTopActivity);
            if (doRelaunch) {
                mActivityMetricsLogger.notifyActivityRelaunched(mTopActivity);
            if (action != null) {
                action.run();
            }
            final ActivityMetricsLogger.TransitionInfoSnapshot info =
                    notifyWindowsDrawn(mTopActivity);
@@ -199,21 +199,27 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
        // Assume that the process is started (ActivityBuilder has mocked the returned value of
        // ATMS#getProcessController) but the activity has not attached process.
        mTopActivity.app = null;
        assertWithMessage("Warm launch").that(launchTemplate.applyAsInt(false /* doRelaunch */))
        assertWithMessage("Warm launch").that(launchTemplate.applyAsInt(null))
                .isEqualTo(WaitResult.LAUNCH_STATE_WARM);

        mTopActivity.app = app;
        mNewActivityCreated = false;
        assertWithMessage("Hot launch").that(launchTemplate.applyAsInt(false /* doRelaunch */))
        assertWithMessage("Hot launch").that(launchTemplate.applyAsInt(null))
                .isEqualTo(WaitResult.LAUNCH_STATE_HOT);

        assertWithMessage("Relaunch").that(launchTemplate.applyAsInt(true /* doRelaunch */))
        assertWithMessage("Relaunch").that(launchTemplate.applyAsInt(
                () -> mActivityMetricsLogger.notifyActivityRelaunched(mTopActivity)))
                .isEqualTo(WaitResult.LAUNCH_STATE_RELAUNCH);

        assertWithMessage("Cold launch by restart").that(launchTemplate.applyAsInt(
                () -> mActivityMetricsLogger.notifyBindApplication(
                        mTopActivity.info.applicationInfo)))
                .isEqualTo(WaitResult.LAUNCH_STATE_COLD);

        mTopActivity.app = null;
        mNewActivityCreated = true;
        doReturn(null).when(mAtm).getProcessController(app.mName, app.mUid);
        assertWithMessage("Cold launch").that(launchTemplate.applyAsInt(false /* doRelaunch */))
        assertWithMessage("Cold launch").that(launchTemplate.applyAsInt(null))
                .isEqualTo(WaitResult.LAUNCH_STATE_COLD);
    }