Android14 WMS-窗口绘制之relayoutWindow流程(二)-Server端

本文接着如下文章往下讲

Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端-CSDN博客

然后就到了Server端WMS的核心实现方法relayoutWindow里29f881a37fcb498095f0b6ace978d5e4.jpg  

WindowManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
...
    public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
            int lastSyncSeqId, ClientWindowFrames outFrames,
            MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,
            InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,
            Bundle outSyncIdBundle) {

  由于此方法太长,所以分开讲述

1. 第一步

        if (outActiveControls != null) {
            outActiveControls.set(null);
        }
        int result = 0;
        boolean configChanged = false;
//获取发起者的Uid和Pid
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        synchronized (mGlobalLock) {
//通过IBinder client查询mWindowMap中对应的WindowState 
            final WindowState win = windowForClientLocked(session, client, false);
            if (win == null) {
                return 0;
            }
            if (win.mRelayoutSeq < seq) {
                win.mRelayoutSeq = seq;
            } else if (win.mRelayoutSeq > seq) {
                return 0;
            }

            if (win.cancelAndRedraw() && win.mPrepareSyncSeqId <= lastSyncSeqId) {
                // The client has reported the sync draw, but we haven't finished it yet.
                // Don't let the client perform a non-sync draw at this time.
                result |= RELAYOUT_RES_CANCEL_AND_REDRAW;
            }
//获取window对应的DisplayContent 
            final DisplayContent displayContent = win.getDisplayContent();
//获取window对应的DisplayPolicy 
            final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
//获取window对应的WindowStateAnimator 
            WindowStateAnimator winAnimator = win.mWinAnimator;
            if (viewVisibility != View.GONE) {
//如果不是Gone,则更新全局变量之窗口申请的宽高 mRequestedWidth mRequestedHeight 
                win.setRequestedSize(requestedWidth, requestedHeight);
            }

2. 第二步

            int attrChanges = 0;
            int flagChanges = 0;
            int privateFlagChanges = 0;
//如果窗口的属性不为空,则说明有要更新的窗口属性
            if (attrs != null) {
//调整窗口参数,主要是针对某些窗口类型,清理一些窗口属性参数
                displayPolicy.adjustWindowParamsLw(win, attrs);
...
窗口type在窗口add之后不能被改变,否则就会异常,窗口type是区分窗口层级很重要的一个东西
                if (win.mAttrs.type != attrs.type) {
                    throw new IllegalArgumentException(
                            "Window type can not be changed after the window is added.");
                }
...
//异或^     两个位相同为0,相异为1
                flagChanges = win.mAttrs.flags ^ attrs.flags;
                privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;
                attrChanges = win.mAttrs.copyFrom(attrs);
                final boolean layoutChanged =
                        (attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0;
                if (layoutChanged || (attrChanges
                        & WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
窗口布局有变化,需要更新
                    win.mLayoutNeeded = true;
                }
                if (layoutChanged && win.providesDisplayDecorInsets()) {
                    configChanged = displayPolicy.updateDecorInsetsInfo();
                }
//看下有没有锁屏相关的flag变化
                if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
                        || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
                    win.mActivityRecord.checkKeyguardFlagsChanged();
                }

                if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
                    updateNonSystemOverlayWindowsVisibilityIfNeeded(
                            win, win.mWinAnimator.getShown());
                }
                if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {
                    winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
                            & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
                }
...
            }

3. 第三步

            int attrChanges = 0;
            int flagChanges = 0;
            int privateFlagChanges = 0;
//如果窗口的属性不为空,则说明有要更新的窗口属性
            if (attrs != null) {
//调整窗口参数,主要是针对某些窗口类型,清理一些窗口属性参数
                displayPolicy.adjustWindowParamsLw(win, attrs);
...
窗口type在窗口add之后不能被改变,否则就会异常,窗口type是区分窗口层级很重要的一个东西
                if (win.mAttrs.type != attrs.type) {
                    throw new IllegalArgumentException(
                            "Window type can not be changed after the window is added.");
                }
...
//异或^     两个位相同为0,相异为1
                flagChanges = win.mAttrs.flags ^ attrs.flags;
                privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;
                attrChanges = win.mAttrs.copyFrom(attrs);
                final boolean layoutChanged =
                        (attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0;
                if (layoutChanged || (attrChanges
                        & WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
窗口布局有变化,需要更新
                    win.mLayoutNeeded = true;
                }
                if (layoutChanged && win.providesDisplayDecorInsets()) {
                    configChanged = displayPolicy.updateDecorInsetsInfo();
                }
//看下有没有锁屏相关的flag变化
                if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
                        || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
                    win.mActivityRecord.checkKeyguardFlagsChanged();
                }

                if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
                    updateNonSystemOverlayWindowsVisibilityIfNeeded(
                            win, win.mWinAnimator.getShown());
                }
                if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {
                    winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
                            & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
                }
...
            }

4. 第四步

//06-01 10:12:18.006  1890  2256 V WindowManager: Relayout Window{8d0d088 u0 
//com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: 
//viewVisibility=0 req=7104x3840 {(0,0)(fillxfill) sim={adjust=resize forwardNavigation} 
//ty=BASE_APPLICATION wanim=0x10302f2
//06-01 10:12:18.006  1890  2256 V WindowManager:   fl=LAYOUT_IN_SCREEN //LAYOUT_INSET_DECOR 
//SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
//06-01 10:12:18.006  1890  2256 V WindowManager:   pfl=NO_MOVE_ANIMATION 
//FORCE_DRAW_STATUS_BAR_BACKGROUND HIDE_NON_SYSTEM_OVERLAY_WINDOWS USE_BLAST 
//FIT_INSETS_CONTROLLED
//06-01 10:12:18.006  1890  2256 V WindowManager:   vsysui=LIGHT_STATUS_BAR 
//LIGHT_NAVIGATION_BAR
//06-01 10:12:18.006  1890  2256 V WindowManager:   apr=LIGHT_STATUS_BARS 
//LIGHT_NAVIGATION_BARS
//06-01 10:12:18.006  1890  2256 V WindowManager:   bhv=DEFAULT
//06-01 10:12:18.006  1890  2256 V WindowManager:   fitSides=}

           if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
            if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
                winAnimator.mAlpha = attrs.alpha;
            }
//设置窗口大小
            win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);

            if (win.mAttrs.surfaceInsets.left != 0
                    || win.mAttrs.surfaceInsets.top != 0
                    || win.mAttrs.surfaceInsets.right != 0
                    || win.mAttrs.surfaceInsets.bottom != 0) {
                winAnimator.setOpaqueLocked(false);
            }

            final int oldVisibility = win.mViewVisibility;

            // If the window is becoming visible, visibleOrAdding may change which may in turn
            // change the IME target.
