DrawState与wms绘制流程梳理

APP端添加窗口->Srv端添加窗口

// app端获取wms
mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
// app端调用wms 会话进行addview完成窗口添加
mWindowManager.addView(mWindowViewLayout, mLayoutParams);

看代码,串一下流程

流程图汇总

在这里插入图片描述
从图中可以看到,整体app端到srv端的窗口添加是通过session调用过去的,通过app端的viewRootImpl
而Srv端的添加逻辑主要就是在wms中的addWindow了;这里详细展开看下

srv端代码展开分析

public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, @InsetsType int requestedVisibleTypes,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
            float[] outSizeCompatScale) {
        outActiveControls.set(null);
        int[] appOp = new int[1];
        final boolean isRoundedCornerOverlay = (attrs.privateFlags
                & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
        int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
                appOp);
        if (res != ADD_OKAY) {
            return res;
        }

        WindowState parentWindow = null;
        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        final int type = attrs.type;

        synchronized (mGlobalLock) {
            if (!mDisplayReady) {
                throw new IllegalStateException("Display has not been initialialized");
            }

            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);

            if (displayContent == null) {
                ProtoLog.w(WM_ERROR, "Attempted to add window to a display that does "
                        + "not exist: %d. Aborting.", displayId);
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }
            if (!displayContent.hasAccess(session.mUid)) {
                ProtoLog.w(WM_ERROR,
                        "Attempted to add window to a display for which the application "
                                + "does not have access: %d.  Aborting.",
                        displayContent.getDisplayId());
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }

            if (mWindowMap.containsKey(client.asBinder())) {
                ProtoLog.w(WM_ERROR, "Window %s is already added", client);
                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
            }

这里去找了下是否存在 父window,条件是为当前add的window类型是什么暂时不清楚,但是不在这个范围内
具体window类型定义在此文件中:frameworks/base/core/java/android/view/WindowManager.java
这里的限定范围是 (1000)  - 1999;
因此这里并没有对parentWindow进行赋值,此时仍然是null;
            if (type >= FIRST_SUB_WINDOW&& type <= LAST_SUB_WINDOW) {
                parentWindow = windowForClientLocked(null, attrs.token, false);
                if (parentWindow == null) {
                    ProtoLog.w(WM_ERROR, "Attempted to add window with token that is not a window: "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                }
                if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
                        && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                    ProtoLog.w(WM_ERROR, "Attempted to add window with token that is a sub-window: "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                }
            }

            if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
                ProtoLog.w(WM_ERROR,
                        "Attempted to add private presentation window to a non-private display.  "
                                + "Aborting.");
                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
            }

            if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) {
                ProtoLog.w(WM_ERROR,
                        "Attempted to add presentation window to a non-suitable display.  "
                                + "Aborting.");
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }

            int userId = UserHandle.getUserId(session.mUid);
            if (requestUserId != userId) {
                try {
                    mAmInternal.handleIncomingUser(callingPid, callingUid, requestUserId,
                            false /*allowAll*/, ALLOW_NON_FULL, null, null);
                } catch (Exception exp) {
                    ProtoLog.w(WM_ERROR, "Trying to add window with invalid user=%d",
                            requestUserId);
                    return WindowManagerGlobal.ADD_INVALID_USER;
                }
                // It's fine to use this userId
                userId = requestUserId;
            }

