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

Commit db407ef1 authored by Tiger Huang's avatar Tiger Huang
Browse files

Introduce updateVisibility and updateLayout

This is a step to let the client layout its window locally. The ultimate
goal is to reduce the jank while laying out the window.

With the new AIDL methods, we can divide IWindowSession.relayout into:

- IWindowSession#updateVisibility (synchronized binder call)
  - To get or update the surface
  - To fetch the latest factors about window-layout
  - Only called when the view visibility is changed

- WindowLayout#computeFrames (local function call)
  - To compute the window frames

- IWindowSession#updateLayout (one way binder call)
  - To report the result of layout to the server

In this way, if the view visibility is not changed, the UI thread of
the client won't be blocked by the binder call during relayout.

The local layout project won't be done in a single CL. In order not to
break the existing logic, this CL introduces a flag: LOCAL_LAYOUT. The
flag will be enabled when the logic of local layout is ready.

Bug: 161810301
Bug: 175861051
Test: presubmit (no behavior change)
Change-Id: Ic4b2fc78a318f3a68e1ef8a35d8f3ab705856702
parent fb8919fa
Loading
Loading
Loading
Loading
+29 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
import static android.view.ViewRootImpl.LOCAL_LAYOUT;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;

import android.animation.Animator;
@@ -39,6 +40,7 @@ import android.app.Service;
import android.app.WallpaperColors;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -257,6 +259,8 @@ public abstract class WallpaperService extends Service {
        private final Point mLastSurfaceSize = new Point();
        private final Matrix mTmpMatrix = new Matrix();
        private final float[] mTmpValues = new float[9];
        private final WindowLayout mWindowLayout = new WindowLayout();
        private final Rect mTempRect = new Rect();

        final WindowManager.LayoutParams mLayout
                = new WindowManager.LayoutParams();
@@ -1091,7 +1095,8 @@ public abstract class WallpaperService extends Service {
                            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

                    final Configuration config = mMergedConfiguration.getMergedConfiguration();
                    final Rect maxBounds = config.windowConfiguration.getMaxBounds();
                    final WindowConfiguration winConfig = config.windowConfiguration;
                    final Rect maxBounds = winConfig.getMaxBounds();
                    if (myWidth == ViewGroup.LayoutParams.MATCH_PARENT
                            && myHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
                        mLayout.width = myWidth;
@@ -1149,10 +1154,28 @@ public abstract class WallpaperService extends Service {
                        mLayout.surfaceInsets.set(0, 0, 0, 0);
                    }

                    final int relayoutResult = mSession.relayout(
                            mWindow, mLayout, mWidth, mHeight,
                            View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl,
                            mInsetsState, mTempControls, mSyncSeqIdBundle);
                    int relayoutResult = 0;
                    if (LOCAL_LAYOUT) {
                        if (!mSurfaceControl.isValid()) {
                            relayoutResult = mSession.updateVisibility(mWindow, mLayout,
                                    View.VISIBLE, mMergedConfiguration, mSurfaceControl,
                                    mInsetsState, mTempControls);
                        }

                        final Rect displayCutoutSafe = mTempRect;
                        mInsetsState.getDisplayCutoutSafe(displayCutoutSafe);
                        mWindowLayout.computeFrames(mLayout, mInsetsState, displayCutoutSafe,
                                winConfig.getBounds(), winConfig.getWindowingMode(), mWidth,
                                mHeight, mRequestedVisibilities, null /* attachedWindowFrame */,
                                1f /* compatScale */, mWinFrames);

                        mSession.updateLayout(mWindow, mLayout, 0 /* flags */, mWinFrames, mWidth,
                                mHeight);
                    } else {
                        relayoutResult = mSession.relayout(mWindow, mLayout, mWidth, mHeight,
                                View.VISIBLE, 0, mWinFrames, mMergedConfiguration,
                                mSurfaceControl, mInsetsState, mTempControls, mSyncSeqIdBundle);
                    }

                    final int transformHint = SurfaceControl.rotationToBufferTransform(
                            (mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -1202,7 +1225,7 @@ public abstract class WallpaperService extends Service {
                            null /* ignoringVisibilityState */, config.isScreenRound(),
                            false /* alwaysConsumeSystemBars */, mLayout.softInputMode,
                            mLayout.flags, SYSTEM_UI_FLAG_VISIBLE, mLayout.type,
                            config.windowConfiguration.getWindowingMode(), null /* typeSideMap */);
                            winConfig.getWindowingMode(), null /* typeSideMap */);

                    if (!fixedSize) {
                        final Rect padding = mIWallpaperEngine.mDisplayPadding;
+35 −0
Original line number Diff line number Diff line
@@ -107,6 +107,41 @@ interface IWindowSession {
            out InsetsState insetsState, out InsetsSourceControl[] activeControls,
            out Bundle bundle);

    /**
     * Changes the view visibility and the attributes of a window. This should only be called when
     * the visibility of the root view is changed. This returns a valid surface if the root view is
     * visible. This also returns the latest information for the caller to compute its window frame.
     *
     * @param window The window being updated.
     * @param attrs If non-null, new attributes to apply to the window.
     * @param viewVisibility Window root view's visibility.
     * @param outMergedConfiguration New config container that holds global, override and merged
     * config for window, if it is now becoming visible and the merged configuration has changed
     * since it was last displayed.
     * @param outSurfaceControl Object in which is placed the new display surface.
     * @param outInsetsState The current insets state in the system.
     * @param outActiveControls The insets source controls for the caller to override the insets
     * state in the system.
     *
     * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
     */
    int updateVisibility(IWindow window, in WindowManager.LayoutParams attrs, int viewVisibility,
            out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
            out InsetsState outInsetsState, out InsetsSourceControl[] outActiveControls);

    /**
     * Reports the layout results and the attributes of a window to the server.
     *
     * @param window The window being reported.
     * @param attrs If non-null, new attributes to apply to the window.
     * @param flags Request flags: {@link WindowManagerGlobal#RELAYOUT_INSETS_PENDING}.
     * @param clientFrames the window frames computed by the client.
     * @param requestedWidth The width the window wants to be.
     * @param requestedHeight The height the window wants to be.
     */
    oneway void updateLayout(IWindow window, in WindowManager.LayoutParams attrs, int flags,
            in ClientWindowFrames clientFrames, int requestedWidth, int requestedHeight);

    /*
     * Notify the window manager that an application is relaunching and
     * windows should be prepared for replacement.
+67 −21
Original line number Diff line number Diff line
@@ -78,11 +78,13 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_E
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER;
@@ -278,6 +280,13 @@ public final class ViewRootImpl implements ViewParent,
     */
    public static final boolean CAPTION_ON_SHELL = false;

    /**
     * Whether the client should compute the window frame on its own.
     * @hide
     */
    public static final boolean LOCAL_LAYOUT =
            SystemProperties.getBoolean("persist.debug.local_layout", false);

    /**
     * Set this system property to true to force the view hierarchy to render
     * at 60 Hz. This can be used to measure the potential framerate.
@@ -8083,17 +8092,68 @@ public final class ViewRootImpl implements ViewParent,
        final int requestedWidth = (int) (mView.getMeasuredWidth() * appScale + 0.5f);
        final int requestedHeight = (int) (mView.getMeasuredHeight() * appScale + 0.5f);

        int relayoutResult = mWindowSession.relayout(mWindow, params,
        mWillMove = false;
        mWillResize = false;
        int relayoutResult = 0;
        WindowConfiguration winConfig = getConfiguration().windowConfiguration;
        if (LOCAL_LAYOUT) {
            if (mFirst || viewVisibility != mViewVisibility) {
                relayoutResult = mWindowSession.updateVisibility(mWindow, params, viewVisibility,
                        mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mTempControls);
                if (mTranslator != null) {
                    mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
                    mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
                }
                mInsetsController.onStateChanged(mTempInsets);
                mInsetsController.onControlsChanged(mTempControls);

                mPendingAlwaysConsumeSystemBars =
                        (relayoutResult & RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0;
            }
            final InsetsState state = mInsetsController.getState();
            final Rect displayCutoutSafe = mTempRect;
            state.getDisplayCutoutSafe(displayCutoutSafe);
            if (mWindowAttributes.type == TYPE_APPLICATION_STARTING) {
                // TODO(b/210378379): Remove the special logic.
                // Letting starting window use the window bounds from the pending config is for the
                // fixed rotation, because the config is not overridden before the starting window
                // is created.
                winConfig = mPendingMergedConfiguration.getMergedConfiguration()
                        .windowConfiguration;
            }
            mWindowLayout.computeFrames(mWindowAttributes, state, displayCutoutSafe,
                    winConfig.getBounds(), winConfig.getWindowingMode(), requestedWidth,
                    requestedHeight, mInsetsController.getRequestedVisibilities(),
                    getAttachedWindowFrame(), 1f /* compatScale */, mTmpFrames);

            mWindowSession.updateLayout(mWindow, params,
                    insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mTmpFrames,
                    requestedWidth, requestedHeight);

        } else {
            relayoutResult = mWindowSession.relayout(mWindow, params,
                    requestedWidth, requestedHeight, viewVisibility,
                    insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                    mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
                    mTempControls, mRelayoutBundle);
            mSyncSeqId = mRelayoutBundle.getInt("seqid");

            if (mTranslator != null) {
                mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame);
                mTranslator.translateRectInScreenToAppWindow(mTmpFrames.displayFrame);
                mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
                mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
            }
            mInsetsController.onStateChanged(mTempInsets);
            mInsetsController.onControlsChanged(mTempControls);

            mPendingAlwaysConsumeSystemBars =
                    (relayoutResult & RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0;
        }

        final int transformHint = SurfaceControl.rotationToBufferTransform(
                (mDisplayInstallOrientation + mDisplay.getRotation()) % 4);

        final WindowConfiguration winConfig = getConfiguration().windowConfiguration;
        WindowLayout.computeSurfaceSize(mWindowAttributes, winConfig.getMaxBounds(), requestedWidth,
                requestedHeight, mTmpFrames.frame, mPendingDragResizing, mSurfaceSize);

@@ -8142,24 +8202,10 @@ public final class ViewRootImpl implements ViewParent,
            destroySurface();
        }

        mPendingAlwaysConsumeSystemBars =
                (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0;

        if (restore) {
            params.restore();
        }

        if (mTranslator != null) {
            mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame);
            mTranslator.translateRectInScreenToAppWindow(mTmpFrames.displayFrame);
            mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
            mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
        }
        setFrame(mTmpFrames.frame);
        mWillMove = false;
        mWillResize = false;
        mInsetsController.onStateChanged(mTempInsets);
        mInsetsController.onControlsChanged(mTempControls);
        return relayoutResult;
    }

+15 −0
Original line number Diff line number Diff line
@@ -335,6 +335,21 @@ public class WindowlessWindowManager implements IWindowSession {
        return 0;
    }

    @Override
    public int updateVisibility(IWindow window, WindowManager.LayoutParams inAttrs,
            int viewVisibility, MergedConfiguration outMergedConfiguration,
            SurfaceControl outSurfaceControl, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        // TODO(b/161810301): Finish the implementation.
        return 0;
    }

    @Override
    public void updateLayout(IWindow window, WindowManager.LayoutParams inAttrs, int flags,
            ClientWindowFrames clientWindowFrames, int requestedWidth, int requestedHeight) {
        // TODO(b/161810301): Finish the implementation.
    }

    @Override
    public void prepareToReplaceWindows(android.os.IBinder appToken, boolean childrenOnly) {
    }
+25 −0
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    private float mLastReportedAnimatorScale;
    private String mPackageName;
    private String mRelayoutTag;
    private String mUpdateViewVisibilityTag;
    private String mUpdateWindowLayoutTag;
    private final InsetsVisibilities mDummyRequestedVisibilities = new InsetsVisibilities();
    private final InsetsSourceControl[] mDummyControls =  new InsetsSourceControl[0];
    final boolean mSetsUnrestrictedKeepClearAreas;
@@ -222,6 +224,27 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        mService.removeWindow(this, window);
    }

    @Override
    public int updateVisibility(IWindow client, WindowManager.LayoutParams attrs,
            int viewVisibility, MergedConfiguration outMergedConfiguration,
            SurfaceControl outSurfaceControl, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mUpdateViewVisibilityTag);
        int res = mService.updateViewVisibility(this, client, attrs, viewVisibility,
                outMergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls);
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        return res;
    }

    @Override
    public void updateLayout(IWindow window, WindowManager.LayoutParams attrs, int flags,
            ClientWindowFrames clientFrames, int requestedWidth, int requestedHeight) {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mUpdateWindowLayoutTag);
        mService.updateWindowLayout(this, window, attrs, flags, clientFrames, requestedWidth,
                requestedHeight);
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }

    @Override
    public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
        mService.setWillReplaceWindows(appToken, childrenOnly);
@@ -689,6 +712,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
            if (wpc != null) {
                mPackageName = wpc.mInfo.packageName;
                mRelayoutTag = "relayoutWindow: " + mPackageName;
                mUpdateViewVisibilityTag = "updateVisibility: " + mPackageName;
                mUpdateWindowLayoutTag = "updateLayout: " + mPackageName;
            } else {
                Slog.e(TAG_WM, "Unknown process pid=" + mPid);
            }
Loading