//窗口由不可见/Gone变为可见
            final boolean becameVisible =
                    (oldVisibility == View.INVISIBLE || oldVisibility == View.GONE)
                            && viewVisibility == View.VISIBLE;
            boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0
                    || becameVisible;
//窗口焦点更新--当之前的可见性和现在不一致,并且窗口没有携带FLAG_NOT_FOCUSABLE,并且mRelayoutCalled为false
            boolean focusMayChange = win.mViewVisibility != viewVisibility
                    || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
                    || (!win.mRelayoutCalled);

            boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
                    && win.hasWallpaper();
            wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
            if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
                winAnimator.mSurfaceController.setSecure(win.isSecureLocked());
            }

            final boolean wasVisible = win.isVisible();

            win.mRelayoutCalled = true;
            win.mInRelayout = true;
//设置窗口可见性为申请的可见性,可见则viewVisibility=0
            win.setViewVisibility(viewVisibility);
            ProtoLog.i(WM_DEBUG_SCREEN_ON,
                    "Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,
                            viewVisibility, new RuntimeException().fillInStackTrace());
//06-01 10:12:18.008  1890  2256 W WindowManager: setLayoutNeeded: 
//callers=com.android.server.wm.WindowState.setDisplayLayoutNeeded:2671 
//com.android.server.wm.WindowManagerService.relayoutWindow:2419 
//com.android.server.wm.Session.relayout:249 
            win.setDisplayLayoutNeeded();
            win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
 

viewVisibility代表当前View的可见性

mViewVisibilityVlaue含义
VISIBLE0x00000000

这个视图可见

与#setVisibility和#attr_android:visibility" android:visibility}一起使用。

INVISIBLE0x00000004

这个视图不可见

与#setVisibility和#attr_android:visibility" android:visibility}一起使用。

GONE0x00000008

这个视图是不可见的,它不占用任何空间进行布局

与#setVisibility和#attr_android:visibility" android:visibility}一起使用。

5. 第五步 创建Surface图层流程

            // We should only relayout if the view is visible, it is a starting window, or the
            // associated appToken is not hidden.
//只有当视图可见、并且它是STARTING窗口或关联的 appToken 未隐藏时,我们才应该重新布局。
            final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
                    (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
                            || win.mActivityRecord.isClientVisible());
            // If we are not currently running the exit animation, we need to see about starting
            // one.
            // This must be called before the call to performSurfacePlacement.
//如果我们当前没有运行退出动画,满足下列条件,则需执行退出动画
            if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
                if (DEBUG_VISIBILITY) {
//06-01 10:12:14.228  1890  2256 I WindowManager: Relayout invis Window{8c33950 u0 
//NotificationShade}: mAnimatingExit=false
                    Slog.i(TAG_WM,
                            "Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit);
                }
                result |= RELAYOUT_RES_SURFACE_CHANGED;
                // When FLAG_SHOW_WALLPAPER flag is removed from a window, we usually set a flag
                // in DC#pendingLayoutChanges and update the wallpaper target later.
                // However it's possible that FLAG_SHOW_WALLPAPER flag is removed from a window
                // when the window is about to exit, so we update the wallpaper target
                // immediately here. Otherwise this window will be stuck in exiting and its
                // surface remains on the screen.
                // TODO(b/189856716): Allow destroying surface even if it belongs to the
                //  keyguard target.
                if (wallpaperMayMove) {
                    displayContent.mWallpaperController.adjustWallpaperWindows();
                }
//执行窗口退出动画
                tryStartExitingAnimation(win, winAnimator);
            }

            // Create surfaceControl before surface placement otherwise layout will be skipped
            // (because WS.isGoneForLayout() is true when there is no surface.
//outSurfaceControl是client端传入的,在ViewRootImpl全局变量中就实例化好了
//http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/view/ViewRootImpl.java#708
//private final SurfaceControl mSurfaceControl = new SurfaceControl();
//所以这个不会为空
            if (shouldRelayout && outSurfaceControl != null) {
                try {
//创建图层
                    result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
                } catch (Exception e) {
                    displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);

                    ProtoLog.w(WM_ERROR,
                            "Exception thrown when creating surface for client %s (%s). %s",
                            client, win.mAttrs.getTitle(), e);
                    Binder.restoreCallingIdentity(origId);
                    return 0;
                }
            }
 

5.1 WindowManagerService#createSurfaceControl

WindowManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
            WindowState win, WindowStateAnimator winAnimator) {
        if (!win.mHasSurface) {
            result |= RELAYOUT_RES_SURFACE_CHANGED;
        }

        WindowSurfaceController surfaceController;
        try {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
//创建window对应的surface图层
            surfaceController = winAnimator.createSurfaceLocked();
...
        if (surfaceController != null) {
            surfaceController.getSurfaceControl(outSurfaceControl);
            ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);

        } else {
...
    }

 5.2  WindowStateAnimator#createSurfaceLocked

WindowStateAnimator.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java

    WindowSurfaceController createSurfaceLocked() {
        final WindowState w = mWin;

        if (mSurfaceController != null) {
            return mSurfaceController;
        }
//设置是否有Surface标志位为false
        w.setHasSurface(false);

        ProtoLog.i(WM_DEBUG_ANIM, "createSurface %s: mDrawState=DRAW_PENDING", this);
//重置图层绘制状态
        resetDrawState();
//要开始绘制图层了,要先freeze(冻住)住屏幕,等待绘制完成再Unfreeze,这里有个超时机制,即
//冻住屏幕有个最大时间WINDOW_FREEZE_TIMEOUT_DURATION--2000ms
        mService.makeWindowFreezingScreenIfNeededLocked(w);

        int flags = SurfaceControl.HIDDEN;
        final WindowManager.LayoutParams attrs = w.mAttrs;
//如果window是加密窗口,则添加此flag
        if (w.isSecureLocked()) {
            flags |= SurfaceControl.SECURE;
        }

        if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {
            flags |= SurfaceControl.SKIP_SCREENSHOT;
        }
//06-01 10:12:18.009  1890  2256 V WindowManager: Creating surface in session 
//android.view.SurfaceSession@fcb7984 window WindowStateAnimator{31728a0 
//com.android.settings/com.android.settings.homepage.SettingsHomepageActivity} format=-1 
//flags=4
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG, "Creating surface in session "
                    + mSession.mSurfaceSession + " window " + this
                    + " format=" + attrs.format + " flags=" + flags);
        }

        // Set up surface control with initial size.
        try {

            // This can be removed once we move all Buffer Layers to use BLAST.
            final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
            final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
//创建图层----创建WindowSurfaceController,主要是管理图层的,可设置图层位置,大小,是否可见等 
            mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,
                    flags, this, attrs.type);
//将 Surface 设置为与颜色空间无关。
            mSurfaceController.setColorSpaceAgnostic(w.getPendingTransaction(),
                    (attrs.privateFlags & LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
//图层创建好了,更新是否有Surface的标志位为true
            w.setHasSurface(true);
...
//06-01 10:12:18.015  1890  2256 V WindowManager: Got surface: 
//Surface(name=com.android.settings/com.android.settings.homepage.SettingsHomepageActivit//y)@0xafd3c59, set left=0 top=0
        if (DEBUG) {
            Slog.v(TAG, "Got surface: " + mSurfaceController
                    + ", set left=" + w.getFrame().left + " top=" + w.getFrame().top);
        }
...
        mLastHidden = true;
//06-01 10:12:18.015  1890  2256 V WindowManager: Created surface 
//WindowStateAnimator{31728a0 
//com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
        if (DEBUG) Slog.v(TAG, "Created surface " + this);
        return mSurfaceController;
    }

  5.3 WindowSurfaceController之创建图层

    WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,
            int windowType) {
        mAnimator = animator;

        title = name;

        mService = animator.mService;
        final WindowState win = animator.mWin;
        mWindowType = windowType;
        mWindowSession = win.mSession;

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
//创建图层
        final SurfaceControl.Builder b = win.makeSurface()
                .setParent(win.getSurfaceControl())
                .setName(name)
                .setFormat(format)
                .setFlags(flags)
                .setMetadata(METADATA_WINDOW_TYPE, windowType)
                .setMetadata(METADATA_OWNER_UID, mWindowSession.mUid)
                .setMetadata(METADATA_OWNER_PID, mWindowSession.mPid)
                .setCallsite("WindowSurfaceController");

        final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags
                & WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);

        if (useBLAST) {
            b.setBLASTLayer();
        }

        mSurfaceControl = b.build();

        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
-------------------------------------------------------------------
//http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/view/SurfaceControl.java#857

    public static class Builder {
        /**
         * Begin building a SurfaceControl.
         */
        public Builder() {
        }

        /**
         * Construct a new {@link SurfaceControl} with the set parameters. The builder
         * remains valid.
         */
        @NonNull
        public SurfaceControl build() {
            if (mWidth < 0 || mHeight < 0) {
                throw new IllegalStateException(
                        "width and height must be positive or unset");
            }
            if ((mWidth > 0 || mHeight > 0) && (isEffectLayer() || isContainerLayer())) {
                throw new IllegalStateException(
                        "Only buffer layers can set a valid buffer size.");
            }

            if (mName == null) {
                Log.w(TAG, "Missing name for SurfaceControl", new Throwable());
            }

            if ((mFlags & FX_SURFACE_MASK) == FX_SURFACE_NORMAL) {
                setBLASTLayer();
            }

            return new SurfaceControl(
                    mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
                    mLocalOwnerView, mCallsite);
        }

---------------------------------------------------------
    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
            SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView,
            String callsite)
                    throws OutOfResourcesException, IllegalArgumentException {
        if (name == null) {
            throw new IllegalArgumentException("name must not be null");
        }

        mName = name;
        mWidth = w;
        mHeight = h;
        mLocalOwnerView = localOwnerView;
        Parcel metaParcel = Parcel.obtain();
        long nativeObject = 0;
        try {
            if (metadata != null && metadata.size() > 0) {
                metaParcel.writeInt(metadata.size());
                for (int i = 0; i < metadata.size(); ++i) {
                    metaParcel.writeInt(metadata.keyAt(i));
                    metaParcel.writeByteArray(
                            ByteBuffer.allocate(4).order(ByteOrder.nativeOrder())
                                    .putInt(metadata.valueAt(i)).array());
                }
                metaParcel.setDataPosition(0);
            }
            nativeObject = nativeCreate(session, name, w, h, format, flags,
                    parent != null ? parent.mNativeObject : 0, metaParcel);
        } finally {
            metaParcel.recycle();
        }
        if (nativeObject == 0) {
            throw new OutOfResourcesException(
                    "Couldn't allocate SurfaceControl native object");
        }
        assignNativeObject(nativeObject, callsite);
    }