hasParent为false;
            ActivityRecord activity = null;
            final boolean hasParent = parentWindow != null;

            // Use existing parent window token for child windows since they go in the same token
            // as there parent window so we can apply the same policy on them.
            对子窗口使用现有的父窗口令牌,因为它们与父窗口使用相同的令牌,
            因此我们可以对它们应用相同的策略
            对于当前添加的悬浮窗,并没有一个parentwindow,因此这里使用的是传入的layout的attrs对应的token
            去通过getWindowToken 拿到map中是否包含了这个token,显然是没有的,所以这里token是null;
            真正的创建token还在下面
            
            WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);
            // If this is a child window, we want to apply the same type checking rules as the
            // parent window type.
            final int rootType = hasParent ? parentWindow.mAttrs.type : type;

            boolean addToastWindowRequiresToken = false;

            final IBinder windowContextToken = attrs.mWindowContextToken;

            if (token == null) {
                if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
                        rootType, attrs.token, attrs.packageName)) {
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                if (hasParent) {
                    // Use existing parent window token for child windows.
                    token = parentWindow.mToken;
                } else if (mWindowContextListenerController.hasListener(windowContextToken)) {
                    // Respect the window context token if the user provided it.
                    final IBinder binder = attrs.token != null ? attrs.token : windowContextToken;
                    final Bundle options = mWindowContextListenerController
                            .getOptions(windowContextToken);
                    token = new WindowToken.Builder(this, binder, type)
                            .setDisplayContent(displayContent)
                            .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                            .setRoundedCornerOverlay(isRoundedCornerOverlay)
                            .setFromClientToken(true)
                            .setOptions(options)
                            .build();
                } else {
                这里把传入的client作为参数,转为binder对象,并new了一个window token,把这个binder作为关键信息
                传了进去;这里的client是函数的入参,类型为IWindow client;
                追根溯源,其是viewrootImpl类传入的一个成员变量,是一个很重要的角色,是一个binder的stub对象,可以和
                server端进行通信;
                    final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                    token = new WindowToken.Builder(this, binder, type)
                            .setDisplayContent(displayContent)
                            .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                            .setRoundedCornerOverlay(isRoundedCornerOverlay)
                            .build();
                }
            } else if (rootType >= FIRST_APPLICATION_WINDOW
                    && rootType <= LAST_APPLICATION_WINDOW) {
                activity = token.asActivityRecord();
                if (activity == null) {
                    ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token "
                            + ".%s Aborting.", token);
                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
                } else if (activity.getParent() == null) {
                    ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token "
                            + ".%s Aborting.", token);
                    return WindowManagerGlobal.ADD_APP_EXITING;
                } else if (type == TYPE_APPLICATION_STARTING) {
                    if (activity.mStartingWindow != null) {
                        ProtoLog.w(WM_ERROR, "Attempted to add starting window to "
                                + "token with already existing starting window");
                        return WindowManagerGlobal.ADD_DUPLICATE_ADD;
                    }
                    if (activity.mStartingData == null) {
                        ProtoLog.w(WM_ERROR, "Attempted to add starting window to "
                                + "token but already cleaned");
                        return WindowManagerGlobal.ADD_DUPLICATE_ADD;
                    }
                }
            } else if (rootType == TYPE_INPUT_METHOD) {
                if (token.windowType != TYPE_INPUT_METHOD) {
                    ProtoLog.w(WM_ERROR, "Attempted to add input method window with bad token "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            } else if (rootType == TYPE_VOICE_INTERACTION) {
                if (token.windowType != TYPE_VOICE_INTERACTION) {
                    ProtoLog.w(WM_ERROR, "Attempted to add voice interaction window with bad token "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            } else if (rootType == TYPE_WALLPAPER) {
                if (token.windowType != TYPE_WALLPAPER) {
                    ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with bad token "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
                if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
                    ProtoLog.w(WM_ERROR,
                            "Attempted to add Accessibility overlay window with bad token "
                                    + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            } else if (type == TYPE_TOAST) {
                // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
                addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
                        callingUid, parentWindow);
                if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
                    ProtoLog.w(WM_ERROR, "Attempted to add a toast window with bad token "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            } else if (type == TYPE_QS_DIALOG) {
                if (token.windowType != TYPE_QS_DIALOG) {
                    ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with bad token "
                            + "%s.  Aborting.", attrs.token);
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            } else if (token.asActivityRecord() != null) {
                ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d",
                        rootType);
                // It is not valid to use an app token with other system types; we will
                // instead make a new token for it (as if null had been passed in for the token).
                attrs.token = null;
                token = new WindowToken.Builder(this, client.asBinder(), type)
                        .setDisplayContent(displayContent)
                        .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                        .build();
            }

            这里是很关键的地方,创建了这个windowtoken对应的windowState,
            final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
            if (win.mDeathRecipient == null) {
                // Client has apparently died, so there is no reason to
                // continue.
                ProtoLog.w(WM_ERROR, "Adding window client %s"
                        + " that is dead, aborting.", client.asBinder());
                return WindowManagerGlobal.ADD_APP_EXITING;
            }

            if (win.getDisplayContent() == null) {
                ProtoLog.w(WM_ERROR, "Adding window to Display that has been removed.");
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }

            final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
            displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
            attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), callingUid, callingPid);
            attrs.inputFeatures = sanitizeSpyWindow(attrs.inputFeatures, win.getName(), callingUid,
                    callingPid);
            win.setRequestedVisibleTypes(requestedVisibleTypes);

            res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
            if (res != ADD_OKAY) {
                return res;
            }

            这里很关键,创建了对应的inputChannel链路;outInputChannel是入参,有viewrootImpl创建的;
            final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
                win.openInputChannel(outInputChannel);
            }

            // If adding a toast requires a token for this app we always schedule hiding
            // toast windows to make sure they don't stick around longer then necessary.
            // We hide instead of remove such windows as apps aren't prepared to handle
            // windows being removed under them.
            //
            // If the app is older it can add toasts without a token and hence overlay
            // other apps. To be maximally compatible with these apps we will hide the
            // window after the toast timeout only if the focused window is from another
            // UID, otherwise we allow unlimited duration. When a UID looses focus we
            // schedule hiding all of its toast windows.
            if (type == TYPE_TOAST) {
                if (!displayContent.canAddToastWindowForUid(callingUid)) {
                    ProtoLog.w(WM_ERROR, "Adding more than one toast window for UID at a time.");
                    return WindowManagerGlobal.ADD_DUPLICATE_ADD;
                }
                // Make sure this happens before we moved focus as one can make the
                // toast focusable to force it not being hidden after the timeout.
                // Focusable toasts are always timed out to prevent a focused app to
                // show a focusable toasts while it has focus which will be kept on
                // the screen after the activity goes away.
                if (addToastWindowRequiresToken
                        || (attrs.flags & FLAG_NOT_FOCUSABLE) == 0
                        || displayContent.mCurrentFocus == null
                        || displayContent.mCurrentFocus.mOwnerUid != callingUid) {
                    mH.sendMessageDelayed(
                            mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
                            win.mAttrs.hideTimeoutMilliseconds);
                }
            }

            // Switch to listen to the {@link WindowToken token}'s configuration changes when
            // adding a window to the window context. Filter sub window type here because the sub
            // window must be attached to the parent window, which is attached to the window context
            // created window token.
            if (!win.isChildWindow()
                    && mWindowContextListenerController.hasListener(windowContextToken)) {
                final int windowContextType = mWindowContextListenerController
                        .getWindowType(windowContextToken);
                final Bundle options = mWindowContextListenerController
                        .getOptions(windowContextToken);
                if (type != windowContextType) {
                    ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
                            + " LayoutParams.type should match! Type from LayoutParams is %d,"
                            + " but type from WindowContext is %d", type, windowContextType);
                    // We allow WindowProviderService to add window other than windowContextType,
                    // but the WindowProviderService won't be associated with the window's
                    // WindowToken.
                    if (!isWindowProviderService(options)) {
                        return WindowManagerGlobal.ADD_INVALID_TYPE;
                    }
                } else {
                    mWindowContextListenerController.updateContainerForWindowContextListener(
                            windowContextToken, token);
                }
            }

            // From now on, no exceptions or errors allowed!
            if (displayContent.mCurrentFocus == null) {
                displayContent.mWinAddedSinceNullFocus.add(win);
            }

            if (excludeWindowTypeFromTapOutTask(type)) {
                displayContent.mTapExcludedWindows.add(win);
            }

            这里终于将当前windowState的信息放到了mWindowMap中,key是client(也就是viewrootImpl的binder stub)
            后面就先不看了,到此为止
            win.attach();
            mWindowMap.put(client.asBinder(), win);
            win.initAppOpsState();
。。。。
    }
        Binder.restoreCallingIdentity(origId);

        return res;
    }

老大一堆,用一句话总结就是,完成mWindowMap变量的成员添加,key是app端的binder stub,value是创建出来的windowState

小总结一下

对于add到server端的一个window来说,addWindow时主要完成以下4个关键步骤

  1. 创建这个窗口的WindowToken,并将其挂载到层级结构树中(一般windowTokend会挂载到leaf下,作为倒数第二层,最后一层往往是个windowState对象)
  2. 创建一个WindowState对象,与当前window进行绑定(使用当前window的信息进行创建)
  3. 将当前窗口的input链路进行打通,通过openInputChannel完成input链路初始化,创建了对应的 Pair<socket,socket>
  4. 将当前窗口的windowState挂载到层级结构树中,使其结构完成;

relayout

概述

应用端发起addwindow到wms,wms创建windowtoken和windowstate,并挂载到了层级结构树上面;
此时应用端会发起relayoutWindow的操作

