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

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

Merge "Consolidate waiting list of visible and launched activity"

parents 5d1694b3 0f8a5212
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -174,6 +174,10 @@ class ActivityMetricsLogger {
        boolean allDrawn() {
            return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.allDrawn();
        }

        boolean contains(ActivityRecord r) {
            return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.contains(r);
        }
    }

    /** The information created when an activity is confirmed to be launched. */
@@ -793,6 +797,7 @@ class ActivityMetricsLogger {

        stopLaunchTrace(info);
        if (abort) {
            mSupervisor.stopWaitingForActivityVisible(info.mLastLaunchedActivity);
            launchObserverNotifyActivityLaunchCancelled(info);
        } else {
            if (info.isInterestingToLoggerAndObserver()) {
+2 −3
Original line number Diff line number Diff line
@@ -5435,7 +5435,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        final TransitionInfoSnapshot info = mTaskSupervisor
            .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
        if (info != null) {
            mTaskSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
            mTaskSupervisor.reportActivityLaunched(false /* timeout */, this,
                    info.windowsFullyDrawnDelayMs, info.getLaunchState());
        }
    }
@@ -5476,9 +5476,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // so there is no valid info. But if it is the current top activity (e.g. sleeping), the
        // invalid state is still reported to make sure the waiting result is notified.
        if (validInfo || this == getDisplayArea().topRunningActivity()) {
            mTaskSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
            mTaskSupervisor.reportActivityLaunched(false /* timeout */, this,
                    windowsDrawnDelayMs, launchState);
            mTaskSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs, launchState);
        }
        finishLaunchTickingLocked();
        if (task != null) {
+21 −44
Original line number Diff line number Diff line
@@ -710,8 +710,12 @@ class ActivityStarter {
                // WaitResult.
                mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
                        mLastStartActivityRecord, originalOptions);
                return getExternalResult(mRequest.waitResult == null ? res
                        : waitForResult(res, mLastStartActivityRecord));
                if (mRequest.waitResult != null) {
                    mRequest.waitResult.result = res;
                    res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
                            launchingState);
                }
                return getExternalResult(res);
            }
        } finally {
            onExecutionComplete();
@@ -796,48 +800,21 @@ class ActivityStarter {
    /**
     * Wait for activity launch completes.
     */
    private int waitForResult(int res, ActivityRecord r) {
        mRequest.waitResult.result = res;
        switch(res) {
            case START_SUCCESS: {
                mSupervisor.mWaitingActivityLaunched.add(mRequest.waitResult);
                do {
                    try {
                        mService.mGlobalLock.wait();
                    } catch (InterruptedException e) {
                    }
                } while (mRequest.waitResult.result != START_TASK_TO_FRONT
                        && !mRequest.waitResult.timeout && mRequest.waitResult.who == null);
                if (mRequest.waitResult.result == START_TASK_TO_FRONT) {
                    res = START_TASK_TO_FRONT;
                }
                break;
            }
            case START_DELIVERED_TO_TOP: {
                mRequest.waitResult.timeout = false;
                mRequest.waitResult.who = r.mActivityComponent;
                mRequest.waitResult.totalTime = 0;
                break;
            }
            case START_TASK_TO_FRONT: {
                // ActivityRecord may represent a different activity, but it should not be
                // in the resumed state.
                if (r.nowVisible && r.isState(RESUMED)) {
                    mRequest.waitResult.timeout = false;
                    mRequest.waitResult.who = r.mActivityComponent;
                    mRequest.waitResult.totalTime = 0;
                } else {
                    mSupervisor.waitActivityVisible(r.mActivityComponent, mRequest.waitResult);
                    // Note: the timeout variable is not currently not ever set.
                    do {
                        try {
                            mService.mGlobalLock.wait();
                        } catch (InterruptedException e) {
                        }
                    } while (!mRequest.waitResult.timeout && mRequest.waitResult.who == null);
                }
                break;
    private int waitResultIfNeeded(WaitResult waitResult, ActivityRecord r,
            LaunchingState launchingState) {
        final int res = waitResult.result;
        if (res == START_DELIVERED_TO_TOP
                || (res == START_TASK_TO_FRONT && r.nowVisible && r.isState(RESUMED))) {
            // The activity should already be visible, so nothing to wait.
            waitResult.timeout = false;
            waitResult.who = r.mActivityComponent;
            waitResult.totalTime = 0;
            return res;
        }
        mSupervisor.waitActivityVisibleOrLaunched(waitResult, r, launchingState);
        if (res == START_SUCCESS && waitResult.result == START_TASK_TO_FRONT) {
            // A trampoline activity is launched and it brings another existing activity to front.
            return START_TASK_TO_FRONT;
        }
        return res;
    }
+63 −75
Original line number Diff line number Diff line
@@ -266,11 +266,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
     */
    private final SparseIntArray mCurTaskIdForUser = new SparseIntArray(20);

    /** List of processes waiting to find out when a specific activity becomes visible. */
    private final ArrayList<WaitInfo> mWaitingForActivityVisible = new ArrayList<>();

    /** List of processes waiting to find out about the next launched activity. */
    final ArrayList<WaitResult> mWaitingActivityLaunched = new ArrayList<>();
    /** List of requests waiting for the target activity to be launched or visible. */
    private final ArrayList<WaitInfo> mWaitingActivityLaunched = new ArrayList<>();

    /** List of activities that are ready to be stopped, but waiting for the next activity to
     * settle down before doing so. */
@@ -552,9 +549,21 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
        return candidateTaskId;
    }

    void waitActivityVisible(ComponentName name, WaitResult result) {
        final WaitInfo waitInfo = new WaitInfo(name, result);
        mWaitingForActivityVisible.add(waitInfo);
    void waitActivityVisibleOrLaunched(WaitResult w, ActivityRecord r,
            LaunchingState launchingState) {
        if (w.result != ActivityManager.START_TASK_TO_FRONT
                && w.result != ActivityManager.START_SUCCESS) {
            // Not a result code that can make activity visible or launched.
            return;
        }
        final WaitInfo waitInfo = new WaitInfo(w, r.mActivityComponent, launchingState);
        mWaitingActivityLaunched.add(waitInfo);
        do {
            try {
                mService.mGlobalLock.wait();
            } catch (InterruptedException ignored) {
            }
        } while (mWaitingActivityLaunched.contains(waitInfo));
    }

    void cleanupActivity(ActivityRecord r) {
@@ -568,23 +577,25 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {

    /** There is no valid launch time, just stop waiting. */
    void stopWaitingForActivityVisible(ActivityRecord r) {
        stopWaitingForActivityVisible(r, WaitResult.INVALID_DELAY, WaitResult.LAUNCH_STATE_UNKNOWN);
        reportActivityLaunched(false /* timeout */, r, WaitResult.INVALID_DELAY,
                WaitResult.LAUNCH_STATE_UNKNOWN);
    }

    void stopWaitingForActivityVisible(ActivityRecord r, long totalTime,
    void reportActivityLaunched(boolean timeout, ActivityRecord r, long totalTime,
            @WaitResult.LaunchState int launchState) {
        boolean changed = false;
        for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
            final WaitInfo w = mWaitingForActivityVisible.get(i);
            if (w.matches(r.mActivityComponent)) {
                final WaitResult result = w.getResult();
                changed = true;
                result.timeout = false;
                result.who = w.getComponent();
                result.totalTime = totalTime;
                result.launchState = launchState;
                mWaitingForActivityVisible.remove(w);
        for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
            final WaitInfo info = mWaitingActivityLaunched.get(i);
            if (!info.matches(r)) {
                continue;
            }
            final WaitResult w = info.mResult;
            w.timeout = timeout;
            w.who = r.mActivityComponent;
            w.totalTime = totalTime;
            w.launchState = launchState;
            mWaitingActivityLaunched.remove(i);
            changed = true;
        }
        if (changed) {
            mService.mGlobalLock.notifyAll();
@@ -603,38 +614,18 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
        boolean changed = false;

        for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
            WaitResult w = mWaitingActivityLaunched.remove(i);
            if (w.who == null) {
                changed = true;
            final WaitInfo info = mWaitingActivityLaunched.get(i);
            if (!info.matches(r)) {
                continue;
            }
            final WaitResult w = info.mResult;
            w.result = result;

            if (result == START_DELIVERED_TO_TOP) {
                // Unlike START_TASK_TO_FRONT, When an intent is delivered to top, there
                // will be no followup launch signals. Assign the result and launched component.
                if (result == START_DELIVERED_TO_TOP) {
                w.who = r.mActivityComponent;
                }
            }
        }

        if (changed) {
            mService.mGlobalLock.notifyAll();
        }
    }

    void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, long totalTime,
            @WaitResult.LaunchState int launchState) {
        boolean changed = false;
        for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
            WaitResult w = mWaitingActivityLaunched.remove(i);
            if (w.who == null) {
                mWaitingActivityLaunched.remove(i);
                changed = true;
                w.timeout = timeout;
                if (r != null) {
                    w.who = new ComponentName(r.info.packageName, r.info.name);
                }
                w.totalTime = totalTime;
                w.launchState = launchState;
                // Do not modify w.result.
            }
        }
        if (changed) {
@@ -1295,8 +1286,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
            r.finishLaunchTickingLocked();
            if (fromTimeout) {
                reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY,
                        -1 /* launchState */);
                reportActivityLaunched(fromTimeout, r, INVALID_DELAY, -1 /* launchState */);
            }

            // This is a hack to semi-deal with a race condition
@@ -1940,14 +1930,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
        pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
        pw.println(prefix + "mUserRootTaskInFront=" + mRootWindowContainer.mUserRootTaskInFront);
        pw.println(prefix + "mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
        if (!mWaitingForActivityVisible.isEmpty()) {
            pw.println(prefix + "mWaitingForActivityVisible=");
            for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) {
                pw.print(prefix + prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix);
            }
        }
        pw.print(prefix); pw.print("isHomeRecentsComponent=");
        pw.println(mRecentTasks.isRecentsComponentHomeActivity(mRootWindowContainer.mCurrentUser));
        if (!mWaitingActivityLaunched.isEmpty()) {
            pw.println(prefix + "mWaitingActivityLaunched=");
            for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
                mWaitingActivityLaunched.get(i).dump(pw, prefix + "  ");
            }
        }
        pw.println();
    }

@@ -2604,32 +2594,30 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    /**
     * Internal container to store a match qualifier alongside a WaitResult.
     */
    static class WaitInfo {
        private final ComponentName mTargetComponent;
        private final WaitResult mResult;

        WaitInfo(ComponentName targetComponent, WaitResult result) {
            this.mTargetComponent = targetComponent;
            this.mResult = result;
        }

        public boolean matches(ComponentName targetComponent) {
            return mTargetComponent == null || mTargetComponent.equals(targetComponent);
        }
    private static class WaitInfo {
        final WaitResult mResult;
        final ComponentName mTargetComponent;
        /**
         * The target component may not be the final drawn activity. The launching state is managed
         * by {@link ActivityMetricsLogger} that can track consecutive launching sequence.
         */
        final LaunchingState mLaunchingState;

        public WaitResult getResult() {
            return mResult;
        WaitInfo(WaitResult result, ComponentName component, LaunchingState launchingState) {
            mResult = result;
            mTargetComponent = component;
            mLaunchingState = launchingState;
        }

        public ComponentName getComponent() {
            return mTargetComponent;
        boolean matches(ActivityRecord r) {
            return mTargetComponent.equals(r.mActivityComponent) || mLaunchingState.contains(r);
        }

        public void dump(PrintWriter pw, String prefix) {
        void dump(PrintWriter pw, String prefix) {
            pw.println(prefix + "WaitInfo:");
            pw.println(prefix + "  mTargetComponent=" + mTargetComponent);
            pw.println(prefix + "  mResult=");
            mResult.dump(pw, prefix);
            mResult.dump(pw, prefix + "    ");
        }
    }
}
+0 −9
Original line number Diff line number Diff line
@@ -5438,14 +5438,6 @@ class Task extends WindowContainer<WindowContainer> {
        r.completeResumeLocked();
    }

    private void clearLaunchTime(ActivityRecord r) {
        // Make sure that there is no activity waiting for this to launch.
        if (!mTaskSupervisor.mWaitingActivityLaunched.isEmpty()) {
            mTaskSupervisor.removeIdleTimeoutForActivity(r);
            mTaskSupervisor.scheduleIdleTimeout(r);
        }
    }

    void awakeFromSleepingLocked() {
        if (!isLeafTask()) {
            forAllLeafTasks((task) -> task.awakeFromSleepingLocked(),
@@ -5588,7 +5580,6 @@ class Task extends WindowContainer<WindowContainer> {
        mLastNoHistoryActivity = prev.isNoHistory() ? prev : null;
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTask().touchActiveTime();
        clearLaunchTime(prev);

        mAtmService.updateCpuStats();

Loading