6. 第六步 刷新界面和更新焦点


            // We may be deferring layout passes at the moment, but since the client is interested
            // in the new out values right now we need to force a layout.
            mWindowPlacerLocked.performSurfacePlacement(true /* force */);

6.1 WindowSurfacePlacer#performSurfacePlacement 刷新界面和更新焦点

performSurfacePlacement 看方法名,perform surface place,即负责所有窗口的Surface的摆放工作,如何显示位置,大小等等,是WMS中的核心方法

90e8fa75df9f4c1bb4ed707d707d3fe1.jpg

下面这些流程的流程图如上

    final void performSurfacePlacement(boolean force) {
        if (mDeferDepth > 0 && !force) {
            mDeferredRequests++;
            return;
        }
//最大执行6次循环
        int loopCount = 6;
        do {
            mTraversalScheduled = false;
            performSurfacePlacementLoop();
            mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
            loopCount--;
        } while (mTraversalScheduled && loopCount > 0);
        mService.mRoot.mWallpaperActionPending = false;
    }

    private void performSurfacePlacementLoop() {
//此方法下面已经有地方将mInLayout置为true,说明已经正在执行performSurfacePlacementLoop方法了
        if (mInLayout) {
...
            return;
        }

        // TODO(multi-display):
        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
//mWaitingForConfig作用是Used to gate application window layout until we have sent the complete configuration.
//当没有完成configuration change的时候,无需做relayout,直到configuration change完成
        if (defaultDisplay.mWaitingForConfig) {
            // Our configuration has changed (most likely rotation), but we
            // don't yet have the complete configuration to report to
            // applications.  Don't do any window layout until we have it.
            return;
        }
//屏幕没准备好,直接返回
        if (!mService.mDisplayReady) {
            // Not yet initialized, nothing to do.
            return;
        }
//对应第一行标志位,表示正在layout
        mInLayout = true;
//内存不足时,强制清理mForceRemoves集合,释放内存
        if (!mService.mForceRemoves.isEmpty()) {
            // Wait a little bit for things to settle down, and off we go.
            while (!mService.mForceRemoves.isEmpty()) {
                final WindowState ws = mService.mForceRemoves.remove(0);
                Slog.i(TAG, "Force removing: " + ws);
                ws.removeImmediately();
            }
            Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
            Object tmp = new Object();
            synchronized (tmp) {
                try {
                    tmp.wait(250);
                } catch (InterruptedException e) {
                }
            }
        }

        try {
//核心的一步
            mService.mRoot.performSurfacePlacement();
//标志位置为false,走完上面这步,layout就完成了
            mInLayout = false;

            if (mService.mRoot.isLayoutNeeded()) {
//需要layout,并且count<6
                if (++mLayoutRepeatCount < 6) {
                    requestTraversal();
                } else {
...
    }

6.2 RootWindowContainer#performSurfacePlacement

RootWindowContainer.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    void performSurfacePlacement() {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
        try {
            performSurfacePlacementNoTrace();
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

 6.3 RootWindowContainer#performSurfacePlacementNoTrace - part1

这个方法也很长,当窗口的某些东西改变的时候,就会走到这里,由于太长,我们分开去讲

    void performSurfacePlacementNoTrace() {
        if (DEBUG_WINDOW_TRACE) {
//06-01 10:12:18.016  1890  2256 V WindowManager: performSurfacePlacementInner: entry. 
//Called by com.android.server.wm.RootWindowContainer.performSurfacePlacement:765 
//com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:177 
//com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:126 
            Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
                    + Debug.getCallers(3));
        }

        int i;

        if (mWmService.mFocusMayChange) {
            mWmService.mFocusMayChange = false;
//更新焦点窗口
            mWmService.updateFocusedWindowLocked(
                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
        }

        mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
        mUserActivityTimeout = -1;
        mObscureApplicationContentOnSecondaryDisplays = false;
        mSustainedPerformanceModeCurrent = false;
        mWmService.mTransactionSequence++;

        // TODO(multi-display): recents animation & wallpaper need support multi-display.
        final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
//获取WindowSurfacePlacer,这个类专门用于摆放windows和他们的surfaces,
//全系统只有一个实例,在WMS实例化中进行的
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
//要开始进行过渡动画了
        if (SHOW_LIGHT_TRANSACTIONS) {
            Slog.i(TAG,
                    ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
        }
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
//设置surface参数,start a transaction,对一组 SurfaceControl 的原子更改。
//即通过SurfaceControl来通知native开始一个Transaction
        mWmService.openSurfaceTransaction();
        try {
//执行Transaction
//下面详细解释这里
            applySurfaceChangesTransaction();
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
//close surface Transaction
            mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            if (SHOW_LIGHT_TRANSACTIONS) {
                Slog.i(TAG,
                        "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
            }
        }
...
剩下的分另一半说

6.3.1 RootWindowContainer#applySurfaceChangesTransaction

RootWindowContainer.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    private void applySurfaceChangesTransaction() {
        // TODO(multi-display): Support these features on secondary screens.
        final DisplayContent defaultDc = mDefaultDisplay;
        final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
        final int defaultDw = defaultInfo.logicalWidth;
        final int defaultDh = defaultInfo.logicalHeight;
        final SurfaceControl.Transaction t = defaultDc.getSyncTransaction();
...
//mChildren为“List of children for this window container”,
//也就是这个WindowContainer的一系列子windowContainer的集合
        final int count = mChildren.size();
//循环遍历
        for (int j = 0; j < count; ++j) {
//获取到这个WindowContainer对应的DisplayContent 
            final DisplayContent dc = mChildren.get(j);
//对这个DisplayContent进行applySurfaceChangesTransaction
            dc.applySurfaceChangesTransaction();
        }

        // Give the display manager a chance to adjust properties like display rotation if it needs
        // to.
        mWmService.mDisplayManagerInternal.performTraversal(t);
        if (t != defaultDc.mSyncTransaction) {
            SurfaceControl.mergeToGlobalTransaction(t);
        }
    }

借用一张图来表示mChildren,mChildren里保存的都是WidowContainer,并且这些WidowContainer按Z值排序,Z值越大越靠前

WindowContainer.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java "List of children for this window container. List is in z-order as the children appear on screen with the top-most window container at the tail of the list."

  protected final WindowList<E> mChildren = new WindowList<E>();

05342f3048dc4ea3adefed42dde7e65c.png

 6.3.2 DisplayContent#applySurfaceChangesTransaction

DisplayContent.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

    void applySurfaceChangesTransaction() {
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;

        beginHoldScreenUpdate();

        mTmpUpdateAllDrawn.clear();
...

        // Perform a layout, if needed.
        performLayout(true /* initial */, false /* updateInputWindows */);
        pendingLayoutChanges = 0;

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
        try {
            mDisplayPolicy.beginPostLayoutPolicyLw();
//遍历windows   执行mApplyPostLayoutPolicy
            forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
            mDisplayPolicy.finishPostLayoutPolicyLw();
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        mInsetsStateController.onPostLayout();

        mTmpApplySurfaceChangesTransactionState.reset();

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
        try {
//遍历windows
//执行mApplySurfaceChangesTransaction
            forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        prepareSurfaces();
...
        finishHoldScreenUpdate();
    }

 6.3.3 DisplayContent#performLayout

DisplayContent.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

    void performLayout(boolean initial, boolean updateInputWindows) {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performLayout");
        try {
            performLayoutNoTrace(initial, updateInputWindows);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

    private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) {
        if (!isLayoutNeeded()) {
            return;
        }
//将mLayoutNeeded = false;
//会打印堆栈:06-01 10:12:18.016  1890  2256 W WindowManager: clearLayoutNeeded: 
//callers=com.android.server.wm.DisplayContent.performLayoutNoTrace:5051 
//com.android.server.wm.DisplayContent.performLayout:5041 
//com.android.server.wm.DisplayContent.applySurfaceChangesTransaction:4963 
        clearLayoutNeeded();

        if (DEBUG_LAYOUT) {
//06-01 10:12:18.016  1890  2256 V WindowManager: performLayout: dw=3840 dh=7104 
            Slog.v(TAG, "-------------------------------------");
            Slog.v(TAG, "performLayout: dw=" + mDisplayInfo.logicalWidth
                    + " dh=" + mDisplayInfo.logicalHeight);
        }

        int seq = mLayoutSeq + 1;
        if (seq < 0) seq = 0;
        mLayoutSeq = seq;

        mTmpInitial = initial;

        // First perform layout of any root windows (not attached to another window).
//首先给所有windows执行layout,mPerformLayout稍后解释
        forAllWindows(mPerformLayout, true /* traverseTopToBottom */);

        // Now perform layout of attached windows, which usually depend on the position of the
        // window they are attached to. XXX does not deal with windows that are attached to windows
        // that are themselves attached.
//给所有attached windows执行layout操作
        forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);

        // Window frames may have changed. Tell the input dispatcher about it.
//更新input window
        mInputMonitor.setUpdateInputWindowsNeededLw();
        if (updateInputWindows) {
            mInputMonitor.updateInputWindowsLw(false /*force*/);
        }
    }

DisplayContent#  mPerformLayout赋值如下:

DisplayContent.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

    private final Consumer<WindowState> mPerformLayout = w -> {
        if (w.mLayoutAttached) {
            return;
        }

        // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
        // wasting time and funky changes while a window is animating away.
        final boolean gone = w.isGoneForLayout();

        if (DEBUG_LAYOUT) {
            Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
                    + " config reported=" + w.isLastConfigReportedToClient());
            final ActivityRecord activity = w.mActivityRecord;
            if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
                    + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
                    + " visibleRequested=" + (activity != null && activity.isVisibleRequested())
                    + " parentHidden=" + w.isParentWindowHidden());
            else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
                    + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
                    + " visibleRequested=" + (activity != null && activity.isVisibleRequested())
                    + " parentHidden=" + w.isParentWindowHidden());
        }

        // If this view is GONE, then skip it -- keep the current frame, and let the caller know
        // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
        // since that means "perform layout as normal, just don't display").
        if (!gone || !w.mHaveFrame || w.mLayoutNeeded) {
            if (mTmpInitial) {
                w.resetContentChanged();
            }
            w.mSurfacePlacementNeeded = true;
            w.mLayoutNeeded = false;
            final boolean firstLayout = !w.isLaidOut();
// Called for each window attached to the window manager as layout is proceeding
//在布局进行时调用附加到窗口管理器的每个窗口
            getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);
            w.mLayoutSeq = mLayoutSeq;

            // If this is the first layout, we need to initialize the last frames and inset values,
            // as otherwise we'd immediately cause an unnecessary resize.
            if (firstLayout) {
                // The client may compute its actual requested size according to the first layout,
                // so we still request the window to resize if the current frame is empty.
                if (!w.getFrame().isEmpty()) {
                    w.updateLastFrames();
                }
                w.onResizeHandled();
            }

            if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.getFrame()
                    + " mParentFrame=" + w.getParentFrame()
                    + " mDisplayFrame=" + w.getDisplayFrame());
        }
    };

DisplayPolicy#layoutWindowLw

    public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
...
        mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
                win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,
                win.getRequestedVisibleTypes(), win.mGlobalScale, sTmpClientFrames);

        win.setFrames(sTmpClientFrames, win.mRequestedWidth, win.mRequestedHeight);
  }
    

DisplayContent#  ​​​​​​​​​​​​​​mApplyPostLayoutPolicy赋值如下:

    private final Consumer<WindowState> mApplyPostLayoutPolicy =
            w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), mImeLayeringTarget);

DisplayPolicy.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java

    /**
     * Called following layout of all window to apply policy to each window.
     *
     * @param win The window being positioned.
     * @param attrs The LayoutParams of the window.
     * @param attached For sub-windows, the window it is attached to. Otherwise null.
     */
    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached, WindowState imeTarget) {

 DisplayContent#  ​​​​​​​mApplySurfaceChangesTransaction赋值如下

    private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
        final boolean obscuredChanged = w.mObscured !=
                mTmpApplySurfaceChangesTransactionState.obscured;
        final RootWindowContainer root = mWmService.mRoot;

        // Update effect.
        w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;

        if (!mTmpApplySurfaceChangesTransactionState.obscured) {
            final boolean isDisplayed = w.isDisplayed();

            if (isDisplayed && w.isObscuringDisplay()) {
                // This window completely covers everything behind it, so we want to leave all
                // of them as undimmed (for performance reasons).
                mObscuringWindow = w;
                mTmpApplySurfaceChangesTransactionState.obscured = true;
            }

            final boolean displayHasContent = root.handleNotObscuredLocked(w,
                    mTmpApplySurfaceChangesTransactionState.obscured,
                    mTmpApplySurfaceChangesTransactionState.syswin);

            if (!mTmpApplySurfaceChangesTransactionState.displayHasContent
                    && !getDisplayPolicy().isWindowExcludedFromContent(w)) {
                mTmpApplySurfaceChangesTransactionState.displayHasContent |= displayHasContent;
            }

            if (w.mHasSurface && isDisplayed) {
                if ((w.mAttrs.flags & FLAG_KEEP_SCREEN_ON) != 0) {
                    mTmpHoldScreenWindow = w;
                } else if (w == mLastWakeLockHoldingWindow) {
                    ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
                            "handleNotObscuredLocked: %s was holding screen wakelock but no longer "
                                    + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
                            w, Debug.getCallers(10));
                }

                final int type = w.mAttrs.type;
                if (type == TYPE_SYSTEM_DIALOG
                        || type == TYPE_SYSTEM_ERROR
                        || (type == TYPE_NOTIFICATION_SHADE
                            &&  mWmService.mPolicy.isKeyguardShowing())) {
                    mTmpApplySurfaceChangesTransactionState.syswin = true;
                }
                if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
                        && w.mAttrs.preferredRefreshRate != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
                            = w.mAttrs.preferredRefreshRate;
                }

                mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing
                        |= w.mAttrs.preferMinimalPostProcessing;

                mTmpApplySurfaceChangesTransactionState.disableHdrConversion
                        |= !(w.mAttrs.isHdrConversionEnabled());

                final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
                        .getPreferredModeId(w);

                if (w.getWindowingMode() != WINDOWING_MODE_PINNED
                        && mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
                        && preferredModeId != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
                }

                final float preferredMinRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
                        .getPreferredMinRefreshRate(w);
                if (mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate == 0
                        && preferredMinRefreshRate != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate =
                            preferredMinRefreshRate;
                }

                final float preferredMaxRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
                        .getPreferredMaxRefreshRate(w);
                if (mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate == 0
                        && preferredMaxRefreshRate != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate =
                            preferredMaxRefreshRate;
                }
            }
        }

        if (obscuredChanged && w.isVisible() && mWallpaperController.isWallpaperTarget(w)) {
            // This is the wallpaper target and its obscured state changed... make sure the
            // current wallpaper's visibility has been updated accordingly.
            mWallpaperController.updateWallpaperVisibility();
        }

        w.handleWindowMovedIfNeeded();

        final WindowStateAnimator winAnimator = w.mWinAnimator;

        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
        w.resetContentChanged();

        // Moved from updateWindowsAndWallpaperLocked().
        if (w.mHasSurface) {
            // Take care of the window being ready to display.
            final boolean committed = winAnimator.commitFinishDrawingLocked();
            if (isDefaultDisplay && committed) {
                if (w.hasWallpaper()) {
                    ProtoLog.v(WM_DEBUG_WALLPAPER,
                            "First draw done in potential wallpaper target %s", w);
                    mWallpaperMayChange = true;
                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                    if (DEBUG_LAYOUT_REPEATS) {
                        surfacePlacer.debugLayoutRepeats(
                                "wallpaper and commitFinishDrawingLocked true",
                                pendingLayoutChanges);
                    }
                }
            }
        }

        final ActivityRecord activity = w.mActivityRecord;
        if (activity != null && activity.isVisibleRequested()) {
            activity.updateLetterboxSurface(w);
            final boolean updateAllDrawn = activity.updateDrawnWindowStates(w);
            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(activity)) {
                mTmpUpdateAllDrawn.add(activity);
            }
        }

        w.updateResizingWindowIfNeeded();
    };