其实上面addWindow时,也只是new出来两个 windowToken和windowState,此时两者只是初始化,并没有surface进行绘制的能力;

其实真正进行surfaceControl创建就是在这个relayout过程中;

代码

绘制阶段

5个绘制阶段,表示当前window所处的绘制状态
在这里插入图片描述
应用调用到wms的relayout的过程和之前的 addWindow类似,都是通过viewRootImpl中的session的binder调用过来的,具体应用侧的流程还没有梳理,大概就是doTraversal-> performTraversals的过程;下面主要看下srv端的逻辑

代码梳理

创建surfacecontrol

public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags,
            ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
            SurfaceControl outSurfaceControl, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) { 


。。。
			// 1. 通过刚刚存储的变量,拿到对应的binder和windowstate
            final WindowState win = windowForClientLocked(session, client, false);
。。。
			// 2. 创建surfacecontrol
			if (shouldRelayout) {
                try {
                    result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
                } catch (Exception e) {
。。。
                }
            }
            // 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.
            
           	// 3. performSurfacePlacement进行relayout操作!!!!!
            mWindowPlacerLocked.performSurfacePlacement(true /* force */);
			//ignore
                
            if (!win.isGoneForLayout()) {
                win.mResizedWhileGone = false;
            }
            
 			// 4. 相关配置数据
            win.fillClientWindowFramesAndConfiguration(outFrames, mergedConfiguration,
                    false /* useLatestConfig */, shouldRelayout);
            outInsetsState.set(win.getCompatInsetsState(), win.isClientLocal());
。。。
        }
。。。
        return result;
    }

finishDraw

看finishDraw之前,回顾下刚刚看的逻辑
整体上就是从app端通过viewrootimpl到session服务端,完成前期的调用,最后是finishDraw的调用;
在这里插入图片描述
我们对finishDraw的流程进行分析
app端的就先不看了,从图中可以看到整体的调用链路,也可以通过抓trace来看调用栈。
我们直接看server端,在finishdraw中的处理。

WindowManagerService.java

void finishDrawingWindow(Session session, IWindow client,
            @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
        if (postDrawTransaction != null) {
            postDrawTransaction.sanitize();
        }

        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized (mGlobalLock) {
           这里通过刚刚addwindow保存的信息,直接拿到对应窗口的相关信息;
                WindowState win = windowForClientLocked(session, client, false);
                ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
                        win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
                if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
                    if (win.hasWallpaper()) {
                        win.getDisplayContent().pendingLayoutChanges |=
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                    }
                    win.setDisplayLayoutNeeded();
                    mWindowPlacerLocked.requestTraversal();
                }
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

看windowState中具体的finishDrawing是怎么处理的;

boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
// 前面这些暂时忽略,是转屏的逻辑,以及activityRecord的逻辑,这里我们先看一个普通的systemWindow的链路;
        if (mOrientationChangeRedrawRequestTime > 0) {
            final long duration =
                    SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
            Slog.i(TAG, "finishDrawing of orientation change: " + this + " " + duration + "ms");
            mOrientationChangeRedrawRequestTime = 0;
        } else if (mActivityRecord != null && mActivityRecord.mRelaunchStartTime != 0
                && mActivityRecord.findMainWindow() == this) {
            final long duration =
                    SystemClock.elapsedRealtime() - mActivityRecord.mRelaunchStartTime;
            Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
            mActivityRecord.finishOrAbortReplacingWindow();
        }
        if (mActivityRecord != null && mAttrs.type == TYPE_APPLICATION_STARTING) {
            mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger()
                    .notifyStartingWindowDrawn(mActivityRecord);
        }

        final boolean syncActive = mPrepareSyncSeqId > 0;
        final boolean syncStillPending = syncActive && mPrepareSyncSeqId > syncSeqId;
        if (syncStillPending && postDrawTransaction != null) {
            ProtoLog.d(WM_DEBUG_SYNC_ENGINE, "Got a buffer for request id=%d but latest request is"
                    + " id=%d. Since the buffer is out-of-date, drop it. win=%s", syncSeqId,
                    mPrepareSyncSeqId, this);
            // sync is waiting for a newer seqId, so this buffer is obsolete and can be dropped
            // to free up the buffer queue.
            dropBufferFrom(postDrawTransaction);
        }

        final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);

        boolean skipLayout = false;
        boolean layoutNeeded = false;
        // Control the timing to switch the appearance of window with different rotations.
        final AsyncRotationController asyncRotationController =
                mDisplayContent.getAsyncRotationController();
        if (asyncRotationController != null
                && asyncRotationController.handleFinishDrawing(this, postDrawTransaction)) {
            // Consume the transaction because the controller will apply it with fade animation.
            // Layout is not needed because the window will be hidden by the fade leash.
            postDrawTransaction = null;
            skipLayout = true;
        } else if (syncActive) {
            // Currently in a Sync that is using BLAST.
            if (!syncStillPending) {
                layoutNeeded = onSyncFinishedDrawing();
            }
            if (postDrawTransaction != null) {
                mSyncTransaction.merge(postDrawTransaction);
                // Consume the transaction because the sync group will merge it.
                postDrawTransaction = null;
            }
        } else if (useBLASTSync()) {
            // Sync that is not using BLAST
            layoutNeeded = onSyncFinishedDrawing();
        }
// 核心逻辑在这里:WindowStateAnimator中的finishDrawingLocked
        layoutNeeded |=
                mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
        mClientWasDrawingForSync = false;
        // We always want to force a traversal after a finish draw for blast sync.
        return !skipLayout && (hasSyncHandlers || layoutNeeded);
    }

WindowStateAnimator.java
这个类也是挺关键的,很多核心逻辑都在这里面
在这里插入图片描述
它与WindowState是一一对应的(WindowState成员变量),是用来控制 动画 和 surface操作的;很关键只能说

    boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
            boolean forceApplyNow) {
        final boolean startingWindow =
                mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
        if (startingWindow) {
            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finishing drawing window %s: mDrawState=%s",
                    mWin, drawStateToString());
        }

        boolean layoutNeeded = false;

        // 最开始这里肯定是 DRAW_PENDING,追一下赋值:是在reset的时候==createSurface的时候;
        if (mDrawState == DRAW_PENDING) {
            ProtoLog.v(WM_DEBUG_DRAW,
                    "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin,
                    mSurfaceController);
            if (startingWindow) {
                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin);
            }

            // 这里直接就下一个阶段~ 直接到commit draw pending,实际上还没有提交,只是先把状态切换过来了;
            mDrawState = COMMIT_DRAW_PENDING;
            layoutNeeded = true;
        }

        if (postDrawTransaction != null) {
            // If there is no surface, the last draw was for the previous surface. We don't want to
            // wait until the new surface is shown and instead just apply the transaction right
            // away.
            if (mLastHidden && mDrawState != NO_SURFACE && !forceApplyNow) {
                mPostDrawTransaction.merge(postDrawTransaction);
            } else {
                mWin.getSyncTransaction().merge(postDrawTransaction);
            }
            layoutNeeded = true;
        }

        return layoutNeeded;
    }

