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

Commit 0200027d authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use actual started activity as the out activity

This removed [1] that uses the existing activity of the reused
task if the launching activity is no-display. It was a fix for
[2] that compares the initial specified component when using
command "am start -W" to start a trampoline activity that starts
another activity.

Since metrics logger can track the latest started activity by
ActivityMetricsLogger.TransitionInfo#mLastLaunchedActivity, the
workaround is no longer needed (WaitInfo#matches can know the
updated launched activity).

Besides, a trampoline activity may not always declare no-display.
So the result may be inconsistent if it depends on no-display even
if the app launch steps are the same. From the perspective of
ActivityStarter, the out activity should be the started activity
rather than the activity which may be the next resumed target.
For the launch time measurement, the metrics logger should be
responsible to handle it. That would also help to preserve the
real launch chain of activities so that setLatestLaunchedActivity
can transfer the launch cookie without missing any records.

The change in ActivityMetricsLogger is to preserve the ability to
report launch time when a trampoline activity is launched on an
existing task and moves the task from background to front. The
started activity is the trampoline and it will finish immediately.
The one that will report drawn is the previous existing activity
on the task.

[1]: I55f47766e8cdf92e31b4ddd97864cb0f5f3b751a
[2]: I7c356a8d153ddc24603acc55749e9992f9000c3f

Bug: 429103772
Flag: EXEMPT bugfix
Test: atest ActivityStarterTests#testReportStartedNoDisplayActivity
Change-Id: I3402af8a2e0a641f9974ede03fb035d2d4f11575
parent 70d5e516
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -300,6 +300,8 @@ class ActivityMetricsLogger {
        boolean mIsDrawn;
        /** The latest activity to have been launched. */
        @NonNull ActivityRecord mLastLaunchedActivity;
        /** The next activity if the latest launched activity in the same task is finishing. */
        @Nullable ActivityRecord mNextRunningActivity;

        /** The type of the source that triggers the launch event. */
        @SourceInfo.SourceType int mSourceType;
@@ -389,6 +391,7 @@ class ActivityMetricsLogger {
                return;
            }
            if (mLastLaunchedActivity != null) {
                mNextRunningActivity = null;
                if (mLastLaunchedActivity.mLaunchCookie != null) {
                    ProtoLog.v(WM_DEBUG_WINDOW_TRANSITIONS,
                            "Transferring launch cookie=%s from=%s(%d) to=%s(%d)",
@@ -446,6 +449,9 @@ class ActivityMetricsLogger {

        /** @return {@code true} if the activity matches a launched activity in this transition. */
        boolean contains(ActivityRecord r) {
            if (mNextRunningActivity != null) {
                return r == mNextRunningActivity;
            }
            return r == mLastLaunchedActivity;
        }

@@ -470,7 +476,8 @@ class ActivityMetricsLogger {
        @Override
        public String toString() {
            return "TransitionInfo{" + Integer.toHexString(System.identityHashCode(this))
                    + " a=" + mLastLaunchedActivity + " d=" + mIsDrawn + "}";
                    + " a=" + mLastLaunchedActivity + " r=" + mNextRunningActivity
                    + " d=" + mIsDrawn + "}";
        }
    }

@@ -986,12 +993,23 @@ class ActivityMetricsLogger {
            Slog.i(TAG, "notifyVisibilityChanged " + r + " visible=" + r.isVisibleRequested()
                    + " state=" + r.getState() + " finishing=" + r.finishing);
        }
        if (r.isState(ActivityRecord.State.RESUMED) && r.mDisplayContent.isSleeping()) {
            // The activity may be launching while keyguard is locked. The keyguard may be dismissed
            // after the activity finished relayout, so skip the visibility check to avoid aborting
            // the tracking of launch event.
        if (r.isState(ActivityRecord.State.RESUMED)) {
            if (r.mDisplayContent.isSleeping()) {
                // The activity may be launching while keyguard is locked. The keyguard may be
                // dismissed after the activity finished relayout, so skip the visibility check
                // to avoid aborting the tracking of launch event.
                return;
            }
            if (r.finishing) {
                // In case it is a trampoline activity that moves the existing task to front, then
                // the next activity will report drawn.
                final ActivityRecord next = r.getTask().getActivityBelow(r);
                if (next != null && !next.finishing && !next.isVisible()) {
                    info.mNextRunningActivity = next;
                    return;
                }
            }
        }
        if (!r.isVisibleRequested() || r.finishing) {
            // Check if the tracker can be cancelled because the last launched activity may be
            // no longer visible.
@@ -1116,6 +1134,10 @@ class ActivityMetricsLogger {
            mSupervisor.stopWaitingForActivityVisible(info.mLastLaunchedActivity);
            launchObserverNotifyActivityLaunchCancelled(info);
        } else {
            if (info.mNextRunningActivity != null) {
                // Report the running activity because the launched activity was finished.
                info.mLastLaunchedActivity = info.mNextRunningActivity;
            }
            if (info.isInterestingToLoggerAndObserver()) {
                launchObserverNotifyActivityLaunchFinished(info, timestampNs);
            }
+0 −8
Original line number Diff line number Diff line
@@ -2398,14 +2398,6 @@ class ActivityStarter {

        setTargetRootTaskIfNeeded(targetTaskTop);

        // When there is a reused activity and the current result is a trampoline activity,
        // set the reused activity as the result.
        if (mLastStartActivityRecord != null
                && (mLastStartActivityRecord.finishing
                    || mLastStartActivityRecord.isNoDisplay())) {
            mLastStartActivityRecord = targetTaskTop;
        }

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do anything
            // if that is the case, so this is it!  And for paranoia, make sure we have
+30 −0
Original line number Diff line number Diff line
@@ -649,6 +649,36 @@ public class ActivityStarterTests extends WindowTestsBase {
        assertEquals(1, activity.compareTo(translucentActivity));
    }

    @Test
    public void testReportStartedNoDisplayActivity() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
                .setVisible(false).build();
        final Task task = activity.getTask();
        task.inRecents = true;
        final ActivityRecord[] outActivity = new ActivityRecord[1];
        final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
                .setInTask(task).setReason("testReportStartedNoDisplayActivity")
                .setOutActivity(outActivity);
        starter.mRequest.activityInfo.applicationInfo.packageName = mContext.getPackageName();
        starter.mRequest.activityInfo.theme = android.R.style.Theme_NoDisplay;
        starter.execute();
        final ActivityRecord startedActivity = outActivity[0];

        assertNotNull(startedActivity);
        assertEquals(task, startedActivity.getTask());
        assertNotEquals("Report started no-display activity instead of the existing one",
                activity, startedActivity);
        assertTrue(startedActivity.isNoDisplay());

        startedActivity.setProcess(activity.app);
        startedActivity.setState(ActivityRecord.State.RESUMED, "test");
        startedActivity.makeFinishingLocked();
        // MetricsLogger will redirect to monitor next activity.
        startedActivity.setVisibility(false);

        assertNotNull(mSupervisor.getActivityMetricsLogger().notifyWindowsDrawn(activity));
    }

    /**
     * Tests activity is cleaned up properly in a task mode violation.
     */