在这个过程中会通过commitFinishDrawingLocked去检查当前窗口的mDrawState情况。Surface的mDrawState的绘制状态是由ViewRootImpl通过Session调用到WMS端,然后在WMS端设置的。

当此window窗口的mDrawState变化状态从NO_SURFACE -> DRAW_PENDING -> COMMIT_DRAW_PENDING  -> HAS_DRAWN-> READY_TO_SHOW,然后才会将图层置为可见状态,设置为可见的log如下:

05-25 10:56:31.956  1915  1973 V WindowManager: performShow on Window{f4647f5 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=false tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4372 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0 
05-25 10:56:31.962  1915  1973 V WindowManager: Showing Window{f4647f5 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=true tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4387 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0

 大概log如下:

06-01 10:12:18.006  1890  2256 V WindowManager: Relayout Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: viewVisibility=0 req=7104x3840 {(0,0)(fillxfill) sim={adjust=resize forwardNavigation} ty=BASE_APPLICATION wanim=0x10302f2
06-01 10:12:18.006  1890  2256 V WindowManager:   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
06-01 10:12:18.006  1890  2256 V WindowManager:   pfl=NO_MOVE_ANIMATION FORCE_DRAW_STATUS_BAR_BACKGROUND HIDE_NON_SYSTEM_OVERLAY_WINDOWS USE_BLAST FIT_INSETS_CONTROLLED
06-01 10:12:18.006  1890  2256 V WindowManager:   vsysui=LIGHT_STATUS_BAR LIGHT_NAVIGATION_BAR
06-01 10:12:18.006  1890  2256 V WindowManager:   apr=LIGHT_STATUS_BARS LIGHT_NAVIGATION_BARS
06-01 10:12:18.006  1890  2256 V WindowManager:   bhv=DEFAULT
06-01 10:12:18.006  1890  2256 V WindowManager:   fitSides=}
06-01 10:12:18.008  1890  2256 W WindowManager: setLayoutNeeded: callers=com.android.server.wm.WindowState.setDisplayLayoutNeeded:2671 com.android.server.wm.WindowManagerService.relayoutWindow:2419 com.android.server.wm.Session.relayout:249 
06-01 10:12:18.009  1890  2256 V WindowManager: Creating surface in session android.view.SurfaceSession@fcb7984 window WindowStateAnimator{31728a0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity} format=-1 flags=4
06-01 10:12:18.015  1890  2256 V WindowManager: Got surface: Surface(name=com.android.settings/com.android.settings.homepage.SettingsHomepageActivity)/@0xafd3c59, set left=0 top=0
06-01 10:12:18.015  1890  2256 I WindowManager: >>> OPEN TRANSACTION createSurfaceLocked
06-01 10:12:18.015  1890  2256 I WindowManager:   SURFACE CREATE pos=(0,0) HIDE: Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
06-01 10:12:18.015  1890  2256 V WindowManager: Created surface WindowStateAnimator{31728a0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
06-01 10:12:18.016  1890  2256 V WindowManager: performSurfacePlacementInner: entry. Called by com.android.server.wm.RootWindowContainer.performSurfacePlacement:765 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:177 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:126 
06-01 10:12:18.016  1890  2256 I WindowManager: >>> OPEN TRANSACTION performLayoutAndPlaceSurfaces
...
06-01 10:12:18.020  1890  2256 I WindowManager: <<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces
06-01 10:12:18.021  1890  2256 E WindowManager: performSurfacePlacementInner exit
06-01 10:12:18.021  1890  2256 V WindowManager: Already visible and does not turn on screen, skip preparing: Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
06-01 10:12:18.022  1890  2256 W WindowManager: Moving IM target from null to null since mInputMethodWindow is null
06-01 10:12:18.022  1890  2256 V WindowManager: Win Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: isDrawn=false, animating=false
06-01 10:12:18.022  1890  2256 V WindowManager: Not displayed: s=Surface(name=com.android.settings/com.android.settings.homepage.SettingsHomepageActivity)/@0xafd3c59 pv=true mDrawState=1 ph=false th=true a=false
06-01 10:12:18.022  1890  2256 V WindowManager: Relayout complete Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: outFrames=ClientWindowFrames{frame=[0,0][7104,3840] display=[0,0][7104,3840] parentFrame=[0,0][0,0]}
06-01 10:12:18.214  1890  1950 I WindowManager: commitFinishDrawingLocked: Window{d8b1e28 u0 Splash Screen com.android.settings} cur mDrawState=HAS_DRAWN
06-01 10:12:18.214  1890  1950 D ActivityTaskManager: updateWindows: starting Window{d8b1e28 u0 Splash Screen com.android.settings} isOnScreen=true allDrawn=false freezingScreen=false
06-01 10:12:18.214  1890  1950 V WindowManager: Resizing Window{d8b1e28 u0 Splash Screen com.android.settings}: configChanged=false last=Rect(0, 0 - 7104, 3840) frame=Rect(0, 0 - 7104, 3840)
06-01 10:12:18.215  1890  1950 V WindowManager: performShow on Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=false tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4372 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0 
...
06-01 10:12:18.220  1890  1950 V WindowManager: Win Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: isDrawn=true, animating=true

06-01 10:12:18.228  1890  1950 V WindowManager: Showing Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=true tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4387 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/695427.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】匿名管道的应用场景 --- 进程池

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

体素技术在AI绘画中的革新作用

随着人工智能技术的不断进步&#xff0c;AI绘画已经成为艺术创作和视觉设计领域的一大趋势。在众多推动AI绘画发展的技术中&#xff0c;体素技术以其独特的优势&#xff0c;正在逐渐改变着我们对计算机生成图像的认识。本文旨在探讨体素技术在AI绘画中的应用与影响&#xff0c;…

【车载开发系列】MCU选型

【车载开发系列】MCU选型 【车载开发系列】MCU选型 【车载开发系列】MCU选型一. 重要概念二. MCU选型的风险风险1风险2 三. MCU选型要点四. MCU选型维度五. MCU 选型需要考虑的因素1&#xff09;ROM/RAM2&#xff09;速度/主频3&#xff09;分析外设需求4&#xff09;工作电压(…

DNS域名解析服务和bond网卡

DHS域名解析 概述 DNS是域名系统的简称&#xff0c;它的作用就是域名和ip地址之间的映射关系。 在互联网中&#xff0c;ip地址是通信的唯一标识。&#xff08;逻辑地址&#xff09; 访问网站需要一个域名 域名解析的目的就是为了实现访问域名就等于访问ip地址。 在访问域…

【数据结构】前缀树(字典树)汇总

基础 {“a”,“abc”,“bac”,“bbc”,“ca” }的字典树如下图&#xff1a; 最主用的应用&#xff1a;一&#xff0c;字符串编码。二&#xff0c;位运算。 字符串编码 相比利用哈希映射编码&#xff0c;优点如下&#xff1a; 依次查询长度为n的字符串s的前缀时间复杂度是O(…

直接用sql语句来查询和分析excel表,不需要导数据,提供了sql语句自动生成,不会sql也能用

用sql语句来查询excel表&#xff0c;我们需要把excel表格导入到数据库中&#xff0c;然后用数据库的管理工具写sql语句来进行查询。方法有很多&#xff0c;我们不一一描述。 今天我们要说的是直接用sql语句来查询和分析excel表。为什么有这么一个想法呢&#xff1f;程…

《软件定义安全》之五:软件定义的安全架构

第5章 软件定义的安全架构 1.软件定义安全架构 安全控制平台&#xff0c;主要负责安全设备的资源池化管理、各类安全信息源的收集和分析、与客户业务系统对接&#xff0c;以及相应安全应用的策略解析和执行。 安全应用是根据特定的安全需求所开发的程序&#xff0c;它利用安全…

LabVIEW进行图像拼接的实现方法与优化

在工业检测和科研应用中&#xff0c;对于大尺寸物体的拍摄需要通过多次拍摄后进行图像拼接。LabVIEW 作为强大的图形化编程工具&#xff0c;能够实现图像拼接处理。本文将详细介绍LabVIEW进行图像拼接的实现方法、注意事项和提高效率的策略。 图像拼接的实现方法 1. 图像采集…

上位机图像处理和嵌入式模块部署(f407 mcu项目开发、产品开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 和做项目、产品相比较&#xff0c;做技术还是比较简单的。一般来说&#xff0c;所谓的技术&#xff0c;就是把相关的功能实现即可。但是做项目和产…

月薪70-100k,京东招ML算法工程师和运筹优化专家!

Datawhale分享 推荐&#xff1a;黄玉琳&#xff0c;京东&#xff0c;Datawhale成员 团队介绍 我们是京东零售集团供应链算法优化团队&#xff0c;通过在人工智能与运筹优化领域的持续性技术革新,为京东自营千万级商品提供算法策略支持,实现了以用户为中心的供应链管理和更高效…

这两款kimi和豆包插件,用来辅助文献阅读和总结,太香了!娜姐亲测好用

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 ChatGPT刚出来的时候&#xff0c;几款速读PDF的AI工具ChatDoc、ChatPDF也跟着火了起来&#xff0c;可见大家对于速读文献、总结文档需求很高。 我记得ChatPDF只有几次免费机会…

这4个科研思维陷阱,可能正在阻碍你发表论文!

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 昨天&#xff0c;有位同学忧心忡忡的过来问我&#xff1a;一区文章已经接收了&#xff0c;因为两张图里有错误&#xff0c;想要撤稿重投。 我的建议如下&#xff1a; 1 重新投…

LabVIEW 用于 MES 系统和卡钳上位机检测

LabVIEW 确实可以用于制造执行系统&#xff08;MES&#xff09;的开发以及卡钳上位机检测。以下是详细说明&#xff1a; 使用 LabVIEW 开发 MES 系统 数据采集与处理&#xff1a;LabVIEW 擅长实时数据采集和处理&#xff0c;可以连接多种传感器和设备&#xff0c;获取生产线上…

如何远程桌面连接?

远程桌面连接是一种方便快捷的方式&#xff0c;可以帮助用户在不同地区的设备之间实现信息的远程通信。我们将介绍一种名为【天联】的组网产品&#xff0c;它可以帮助用户轻松实现远程桌面连接。 【天联】组网是一款异地组网内网穿透产品&#xff0c;由北京金万维科技有限公司…

最新大屏幕互动系统PHP源码 附动态背景图和配乐素材 含搭建教程

简介&#xff1a; 最新大屏幕互动系统PHP源码 附动态背景图和配乐素材 含搭建教程 测试环境&#xff1a;NginxPHP7.0MySQL5.6 ![CYA]CPZMY8NK8YADA.png](https://img-blog.csdnimg.cn/img_convert/fe17ef2c4663e1ad9d79b5e55f1db146.png)

【ARM】PK51-如何添加芯片型号的方法

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 遇到打开工程提示没有该芯片设备提示如何解决。 2、 问题场景 客户发来一个工程文件&#xff0c;打开后软件提示没有发现该芯片设备提示。 图 1 3、软硬件环境 1&#xff09;、软件版本&#xff1a;keil μvision…

【Linux】用户和组的管理、综合实训

目录 实训1&#xff1a;用户的管理 实训2:组的管理 实训3:综合实训 实训1&#xff1a;用户的管理 (1)创建一个新用户userl&#xff0c;设置其主目录为/home/user 1。 (2)查看/etc/passwd 文件的最后一行&#xff0c;看看是如何记录的。 (3)查看文件/etc/shadow文件的最后一…

【Qt秘籍】[010]-Qt常用控件

一、控件概述 在GUI&#xff08;图形用户界面&#xff09;开发领域&#xff0c;Qt无疑是众多开发者心中的首选框架之一。它不仅跨平台、功能强大&#xff0c;而且拥有丰富且灵活的控件库&#xff0c;使得开发者能够快速构建美观、高效的用户界面。对于初学者而言&#xff0…

k8s学习--kubernetes服务自动伸缩之垂直伸缩(资源伸缩)VPA详细解释与安装

文章目录 前言VPA简介简单理解详细解释VPA的优缺点优点1.自动化资源管理2.资源优化3.性能和稳定性提升5.成本节约6.集成性和灵活性 缺点1.Pod 重启影响可用性2.与 HPA 冲突3.资源监控和推荐滞后&#xff1a;4.实现复杂度&#xff1a; 核心概念Resource Requests 和 Limits自动调…

星空如何异地组网?

网络已经成为人们生活的重要组成部分。无论是个人还是企业&#xff0c;都需要通过网络进行信息传输和资源共享。在传统的网络连接方式中&#xff0c;存在着网络限制、访问速度慢、数据安全等问题。随着科技的发展&#xff0c;一种全新的网络连接方式──星空异地组网&#xff0…