在这里插入图片描述
在这里插入图片描述
到这里发现没什么其他逻辑了,那就返回;回到WindowManagerService.java中finishDrawingWindow

WindowManagerService.java

void finishDrawingWindow(Session session, IWindow client,
            @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
        if (postDrawTransaction != null) {
            postDrawTransaction.sanitize();
        }

        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized (mGlobalLock) {
           这里通过刚刚addwindow保存的信息,直接拿到对应窗口的相关信息;
                WindowState win = windowForClientLocked(session, client, false);
                ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
                        win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
                        // 这里看完了,往下走
                if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
                    if (win.hasWallpaper()) {
                        win.getDisplayContent().pendingLayoutChanges |=
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                    }
                    win.setDisplayLayoutNeeded();
// 接下来我们看这里,调用WindowPlacerLocked(WindowSurfacePlacer类窗口surface放置者, 听听这明着)的 requestTraversal方法(请求遍历)!
                    mWindowPlacerLocked.requestTraversal();
                }
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

WindowSurfacePlacer.java
这里看到窗口surface放置类中,直接调用了service的AnimationHandler post出去一个放置任务!

void requestTraversal() {
        if (mTraversalScheduled) {
            return;
        }

        // Set as scheduled even the request will be deferred because mDeferredRequests is also
        // increased, then the end of deferring will perform the request.
        mTraversalScheduled = true;
        if (mDeferDepth > 0) {
            mDeferredRequests++;
            if (DEBUG) Slog.i(TAG, "Defer requestTraversal " + Debug.getCallers(3));
            return;
        }
        // mPerformSurfacePlacement:
        //     private final Traverser mPerformSurfacePlacement = new Traverser();继承Runnable
		// 就是个Runnable!
        mService.mAnimationHandler.post(mPerformSurfacePlacement);
    }

frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
post的调用,内部的runnable需要追踪一下,这里实际的finishDraw非常关键的逻辑
performSurfacePlacement-》performSurfacePlacement-》performSurfacePlacementLoop

private class Traverser implements Runnable {
        @Override
        public void run() {
            synchronized (mService.mGlobalLock) {
                performSurfacePlacement();
            }
        }
    }

    final void performSurfacePlacement() {
        performSurfacePlacement(false /* force */);
    }

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

    private void performSurfacePlacementLoop() {
        if (mInLayout) {
            if (DEBUG) {
                throw new RuntimeException("Recursive call!");
            }
            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
                    + Debug.getCallers(3));
            return;
        }

        // TODO(multi-display):
        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
        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;
        }

        mInLayout = true;

        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 {
        // 调用到这里,是RootWindowContainer的方法
            mService.mRoot.performSurfacePlacement();

            mInLayout = false;

            if (mService.mRoot.isLayoutNeeded()) {
                if (++mLayoutRepeatCount < 6) {
                    requestTraversal();
                } else {
                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
                    mLayoutRepeatCount = 0;
                }
            } else {
                mLayoutRepeatCount = 0;
            }

            if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
                mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
                mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
            }
        } catch (RuntimeException e) {
            mInLayout = false;
            Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
        }
    }

RootWindowContainer.java: performSurfacePlacement -> performSurfacePlacementNoTrace-》applySurfaceChangesTransaction

    void performSurfacePlacement() {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
        try {
            performSurfacePlacementNoTrace();
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
void performSurfacePlacementNoTrace() {
        。。。。。。。
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
        mWmService.openSurfaceTransaction();
        try {
            applySurfaceChangesTransaction();
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
            mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            if (SHOW_LIGHT_TRANSACTIONS) {
                Slog.i(TAG,
                        "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
            }
        }
        。。。。。。


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();
        if (mWmService.mWatermark != null) {
            mWmService.mWatermark.positionSurface(defaultDw, defaultDh, t);
        }
        if (mWmService.mStrictModeFlash != null) {
            mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, t);
        }
        if (mWmService.mEmulatorDisplayOverlay != null) {
            mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
                    defaultDc.getRotation(), t);
        }

        final int count = mChildren.size();
        for (int j = 0; j < count; ++j) {
            final DisplayContent dc = mChildren.get(j);
            // 这里!
            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);
        }
    }

-> DisplayContent.java:applySurfaceChangesTransaction
注意,这里就是核心逻辑了

void applySurfaceChangesTransaction() {
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
...........
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
        try {
            mDisplayPolicy.beginPostLayoutPolicyLw();
            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 {
         // 这里:对于所有的window,使用这个surface changes的任务
            forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        prepareSurfaces();

...........
    }


    void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
        ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
        forAllWindows(wrapper, traverseTopToBottom);
        wrapper.release();
    }

mApplySurfaceChangesTransaction
这个成员变量内容很多,我们挑重点看看;

// Moved from updateWindowsAndWallpaperLocked().
// 这里肯定是有surface的,理论上讲,此时已经app已经画完了,怎么会没有呢!
// 赋值的位置是:(下面图)setHasSurface的时候为true时是createSurface的时候;
        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();

在这里插入图片描述
WindowStateAnimator.java

boolean commitFinishDrawingLocked() {
        if (DEBUG_STARTING_WINDOW_VERBOSE &&
                mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
            Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
                    + drawStateToString());
        }
        // 这里进行一下校验,当前的状态应该是draw_pending的;
        if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
            return false;
        }
        ProtoLog.i(WM_DEBUG_ANIM, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s",
                mSurfaceController);
// 这里直接将状态变为 ready_to_show!并在下面进一步调用
        mDrawState = READY_TO_SHOW;
        boolean result = false;
        final ActivityRecord activity = mWin.mActivityRecord;
// 对于一个普通的系统窗口,不是一个activity,就会进入进来,如果是activity会走其他逻辑,我们后面再看;
// 这里先跟进去看看对于一个普通的系统窗口,会怎么 performShow!
        if (activity == null || activity.canShowWindows()
                || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
            result = mWin.performShowLocked();
        }
        return result;
    }

WindowState.java

