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

Commit 5495bffd authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Reduce invocation of surface placement of switching activities

This skips to perform surface placement immediately when starting
activity and reporting activity paused. Because the window of
next resuming activity should also do it by relayout.

These skip cases are relatively safe because before the transition
is ready, the visual appearance should keep the same even if without
running surface placement.

One of obvious benefit is to reduce lock contention from the systemui
when handling starting window (add window/relayout/finish drawn).

Bug: 188398125
Bug: 183665220
Bug: 187104264
Test: CtsWindowManagerDeviceTestCases

Change-Id: Ice5a47a64178cbd00ce27625a60eded2b699e9cf
parent cc0987b1
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.SKIP_LAYOUT_REASON_ALLOWED;
import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutMillisLocked;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
@@ -5361,6 +5362,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                mAtmService.deferWindowLayout();
                try {
                    task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
                    // If there is no possible transition to execute, then allow to skip layout
                    // because it may be done by next resumed activity.
                    if (!pausingActivity.mDisplayContent.areOpeningAppsReady()) {
                        mAtmService.addWindowLayoutReasons(SKIP_LAYOUT_REASON_ALLOWED);
                    }
                } finally {
                    mAtmService.continueWindowLayout();
                }
+2 −0
Original line number Diff line number Diff line
@@ -1549,6 +1549,8 @@ class ActivityStarter {
        mService.getTransitionController().collect(r);
        try {
            mService.deferWindowLayout();
            // Allow to skip layout because it may be done by the window of the starting activity.
            mService.addWindowLayoutReasons(ActivityTaskManagerService.SKIP_LAYOUT_REASON_ALLOWED);
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
+38 −8
Original line number Diff line number Diff line
@@ -657,14 +657,27 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    @IntDef({
            LAYOUT_REASON_CONFIG_CHANGED,
            LAYOUT_REASON_VISIBILITY_CHANGED,
            SKIP_LAYOUT_REASON_ALLOWED,
            SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT,
    })
    @interface LayoutReason {
    }

    static final int LAYOUT_REASON_MASK = 0x0000ffff;
    static final int LAYOUT_REASON_CONFIG_CHANGED = 0x1;
    static final int LAYOUT_REASON_VISIBILITY_CHANGED = 0x2;
    static final int SKIP_LAYOUT_REASON_MASK = 0xfffe0000;

    /** The reasons to perform surface placement. */
    /**
     * Allow to call {@link WindowSurfacePlacer#endDeferAndSkipLayout} if there is a reason
     * included in {@link #SKIP_LAYOUT_REASON_MASK} was added.
     */
    static final int SKIP_LAYOUT_REASON_ALLOWED = 1 << 16;

    /** Used when the client is scheduled to call relayout. */
    static final int SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT = 1 << 17;

    /** The reasons to perform or skip surface placement. */
    @LayoutReason
    private int mLayoutReasons;

@@ -4187,18 +4200,35 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        mWindowManager.mWindowPlacerLocked.deferLayout();
    }

    /** @see WindowSurfacePlacer#continueLayout */
    /**
     * @see WindowSurfacePlacer#continueLayout
     * @see WindowSurfacePlacer#endDeferAndSkipLayout
     */
    void continueWindowLayout() {
        mWindowManager.mWindowPlacerLocked.continueLayout(mLayoutReasons != 0);
        if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons);
        if ((mLayoutReasons & SKIP_LAYOUT_REASON_ALLOWED) != 0) {
            final int skipReasons = mLayoutReasons & SKIP_LAYOUT_REASON_MASK;
            if (skipReasons != 0) {
                if (DEBUG_ALL) {
                    Slog.i(TAG, "continueWindowLayout skip-reasons="
                            + Integer.toHexString(skipReasons));
                }
                mWindowManager.mWindowPlacerLocked.endDeferAndSkipLayout();
                return;
            }
        }

        final int reasons = mLayoutReasons & LAYOUT_REASON_MASK;
        mWindowManager.mWindowPlacerLocked.continueLayout(reasons != 0);
        if (DEBUG_ALL && reasons != 0 && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            Slog.i(TAG, "continueWindowLayout reasons=" + Integer.toHexString(reasons));
        }
    }

    /**
     * If a reason is added between {@link #deferWindowLayout} and {@link #continueWindowLayout},
     * it will make sure {@link WindowSurfacePlacer#performSurfacePlacement} is called when the last
     * defer count is gone.
     * If a reason within {@link #LAYOUT_REASON_MASK} is added between {@link #deferWindowLayout}
     * and {@link #continueWindowLayout}, {@link WindowSurfacePlacer#performSurfacePlacement} will
     * be called when the last defer count is gone. Note that the {@link #SKIP_LAYOUT_REASON_MASK}
     * has higher priority to determine whether to perform layout.
     */
    void addWindowLayoutReasons(@LayoutReason int reasons) {
        mLayoutReasons |= reasons;
+3 −0
Original line number Diff line number Diff line
@@ -938,6 +938,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
        if (r.app != null) {
            r.app.updateServiceConnectionActivities();
        }
        // Expect a window of the starting activity will perform relayout.
        mService.addWindowLayoutReasons(
                ActivityTaskManagerService.SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT);

        return true;
    }
+16 −0
Original line number Diff line number Diff line
@@ -3995,6 +3995,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return mLayoutNeeded;
    }

    /** Returns {@code true} if all opening apps may be ready to execute transition. */
    boolean areOpeningAppsReady() {
        final int size = mOpeningApps.size();
        for (int i = size - 1; i >= 0; i--) {
            final ActivityRecord r = mOpeningApps.valueAt(i);
            if (!r.hasVisible) {
                return false;
            }
            final WindowState w = r.findMainWindow();
            if (w != null && !w.isDrawn()) {
                return false;
            }
        }
        return size > 0;
    }

    void dumpTokens(PrintWriter pw, boolean dumpAll) {
        if (mTokenMap.isEmpty()) {
            return;
Loading