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

Commit f9527fd0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Report launch time on the last started activity"

parents 793c088a 1c5d72ee
Loading
Loading
Loading
Loading
+23 −7
Original line number Original line Diff line number Diff line
@@ -187,9 +187,24 @@ class ActivityMetricsLogger {
        private int startingWindowDelayMs = INVALID_DELAY;
        private int startingWindowDelayMs = INVALID_DELAY;
        private int bindApplicationDelayMs = INVALID_DELAY;
        private int bindApplicationDelayMs = INVALID_DELAY;
        private int reason = APP_TRANSITION_TIMEOUT;
        private int reason = APP_TRANSITION_TIMEOUT;
        private boolean loggedWindowsDrawn;
        private int numUndrawnActivities;
        private boolean loggedStartingWindowDrawn;
        private boolean loggedStartingWindowDrawn;
        private boolean launchTraceActive;
        private boolean launchTraceActive;

        /**
         * Remembers the latest launched activity to represent the final transition. This also
         * increments the number of activities that should be drawn, so a consecutive launching
         * sequence can be coalesced as one event.
         */
        void setLatestLaunchedActivity(ActivityRecord r) {
            if (launchedActivity == r) {
                return;
            }
            launchedActivity = r;
            if (!r.noDisplay) {
                numUndrawnActivities++;
            }
        }
    }
    }


    final class WindowingModeTransitionInfoSnapshot {
    final class WindowingModeTransitionInfoSnapshot {
@@ -400,7 +415,7 @@ class ActivityMetricsLogger {
            // the other attributes.
            // the other attributes.


            // Coalesce multiple (trampoline) activities from a single sequence together.
            // Coalesce multiple (trampoline) activities from a single sequence together.
            info.launchedActivity = launchedActivity;
            info.setLatestLaunchedActivity(launchedActivity);
            return;
            return;
        }
        }


@@ -422,7 +437,7 @@ class ActivityMetricsLogger {
        // A new launch sequence [with the windowingMode] has begun.
        // A new launch sequence [with the windowingMode] has begun.
        // Start tracking it.
        // Start tracking it.
        final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
        final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
        newInfo.launchedActivity = launchedActivity;
        newInfo.setLatestLaunchedActivity(launchedActivity);
        newInfo.currentTransitionProcessRunning = processRunning;
        newInfo.currentTransitionProcessRunning = processRunning;
        newInfo.startResult = resultCode;
        newInfo.startResult = resultCode;
        mWindowingModeTransitionInfo.put(windowingMode, newInfo);
        mWindowingModeTransitionInfo.put(windowingMode, newInfo);
@@ -448,11 +463,11 @@ class ActivityMetricsLogger {
        if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
        if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);


        final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
        final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
        if (info == null || info.loggedWindowsDrawn) {
        if (info == null || info.numUndrawnActivities == 0) {
            return null;
            return null;
        }
        }
        info.windowsDrawnDelayMs = calculateDelay(timestampNs);
        info.windowsDrawnDelayMs = calculateDelay(timestampNs);
        info.loggedWindowsDrawn = true;
        info.numUndrawnActivities--;
        final WindowingModeTransitionInfoSnapshot infoSnapshot =
        final WindowingModeTransitionInfoSnapshot infoSnapshot =
                new WindowingModeTransitionInfoSnapshot(info);
                new WindowingModeTransitionInfoSnapshot(info);
        if (allWindowsDrawn() && mLoggedTransitionStarting) {
        if (allWindowsDrawn() && mLoggedTransitionStarting) {
@@ -594,9 +609,10 @@ class ActivityMetricsLogger {
        }
        }
    }
    }


    private boolean allWindowsDrawn() {
    @VisibleForTesting
    boolean allWindowsDrawn() {
        for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
        for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
            if (!mWindowingModeTransitionInfo.valueAt(index).loggedWindowsDrawn) {
            if (mWindowingModeTransitionInfo.valueAt(index).numUndrawnActivities != 0) {
                return false;
                return false;
            }
            }
        }
        }
+68 −78
Original line number Original line Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.server.wm;


import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -63,10 +61,8 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    private ActivityMetricsLaunchObserver mLaunchObserver;
    private ActivityMetricsLaunchObserver mLaunchObserver;
    private ActivityMetricsLaunchObserverRegistry mLaunchObserverRegistry;
    private ActivityMetricsLaunchObserverRegistry mLaunchObserverRegistry;


    private ActivityStack mStack;
    private ActivityRecord mTrampolineActivity;
    private TaskRecord mTask;
    private ActivityRecord mTopActivity;
    private ActivityRecord mActivityRecord;
    private ActivityRecord mActivityRecordTrampoline;


    @Before
    @Before
    public void setUpAMLO() {
    public void setUpAMLO() {
@@ -80,15 +76,10 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {


        // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
        // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
        // This seems to be the easiest way to create an ActivityRecord.
        // This seems to be the easiest way to create an ActivityRecord.
        mStack = new StackBuilder(mRootActivityContainer)
        mTrampolineActivity = new ActivityBuilder(mService).setCreateTask(true).build();
                .setActivityType(ACTIVITY_TYPE_STANDARD)
        mTopActivity = new ActivityBuilder(mService)
                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                .setTask(mTrampolineActivity.getTaskRecord())
                .setOnTop(true)
                .setCreateActivity(true)
                .build();
                .build();
        mTask = mStack.topTask();
        mActivityRecord = mTask.getTopActivity();
        mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
    }
    }


    @After
    @After
@@ -123,8 +114,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
        return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
        return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
    }
    }


    @Test
    private void onIntentStarted() {
    public void testOnIntentStarted() throws Exception {
        Intent intent = new Intent("action 1");
        Intent intent = new Intent("action 1");


        mActivityMetricsLogger.notifyActivityLaunching(intent);
        mActivityMetricsLogger.notifyActivityLaunching(intent);
@@ -134,123 +124,123 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    }
    }


    @Test
    @Test
    public void testOnIntentFailed() throws Exception {
    public void testOnIntentFailed() {
        testOnIntentStarted();
        onIntentStarted();

        ActivityRecord activityRecord = null;


        // Bringing an intent that's already running 'to front' is not considered
        // Bringing an intent that's already running 'to front' is not considered
        // as an ACTIVITY_LAUNCHED state transition.
        // as an ACTIVITY_LAUNCHED state transition.
        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
                activityRecord);
                null /* launchedActivity */);


        verifyAsync(mLaunchObserver).onIntentFailed();
        verifyAsync(mLaunchObserver).onIntentFailed();
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    private void onActivityLaunched() {
    public void testOnActivityLaunched() throws Exception {
        onIntentStarted();
        testOnIntentStarted();


        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTopActivity);
                mActivityRecord);


        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mActivityRecord), anyInt());
        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    @Test
    public void testOnActivityLaunchFinished() throws Exception {
    public void testOnActivityLaunchFinished() {
       testOnActivityLaunched();
        onActivityLaunched();


        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
                SystemClock.elapsedRealtimeNanos());
                SystemClock.elapsedRealtimeNanos());


       mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecord.getWindowingMode(),
        notifyWindowsDrawn(mTopActivity);
               SystemClock.elapsedRealtimeNanos());


       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecord), anyLong());
        verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    @Test
    public void testOnActivityLaunchCancelled() throws Exception {
    public void testOnActivityLaunchCancelled() {
       testOnActivityLaunched();
        onActivityLaunched();


       mActivityRecord.mDrawn = true;
        mTopActivity.mDrawn = true;


        // Cannot time already-visible activities.
        // Cannot time already-visible activities.
       mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mActivityRecord);
        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity);


       verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mActivityRecord));
        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTopActivity));
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    @Test
    public void testOnReportFullyDrawn() throws Exception {
    public void testOnReportFullyDrawn() {
        testOnActivityLaunched();
        onActivityLaunched();


        mActivityMetricsLogger.logAppTransitionReportedDrawn(mActivityRecord, false);
        mActivityMetricsLogger.logAppTransitionReportedDrawn(mTopActivity, false);


        verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mActivityRecord), anyLong());
        verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong());
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    private void onActivityLaunchedTrampoline() {
    public void testOnActivityLaunchedTrampoline() throws Exception {
        onIntentStarted();
        testOnIntentStarted();


        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTopActivity);
                mActivityRecord);


        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mActivityRecord), anyInt());
        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());


        // A second, distinct, activity launch is coalesced into the the current app launch sequence
        // A second, distinct, activity launch is coalesced into the the current app launch sequence
        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTrampolineActivity);
                mActivityRecordTrampoline);


        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    private void notifyWindowsDrawn(ActivityRecord r) {
        mActivityMetricsLogger.notifyWindowsDrawn(r.getWindowingMode(),
                SystemClock.elapsedRealtimeNanos());
    }

    @Test
    @Test
    public void testOnActivityLaunchFinishedTrampoline() throws Exception {
    public void testOnActivityLaunchFinishedTrampoline() {
       testOnActivityLaunchedTrampoline();
        onActivityLaunchedTrampoline();


        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
                SystemClock.elapsedRealtimeNanos());
                SystemClock.elapsedRealtimeNanos());


       mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecordTrampoline.getWindowingMode(),
        notifyWindowsDrawn(mTrampolineActivity);
               SystemClock.elapsedRealtimeNanos());


       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecordTrampoline),
        assertWithMessage("Trampoline activity is drawn but the top activity is not yet")
                .that(mActivityMetricsLogger.allWindowsDrawn()).isFalse();

        notifyWindowsDrawn(mTopActivity);

        verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTrampolineActivity),
                anyLong());
                anyLong());
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    @Test
    public void testOnActivityLaunchCancelledTrampoline() throws Exception {
    public void testOnActivityLaunchCancelledTrampoline() {
       testOnActivityLaunchedTrampoline();
        onActivityLaunchedTrampoline();


       mActivityRecordTrampoline.mDrawn = true;
        mTrampolineActivity.mDrawn = true;


        // Cannot time already-visible activities.
        // Cannot time already-visible activities.
       mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTrampolineActivity);
               mActivityRecordTrampoline);


       verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mActivityRecordTrampoline));
        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
        verifyNoMoreInteractions(mLaunchObserver);
        verifyNoMoreInteractions(mLaunchObserver);
    }
    }


    @Test
    @Test
    public void testActivityRecordProtoIsNotTooBig() throws Exception {
    public void testActivityRecordProtoIsNotTooBig() {
        // The ActivityRecordProto must not be too big, otherwise converting it at runtime
        // The ActivityRecordProto must not be too big, otherwise converting it at runtime
        // will become prohibitively expensive.
        // will become prohibitively expensive.
        assertWithMessage("mActivityRecord: %s", mActivityRecord).
        assertWithMessage("mTopActivity: %s", mTopActivity)
                that(activityRecordToProto(mActivityRecord).length).
                .that(activityRecordToProto(mTopActivity).length)
                isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
                .isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);


        assertWithMessage("mActivityRecordTrampoline: %s", mActivityRecordTrampoline).
        assertWithMessage("mTrampolineActivity: %s", mTrampolineActivity)
                that(activityRecordToProto(mActivityRecordTrampoline).length).
                .that(activityRecordToProto(mTrampolineActivity).length)
                isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
                .isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
    }
    }
}
}