boolean performShowLocked() {
......
        logPerformShow("Showing ");

        mWmService.enableScreenIfNeededLocked();
 // 这里也很重要,对于acitivity来说动画很重要,但是这个系统窗口是没有动画的,后面在看;
        mWinAnimator.applyEnterAnimationLocked();

        // Force the show in the next prepareSurfaceLocked() call.
        mWinAnimator.mLastAlpha = -1;
        ProtoLog.v(WM_DEBUG_ANIM, "performShowLocked: mDrawState=HAS_DRAWN in %s", this);
        
// 这里直接进入到下一阶段,state变成 has_drawn,但是实际还没有进行绘制呢!!!
        mWinAnimator.mDrawState = HAS_DRAWN;
        mWmService.scheduleAnimationLocked();

        if (mHidden) {
            mHidden = false;
            final DisplayContent displayContent = getDisplayContent();
// 这里可以看到,对于all window,每次调用都会对孩子进行处理,调用孩子的performShowLocked
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                final WindowState c = mChildren.get(i);
                if (c.mWinAnimator.mSurfaceController != null) {
                    c.performShowLocked();
                    // It hadn't been shown, which means layout not performed on it, so now we
                    // want to make sure to do a layout.  If called from within the transaction
                    // loop, this will cause it to restart with a new layout.
                    if (displayContent != null) {
                        displayContent.setLayoutNeeded();
                    }
                }
            }
        }

        return true;
    }

到这里,drawState的流程走完了,但是还没有实际绘制上,下面我们来看看,到底是哪里进行的绘制;

surface

上面我们发现,状态最终的转换核心函数是:
DisplayContent.java:applySurfaceChangesTransaction
在这个transaction执行完成后,整个的drawState已经到达了has_drawn的状态,这已经可以说,在wms侧已经干完了;
但是我们从 DisplayContent.java:applySurfaceChangesTransaction结束完成后,发现真正的提交给surfaceflinger的transaction在后面;

我们继续看这个函数:
DisplayContent.java:applySurfaceChangesTransaction

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

        beginHoldScreenUpdate();

        mTmpUpdateAllDrawn.clear();

        if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
                pendingLayoutChanges);

        if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
            mWallpaperController.adjustWallpaperWindows();
        }

        if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
            if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
            if (updateOrientation()) {
                setLayoutNeeded();
                sendNewConfiguration();
            }
        }

        if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
            setLayoutNeeded();
        }

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

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
        try {
            mDisplayPolicy.beginPostLayoutPolicyLw();
            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 {
            forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }

// 这里是关键信息!,对于上面执行完forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
之后,就已经完成了状态的切换,这里与sf进行交互,完成真正的任务提交;

        prepareSurfaces();

        // This should be called after the insets have been dispatched to clients and we have
        // committed finish drawing windows.
        mInsetsStateController.getImeSourceProvider().checkShowImePostLayout();

        mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
        if (!mWmService.mDisplayFrozen) {
            mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
                    mLastHasContent,
                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
                    mTmpApplySurfaceChangesTransactionState.preferredModeId,
                    mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate,
                    mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate,
                    mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
                    true /* inTraversal, must call performTraversalInTrans... below */);
        }
        // If the display now has content, or no longer has content, update recording.
        updateRecording();

        final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
        if (wallpaperVisible != mLastWallpaperVisible) {
            mLastWallpaperVisible = wallpaperVisible;
            mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
        }

        while (!mTmpUpdateAllDrawn.isEmpty()) {
            final ActivityRecord activity = mTmpUpdateAllDrawn.removeLast();
            // See if any windows have been drawn, so they (and others associated with them)
            // can now be shown.
            activity.updateAllDrawn();
        }

        finishHoldScreenUpdate();
    }

prepareSurfaces:看起来没啥东西,

void prepareSurfaces() {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces");
        try {
            final Transaction transaction = getPendingTransaction();
            这里父类,追踪一下
            super.prepareSurfaces();

            // TODO: Once we totally eliminate global transaction we will pass transaction in here
            //       rather than merging to global.
            SurfaceControl.mergeToGlobalTransaction(transaction);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

DisplayArea:prepareSurfaces

        void prepareSurfaces() {
            mDimmer.resetDimStates();
            super.prepareSurfaces();
            // Bounds need to be relative, as the dim layer is a child.
            getBounds(mTmpDimBoundsRect);
            mTmpDimBoundsRect.offsetTo(0 /* newLeft */, 0 /* newTop */);

            // If SystemUI is dragging for recents, we want to reset the dim state so any dim layer
            // on the display level fades out.
            if (forAllTasks(task -> !task.canAffectSystemUiFlags())) {
                mDimmer.resetDimStates();
            }

            if (mDimmer.updateDims(getSyncTransaction(), mTmpDimBoundsRect)) {
                scheduleAnimation();
            }
        }
    }

WindowContainer:prepareSurfaces

    void prepareSurfaces() {
        // If a leash has been set when the transaction was committed, then the leash reparent has
        // been committed.
        mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
        for (int i = 0; i < mChildren.size(); i++) {
            mChildren.get(i).prepareSurfaces();
        }
    }

这里遍历当前窗口的每一个孩子,并调用孩子的prepareSurfaces,实际上对于系统窗口,我们没有activity,也不是个task或者fragment,这里我们就看windowState,最为普通的这个;
在这里插入图片描述

WindowState:prepareSurfaces

    void prepareSurfaces() {
        mIsDimming = false;
        applyDims();
        updateSurfacePositionNonOrganized();
        // Send information to SurfaceFlinger about the priority of the current window.
        updateFrameRateSelectionPriorityIfNeeded();
        updateScaleIfNeeded();
这里:调用到WindowStateAnimate的surface准备函数;
        mWinAnimator.prepareSurfaceLocked(getSyncTransaction());
        super.prepareSurfaces();
    }

WindowStateAnimator:prepareSurfaceLocked
函数比较长,我们看重点的内容;

void prepareSurfaceLocked(SurfaceControl.Transaction t) {
        final WindowState w = mWin;
        if (!hasSurface()) {

            // There is no need to wait for an animation change if our window is gone for layout
            // already as we'll never be visible.
            if (w.getOrientationChanging() && w.isGoneForLayout()) {
                ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change skips hidden %s", w);
                w.setOrientationChanging(false);
            }
            return;
        }

        computeShownFrameLocked();

        if (w.isParentWindowHidden() || !w.isOnScreen()) {
            hide(t, "prepareSurfaceLocked");
            mWallpaperControllerLocked.hideWallpapers(w);

            // If we are waiting for this window to handle an orientation change. If this window is
            // really hidden (gone for layout), there is no point in still waiting for it.
            // Note that this does introduce a potential glitch if the window becomes unhidden
            // before it has drawn for the new orientation.
            if (w.getOrientationChanging() && w.isGoneForLayout()) {
                w.setOrientationChanging(false);
                ProtoLog.v(WM_DEBUG_ORIENTATION,
                        "Orientation change skips hidden %s", w);
            }
            
走到这里:,当前是hid状态,我们进入这儿if,createSurface的时候把mLast配置为true
        } else if (mLastAlpha != mShownAlpha
                || mLastHidden) {
            mLastAlpha = mShownAlpha;
            ProtoLog.i(WM_SHOW_TRANSACTIONS,
                    "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s",
                    mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w);
                    
1. 这里提交一个transaction:通过t.setAlpha传入这个surface,调整surface的alpha值、
// 这里就不进去看了,直接粘贴下函数里面的设置;返回true         t.setAlpha(mSurfaceControl, alpha);
            boolean prepared =
                mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);

            if (prepared && mDrawState == HAS_DRAWN) {
                if (mLastHidden) {

2. 这里就非常非常关键了,就是这里和surfacecontrol进行的交互,完成了show的调用,我们来详细看一下这里
                    if (showSurfaceRobustlyLocked(t)) {
                        mAnimator.requestRemovalOfReplacedWindows(w);
                        mLastHidden = false;
                        final DisplayContent displayContent = w.getDisplayContent();
                        if (!displayContent.getLastHasContent()) {
                            // This draw means the difference between unique content and mirroring.
                            // Run another pass through performLayout to set mHasContent in the
                            // LogicalDisplay.
                            displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
                            if (DEBUG_LAYOUT_REPEATS) {
                                mService.mWindowPlacerLocked.debugLayoutRepeats(
                                        "showSurfaceRobustlyLocked " + w,
                                        displayContent.pendingLayoutChanges);
                            }
                        }
                    } else {
                        w.setOrientationChanging(false);
                    }
                }
            }
        } else {
            if (mWin.isAnimating(TRANSITION | PARENTS)) {
                ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
            }
        }

        if (w.getOrientationChanging()) {
            if (!w.isDrawn()) {
                if (w.mDisplayContent.shouldSyncRotationChange(w)) {
                    w.mWmService.mRoot.mOrientationChangeComplete = false;
                    mAnimator.mLastWindowFreezeSource = w;
                }
                ProtoLog.v(WM_DEBUG_ORIENTATION,
                        "Orientation continue waiting for draw in %s", w);
            } else {
                w.setOrientationChanging(false);
                ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w);
            }
        }
    }

