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

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

Merge "AML: Abort launching metrics if no activities will be drawn"

parents 3ff32e08 1063b517
Loading
Loading
Loading
Loading
+26 −21
Original line number Diff line number Diff line
@@ -403,8 +403,7 @@ class ActivityMetricsLogger {

        if (launchedActivity != null && launchedActivity.mDrawn) {
            // Launched activity is already visible. We cannot measure windows drawn delay.
            reset(true /* abort */, info, "launched activity already visible",
                0L /* timestampNs */);
            abort(info, "launched activity already visible");
            return;
        }

@@ -422,8 +421,7 @@ class ActivityMetricsLogger {
        if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
                || windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
            // Failed to launch or it was not a process switch, so we don't care about the timing.
            reset(true /* abort */, info, "failed to launch or not a process switch",
                0L /* timestampNs */);
            abort(info, "failed to launch or not a process switch");
            return;
        } else if (otherWindowModesLaunching) {
            // Don't log this windowing mode but continue with the other windowing modes.
@@ -469,8 +467,7 @@ class ActivityMetricsLogger {
        final WindowingModeTransitionInfoSnapshot infoSnapshot =
                new WindowingModeTransitionInfoSnapshot(info);
        if (allWindowsDrawn() && mLoggedTransitionStarting) {
            reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn",
                timestampNs /* timestampNs */);
            reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn", timestampNs);
        }
        return infoSnapshot;
    }
@@ -544,10 +541,11 @@ class ActivityMetricsLogger {
        mHandler.obtainMessage(MSG_CHECK_VISIBILITY, args).sendToTarget();
    }

    private boolean hasVisibleNonFinishingActivity(TaskRecord t) {
    /** @return {@code true} if the given task has an activity will be drawn. */
    private static boolean hasActivityToBeDrawn(TaskRecord t) {
        for (int i = t.getChildCount() - 1; i >= 0; --i) {
            final ActivityRecord r = t.getChildAt(i);
            if (r.visible && !r.finishing) {
            if (r.visible && !r.mDrawn && !r.finishing) {
                return true;
            }
        }
@@ -574,19 +572,20 @@ class ActivityMetricsLogger {
                return;
            }

            // Check if there is any activity in the task that is visible and not finishing. If the
            // launched activity finished before it is drawn and if there is another activity in
            // the task then that activity will be draw on screen.
            if (hasVisibleNonFinishingActivity(t)) {
            // If the task of the launched activity contains any activity to be drawn, then the
            // window drawn event should report later to complete the transition. Otherwise all
            // activities in this task may be finished, invisible or drawn, so the transition event
            // should be cancelled.
            if (hasActivityToBeDrawn(t)) {
                return;
            }

            if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible activity=" + r);
            logAppTransitionCancel(info);
            mWindowingModeTransitionInfo.remove(r.getWindowingMode());
            if (mWindowingModeTransitionInfo.size() == 0) {
                reset(true /* abort */, info, "notifyVisibilityChanged to invisible",
                    0L /* timestampNs */);
            // Abort if this is the only one active transition.
            if (mWindowingModeTransitionInfo.size() == 1
                    && mWindowingModeTransitionInfo.get(r.getWindowingMode()) != null) {
                abort(info, "notifyVisibilityChanged to invisible");
            }
        }
    }
@@ -622,19 +621,25 @@ class ActivityMetricsLogger {
                && mWindowingModeTransitionInfo.size() > 0;
    }

    /** Aborts tracking of current launch metrics. */
    private void abort(WindowingModeTransitionInfo info, String cause) {
        reset(true /* abort */, info, cause, 0L /* timestampNs */);
    }

    private void reset(boolean abort, WindowingModeTransitionInfo info, String cause,
            long timestampNs) {
        final boolean isAnyTransitionActive = isAnyTransitionActive();
        if (DEBUG_METRICS) {
            Slog.i(TAG,
                "reset abort=" + abort + ",cause=" + cause + ",timestamp=" + timestampNs);
            Slog.i(TAG, "reset abort=" + abort + " cause=" + cause + " timestamp=" + timestampNs
                    + " active=" + isAnyTransitionActive);
        }
        if (!abort && isAnyTransitionActive()) {
        if (!abort && isAnyTransitionActive) {
            logAppTransitionMultiEvents();
        }
        stopLaunchTrace(info);

        // Ignore reset-after reset.
        if (isAnyTransitionActive()) {
        if (isAnyTransitionActive) {
            // LaunchObserver callbacks.
            if (abort) {
                launchObserverNotifyActivityLaunchCancelled(info);
+39 −17
Original line number Diff line number Diff line
@@ -149,9 +149,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    public void testOnActivityLaunchFinished() {
        onActivityLaunched();

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

        notifyTransitionStarting();
        notifyWindowsDrawn(mTopActivity);

        verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
@@ -159,10 +157,10 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    }

    @Test
    public void testOnActivityLaunchCancelled() {
    public void testOnActivityLaunchCancelled_hasDrawn() {
        onActivityLaunched();

        mTopActivity.mDrawn = true;
        mTopActivity.visible = mTopActivity.mDrawn = true;

        // Cannot time already-visible activities.
        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity);
@@ -171,6 +169,28 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
        verifyNoMoreInteractions(mLaunchObserver);
    }

    @Test
    public void testOnActivityLaunchCancelled_finishedBeforeDrawn() {
        mTopActivity.visible = mTopActivity.mDrawn = true;

        // Suppress resume when creating the record because we want to notify logger manually.
        mSupervisor.beginDeferResume();
        // Create an activity with different process that meets process switch.
        final ActivityRecord noDrawnActivity = new ActivityBuilder(mService)
                .setTask(mTopActivity.getTaskRecord())
                .setProcessName("other")
                .build();
        mSupervisor.readyToResume();

        mActivityMetricsLogger.notifyActivityLaunching(noDrawnActivity.intent);
        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, noDrawnActivity);

        noDrawnActivity.destroyIfPossible("test");
        mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity);

        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity));
    }

    @Test
    public void testOnReportFullyDrawn() {
        onActivityLaunched();
@@ -184,16 +204,21 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    private void onActivityLaunchedTrampoline() {
        onIntentStarted();

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

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

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

        verifyNoMoreInteractions(mLaunchObserver);
    }

    private void notifyTransitionStarting() {
        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
                SystemClock.elapsedRealtimeNanos());
    }

    private void notifyWindowsDrawn(ActivityRecord r) {
        mActivityMetricsLogger.notifyWindowsDrawn(r.getWindowingMode(),
                SystemClock.elapsedRealtimeNanos());
@@ -203,15 +228,12 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    public void testOnActivityLaunchFinishedTrampoline() {
        onActivityLaunchedTrampoline();

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

        notifyTransitionStarting();
        notifyWindowsDrawn(mTrampolineActivity);

        notifyWindowsDrawn(mTopActivity);

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

@@ -219,12 +241,12 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
    public void testOnActivityLaunchCancelledTrampoline() {
        onActivityLaunchedTrampoline();

        mTrampolineActivity.mDrawn = true;
        mTopActivity.mDrawn = true;

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

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

+9 −2
Original line number Diff line number Diff line
@@ -118,7 +118,8 @@ class ActivityTestsBase extends SystemServiceTestsBase {
        private ComponentName mComponent;
        private String mTargetActivity;
        private TaskRecord mTaskRecord;
        private int mUid;
        private String mProcessName = "name";
        private int mUid = 12345;
        private boolean mCreateTask;
        private ActivityStack mStack;
        private int mActivityFlags;
@@ -175,6 +176,11 @@ class ActivityTestsBase extends SystemServiceTestsBase {
            return this;
        }

        ActivityBuilder setProcessName(String name) {
            mProcessName = name;
            return this;
        }

        ActivityBuilder setUid(int uid) {
            mUid = uid;
            return this;
@@ -235,6 +241,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
            aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
            aInfo.applicationInfo.packageName = mComponent.getPackageName();
            aInfo.applicationInfo.uid = mUid;
            aInfo.processName = mProcessName;
            aInfo.packageName = mComponent.getPackageName();
            if (mTargetActivity != null) {
                aInfo.targetActivity = mTargetActivity;
@@ -268,7 +275,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
            }

            final WindowProcessController wpc = new WindowProcessController(mService,
                    mService.mContext.getApplicationInfo(), "name", 12345,
                    mService.mContext.getApplicationInfo(), mProcessName, mUid,
                    UserHandle.getUserId(12345), mock(Object.class),
                    mock(WindowProcessListener.class));
            wpc.setThread(mock(IApplicationThread.class));