showSurfaceRobustlyLocked

    private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
        boolean shown = mSurfaceController.showRobustly(t);
        if (!shown)
            return false;

        t.merge(mPostDrawTransaction);
        return true;
    }

WindowSurfaceController:showRobustly

    boolean showRobustly(SurfaceControl.Transaction t) {
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
        if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
                + " during relayout");

        if (mSurfaceShown) {
            return true;
        }

        setShown(true);

1. 这里!通过transation调用了show,展示当前surfacecontrol
        t.show(mSurfaceControl);
        if (mAnimator.mIsWallpaper) {
            final DisplayContent dc = mAnimator.mWin.getDisplayContent();
            EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE,
                    dc.mDisplayId, 1 /* request shown */,
                    String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
        }
        return true;
    }

都调用完成后,回到
RootWindowContainer:performSurfacePlacementNoTrace,重新close transaction
在这里插入图片描述

dump查看

从dump可以看出,一共有很多window;能够从
Surface: shown=false layer=0 alpha=1.0 rect=(0.0,0.0) 1440 x 1 transform=(1.0, 0.0, 0.0, 1.0)
mDrawState=HAS_DRAWN mLastHidden=true
大致看出,当前是否是显示的。


WINDOW MANAGER WINDOWS (dumpsys window windows)
  Window #0 Window{43a0424 u0 pip-dismiss-overlay}:
    mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@4f80fb6
    mOwnerUid=10102 showForAllUsers=true package=com.android.systemui appop=NONE
    mAttrs={(0,220)(fillx500) sim={adjust=pan} ty=NAVIGATION_BAR_PANEL fmt=TRANSLUCENT
      fl=NOT_FOCUSABLE NOT_TOUCHABLE LAYOUT_IN_SCREEN
      pfl=SHOW_FOR_ALL_USERS FIT_INSETS_CONTROLLED}
    Requested w=720 h=500 mLayoutSeq=127385
    mBaseLayer=251000 mSubLayer=0    mToken=WindowToken{f2c54b7 android.os.BinderProxy@4f80fb6}
    mViewVisibility=0x4 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x0
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mLastReportedConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined}}
    mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
    Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
        display=[0,0][1440,720]
        content=[0,220][1440,720] visible=[0,220][1440,720]
        decor=[0,0][1440,720]
    mFrame=[0,220][1440,720] last=[0,0][0,0]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]    Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
     surface=[0,0][0,0]
    WindowStateAnimator{fb09620 pip-dismiss-overlay}:
      mDrawState=NO_SURFACE       mLastHidden=false
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
      mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0
    mOrientationChanging=false configOrientationChanging=true mAppFreezing=false mReportOrientationChanged=true
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    isOnScreen=false
    isVisible=false
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= {  }
  Window #1 Window{c12ce36 u0 NotificationShade}:
    mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@efd2f8
    mOwnerUid=10102 showForAllUsers=true package=com.android.systemui appop=NONE
    mAttrs={(0,0)(fillxfill) gr=TOP CENTER_VERTICAL sim={adjust=resize} layoutInDisplayCutoutMode=always ty=2040 fmt=TRANSLUCENT
      fl=NOT_FOCUSABLE TOUCHABLE_WHEN_WAKING WATCH_OUTSIDE_TOUCH SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
      pfl=COLOR_SPACE_AGNOSTIC BEHAVIOR_CONTROLLED FIT_INSETS_CONTROLLED
      bhv=SHOW_TRANSIENT_BARS_BY_SWIPE}
    Requested w=720 h=1440 mLayoutSeq=17
    mBaseLayer=191000 mSubLayer=0    mToken=WindowToken{c3493d1 android.os.BinderProxy@6f78a5b}
    mViewVisibility=0x4 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x0
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mLastReportedConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined}}
    mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
    Frames: containing=[0,0][720,1440] parent=[0,0][720,1440]
        display=[0,0][720,1440]
        content=[0,0][720,1440] visible=[0,0][720,1440]
        decor=[0,0][720,1440]
    mFrame=[0,0][720,1440] last=[0,0][720,1440]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]    Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
     surface=[0,0][0,0]
    WindowStateAnimator{4124123 NotificationShade}:
      mDrawState=NO_SURFACE       mLastHidden=false
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
      mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0
    mOrientationChanging=false configOrientationChanging=true mAppFreezing=false mReportOrientationChanged=true
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    isOnScreen=false
    isVisible=false
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= {  }
  Window #2 Window{4b25d1a u0 StatusBar}:
    mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@ce60910
    mOwnerUid=10102 showForAllUsers=true package=com.android.systemui appop=NONE
    mAttrs={(0,0)(fillx0) gr=TOP CENTER_VERTICAL sim={adjust=pan} layoutInDisplayCutoutMode=always ty=STATUS_BAR fmt=TRANSLUCENT
      fl=NOT_FOCUSABLE SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
      pfl=COLOR_SPACE_AGNOSTIC FIT_INSETS_CONTROLLED}
    Requested w=1440 h=0 mLayoutSeq=127407
    mBaseLayer=171000 mSubLayer=0    mToken=WindowToken{714ec09 android.os.BinderProxy@a1ae9d3}
    mViewVisibility=0x0 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x0
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mHasSurface=true isReadyForDisplay()=false mWindowRemovalAllowed=false
    Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
        display=[0,0][1440,720]
        content=[0,0][1440,0] visible=[0,0][1440,0]
        decor=[0,0][0,0]
    mFrame=[0,0][1440,0] last=[0,0][1440,0]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]    Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
     surface=[0,0][0,0]
    ContainerAnimator:
      mLeash=Surface(name=Surface(name=4b25d1a StatusBar)/@0x74e7825 - animation-leash)/@0xd65d49e mAnimationType=32
      Animation: com.android.server.wm.InsetsSourceProvider$ControlAdapter@b57db7f
        ControlAdapter
         mCapturedLeash=Surface(name=Surface(name=4b25d1a StatusBar)/@0x74e7825 - animation-leash)/@0xd65d49e    WindowStateAnimator{5c17a52 StatusBar}:
       mAnimationIsEntrance=true      mSurface=Surface(name=StatusBar)/@0x393894f
      Surface: shown=false layer=0 alpha=1.0 rect=(0.0,0.0) 1440 x 1 transform=(1.0, 0.0, 0.0, 1.0)
      mDrawState=HAS_DRAWN       mLastHidden=true
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][1440,0] mLastClipRect=[0,0][1440,0]
    mLastFreezeDuration=+282ms
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=-1
    isOnScreen=true
    isVisible=false
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= {  }
  Window #3 Window{17fc334 u0 InputMethod}:
    mDisplayId=0 rootTaskId=1 mSession=Session{80b5446 4835:u0a10087} mClient=android.os.BinderProxy@4a46607
    mOwnerUid=10087 showForAllUsers=false package=com.android.inputmethod.pinyin appop=NONE
    mAttrs={(0,0)(fillxwrap) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan forwardNavigation} ty=INPUT_METHOD fmt=TRANSPARENT wanim=0x1030056
      fl=NOT_FOCUSABLE LAYOUT_IN_SCREEN SPLIT_TOUCH DRAWS_SYSTEM_BAR_BACKGROUNDS
      pfl=FIT_INSETS_CONTROLLED
      fitTypes=STATUS_BARS NAVIGATION_BARS
      fitSides=LEFT TOP RIGHT}
    Requested w=1440 h=0 mLayoutSeq=127404
    mIsImWindow=true mIsWallpaper=false mIsFloatingLayer=true mWallpaperVisible=false
    mBaseLayer=151000 mSubLayer=0    mToken=WindowToken{cde643b android.os.Binder@eda5aca}
    mViewVisibility=0x8 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x0
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mTouchableInsets=2 mGivenInsetsPending=false
    touchable region=SkRegion()
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mLastReportedConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined}}
    mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
    Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
        display=[0,0][1440,720]
        content=[0,720][1440,720] visible=[0,720][1440,720]
        decor=[0,0][1440,720]
    mFrame=[0,720][1440,720] last=[0,0][0,0]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]    Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
     surface=[0,0][0,0]
    ContainerAnimator:
      mLeash=Surface(name=Surface(name=17fc334 InputMethod)/@0xb986ed2 - animation-leash)/@0xc83574c mAnimationType=32
      Animation: com.android.server.wm.InsetsSourceProvider$ControlAdapter@94d8395
        ControlAdapter
         mCapturedLeash=Surface(name=Surface(name=17fc334 InputMethod)/@0xb986ed2 - animation-leash)/@0xc83574c    WindowStateAnimator{e569caa InputMethod}:
      mDrawState=NO_SURFACE       mLastHidden=false
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
      mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    isOnScreen=false
    isVisible=false
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= {  }
  Window #4 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}:
    mDisplayId=0 rootTaskId=15 mSession=Session{fbf5011 4610:u0a10115} mClient=android.os.BinderProxy@c0a303c
    mOwnerUid=10115 showForAllUsers=false package=com.test.xxxxx appop=NONE
    mAttrs={(0,0)(fillxfill) sim={adjust=resize forwardNavigation} layoutInDisplayCutoutMode=shortEdges ty=BASE_APPLICATION fmt=TRANSLUCENT wanim=0x1030001 sysuil=true
      fl=KEEP_SCREEN_ON LAYOUT_IN_SCREEN FULLSCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED
      pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED
      vsysui=HIDE_NAVIGATION FULLSCREEN LAYOUT_STABLE LAYOUT_HIDE_NAVIGATION LAYOUT_FULLSCREEN IMMERSIVE_STICKY
      bhv=SHOW_TRANSIENT_BARS_BY_SWIPE
      fitSides=}
    Requested w=1440 h=720 mLayoutSeq=127407
    mBaseLayer=21000 mSubLayer=0    mToken=ActivityRecord{7f6ad57 u0 com.test.xxxxx/com.test.xxxxxClient t15}
    mActivityRecord=ActivityRecord{7f6ad57 u0 com.test.xxxxx/com.test.xxxxxClient t15}
    mAppDied=false    drawnStateEvaluated=true    mightAffectAllDrawn=true
    mViewVisibility=0x0 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x1706
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.1}
    mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.1}
    mHasSurface=true isReadyForDisplay()=true mWindowRemovalAllowed=false
    Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
        display=[0,0][1440,720]
        content=[0,0][1440,720] visible=[0,0][1440,720]
        decor=[0,0][1440,720]
    mFrame=[0,0][1440,720] last=[0,0][1440,720]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]    Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
     surface=[0,0][0,0]
    WindowStateAnimator{418b09b com.test.xxxxx/com.test.xxxxxClient}:
      mSurface=Surface(name=com.test.xxxxx/com.test.xxxxxClient)/@0x7349c38
      Surface: shown=true layer=0 alpha=1.0 rect=(0.0,0.0) 1440 x 720 transform=(1.0, 0.0, 1.0, 0.0)
      mDrawState=HAS_DRAWN       mLastHidden=false
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][1440,720] mLastClipRect=[0,0][1440,720]
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    isOnScreen=true
    isVisible=true
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][1440,0], mVisible=false} }
  Window #5 Window{5e2ca2a u0 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}:
    mDisplayId=0 rootTaskId=1 mSession=Session{a65c98b 802:u0a10101} mClient=android.os.BinderProxy@2dff715
    mOwnerUid=10101 showForAllUsers=false package=com.android.launcher3 appop=NONE
    mAttrs={(0,0)(fillxfill) sim={adjust=pan forwardNavigation} layoutInDisplayCutoutMode=always ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x10302f2
      fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SHOW_WALLPAPER SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
      pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED
      vsysui=LAYOUT_STABLE LAYOUT_HIDE_NAVIGATION LAYOUT_FULLSCREEN
      fitSides=}
    Requested w=720 h=1440 mLayoutSeq=127374
    mBaseLayer=21000 mSubLayer=0    mToken=ActivityRecord{627d118 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t5}
    mActivityRecord=ActivityRecord{627d118 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t5}
    mAppDied=false    drawnStateEvaluated=true    mightAffectAllDrawn=true
    mViewVisibility=0x8 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x700
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_90} s.83}
    mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w360dp h720dp 320dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 720, 1440) mAppBounds=Rect(0, 0 - 720, 1440) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.81}
    mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
    Frames: containing=[0,0][720,1440] parent=[0,0][720,1440]
        display=[0,0][720,1440]
        content=[0,0][720,1440] visible=[0,0][720,1440]
        decor=[0,0][720,1440]
    mFrame=[0,0][720,1440] last=[0,0][720,1440]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]    Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
     surface=[0,0][0,0]
    WindowStateAnimator{c1961d6 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}:
      mDrawState=NO_SURFACE       mLastHidden=true
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][720,1440] mLastClipRect=[0,0][720,1440]
    mOrientationChanging=false configOrientationChanging=true mAppFreezing=false mReportOrientationChanged=true
    mLastFreezeDuration=+181ms
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    mWallpaperX=0.0 mWallpaperY=0.5
    mWallpaperXStep=0.33333334 mWallpaperYStep=1.0
    isOnScreen=false
    isVisible=false
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][720,0], mVisible=true} }
  Window #6 Window{d9974be u0 com.android.systemui.ImageWallpaper}:
    mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@97b1f79
    mOwnerUid=10102 showForAllUsers=false package=com.android.systemui appop=NONE
    mAttrs={(0,0)(1440x2880) gr=TOP START CENTER layoutInDisplayCutoutMode=always ty=WALLPAPER fmt=RGBX_8888 wanim=0x103030e
      fl=NOT_FOCUSABLE NOT_TOUCHABLE LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS SCALED LAYOUT_INSET_DECOR}
    Requested w=720 h=1440 mLayoutSeq=127381
    mIsImWindow=false mIsWallpaper=true mIsFloatingLayer=true mWallpaperVisible=false
    mBaseLayer=11000 mSubLayer=0    mToken=WallpaperWindowToken{fbf8941 token=android.os.Binder@4007828}
    mViewVisibility=0x0 mHaveFrame=true mObscured=false
    mSeq=0 mSystemUiVisibility=0x0
    mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
    mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
    mHasSurface=true isReadyForDisplay()=false mWindowRemovalAllowed=false
    Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
        display=[-10000,-10000][10000,10000]
        content=[0,0][1440,720] visible=[0,0][1440,720]
        decor=[0,0][1440,720]
    mFrame=[0,0][1440,2880] last=[0,0][720,1440]
     cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
    Cur insets: content=[0,0][0,2160] visible=[0,0][0,2160] stable=[0,0][0,2160]    Lst insets: content=[0,0][0,2160] visible=[0,0][0,2160] stable=[0,0][0,2160]
     surface=[0,0][0,0]
    WindowStateAnimator{6f0b1f1 com.android.systemui.ImageWallpaper}:
       mAnimationIsEntrance=true      mSurface=Surface(name=com.android.systemui.ImageWallpaper)/@0x175f1e1
      Surface: shown=false layer=0 alpha=0.0 rect=(-72.0,-1224.0) 720 x 1440 transform=(2.2, 0.0, 2.2, 0.0)
      mDrawState=HAS_DRAWN       mLastHidden=true
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
    mLastFreezeDuration=+135ms
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    mHScale=2.0 mVScale=2.0
    mWallpaperX=0.0 mWallpaperY=0.5
    mWallpaperXStep=0.33333334 mWallpaperYStep=1.0
    mWallpaperZoomOut=0.0
    isOnScreen=true
    isVisible=false
    mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= {  }

  mGlobalConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
  mHasPermanentDpad=false
  mTopFocusedDisplayId=0
  mInputMethodTarget in display# 0 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
  mInputMethodInputTarget in display# 0 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
  inputMethodControlTarget in display# 0 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
  mInTouchMode=true
  mLastDisplayFreezeDuration=+359ms due to Window{d9974be u0 com.android.systemui.ImageWallpaper}
  mLastWakeLockHoldingWindow=Window{2d5f15f u0 com.test.xxxxx/com.test.xxxxxLauncher} mLastWakeLockObscuringWindow=null
  mHighResTaskSnapshotScale=1.0
  SnapshotCache
  mInputMethodWindow=Window{17fc334 u0 InputMethod}
  mTraversalScheduled=false
  mHoldScreenWindow=Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
  mObscuringWindow=null
  mSystemBooted=true mDisplayEnabled=true
  mTransactionSequence=161065
  mDisplayFrozen=false windows=0 client=false apps=0  mRotation=1  mLastOrientation=6
 waitingForConfig=false
  Animation settings: disabled=false window=1.0 transition=0.0 animator=1.0
  PolicyControl.sImmersiveStatusFilter=null
  PolicyControl.sImmersiveNavigationFilter=null
  PolicyControl.sImmersivePreconfirmationsFilter=null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值