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) {
//ignore
//根据client找到对应的WindowState
final WindowState win = windowForClientLocked(session, client, false);
//ignore
// Create surfaceControl before surface placement otherwise layout will be skipped
// (because WS.isGoneForLayout() is true when there is no surface.
if (shouldRelayout) {
try {
//创建对应的window需要的SurfaceControl,传递回应用,应用用他进行绘制
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
//ignore
}
}
//调用最核心的performSurfacePlacement进行相关的layout操作
// 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 */);
//ignore
if (!win.isGoneForLayout()) {
win.mResizedWhileGone = false;
}
//把相关config数据填回去
win.fillClientWindowFramesAndConfiguration(outFrames, mergedConfiguration,
false /* useLatestConfig */, shouldRelayout);
//把相关inset数据设置回去
outInsetsState.set(win.getCompatInsetsState(), win.isClientLocal());
//ignore
getInsetsSourceControls(win, outActiveControls);
}
Binder.restoreCallingIdentity(origId);
return result;
}
主要就有2个最关键步骤:
1、创建对应Window的SurfaceControl
2、计算出对应的window区域等,把inset和config传递回去
更多内容qqun:422901085 https://ke.qq.com/course/5992266#term_id=106217431
1、创建对应Window的SurfaceControl,这个之前图层结构树部分有讲解
调用是createSurfaceControl:
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");
surfaceController = winAnimator.createSurfaceLocked();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (surfaceController != null) {
surfaceController.getSurfaceControl(outSurfaceControl);
ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win);
outSurfaceControl.release();
}
return result;
}
这里首先又调用到了winAnimator.createSurfaceLocked();
WindowSurfaceController createSurfaceLocked() {
//ignore
mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,
flags, this, attrs.type);
//ignore
}
调用到了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");//此时其实还是属于Container,因为DisplayerContent创建
final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);
if (useBLAST) {
b.setBLASTLayer();//非常关键,变成非Container
}
mSurfaceControl = b.build();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
2、计算出对应的window区域等,把inset和config传递回去
这个部分最关键方法就是 mWindowPlacerLocked.performSurfacePlacement(true /* force */);
下面来对他进行详细分析:
final void performSurfacePlacement(boolean force) {
119 if (mDeferDepth > 0 && !force) {
120 mDeferredRequests++;
121 return;
122 }
123 int loopCount = 6;
124 do {
125 mTraversalScheduled = false;
126 performSurfacePlacementLoop();//调用performSurfacePlacementLoop
127 mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
128 loopCount--;
129 } while (mTraversalScheduled && loopCount > 0);
130 mService.mRoot.mWallpaperActionPending = false;
131 }
performSurfacePlacementLoop
private void performSurfacePlacementLoop() {
//ignore
mService.mRoot.performSurfacePlacement();
//ignore
}
这里会调用到RootWindowContainer的performSurfacePlacement
void performSurfacePlacement() {
782 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
783 try {
784 performSurfacePlacementNoTrace();
785 } finally {
786 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
787 }
788 }
接下来又到performSurfacePlacementNoTrace,接下来又会调用到最关键的applySurfaceChangesTransaction方法:
private void applySurfaceChangesTransaction() {
//ignore
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(mDisplayTransaction);
SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
}
这里又会调用到DisplayContent 的applySurfaceChangesTransaction
void applySurfaceChangesTransaction() {
//执行布局相关
// Perform a layout, if needed.
performLayout(true /* initial */, false /* updateInputWindows */);
pendingLayoutChanges = 0;
//判断布局策略
mDisplayPolicy.beginPostLayoutPolicyLw();
forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
//
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
try {
//挨个迭代每个窗口执行mApplySurfaceChangesTransaction
forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
//做绘制前最后一些处理
prepareSurfaces();
//ignore
}
这里我们这次重点是performLayout,其他后面几篇blog再讲解
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;
}
clearLayoutNeeded();
if (DEBUG_LAYOUT) {
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).
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.
forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
// Window frames may have changed. Tell the input dispatcher about it.
mInputMonitor.setUpdateInputWindowsNeededLw();
if (updateInputWindows) {
mInputMonitor.updateInputWindowsLw(false /*force*/);
}
}
最后也是循环遍历层级结构树的每个windowstate进行mPerformLayout的执行
private final Consumer<WindowState> mPerformLayout = w -> {
//ignore
getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);
//ignore
};
调用是DisplayPolicy.java的layoutWindowLw
public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
//ignore
mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,
win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
sTmpClientFrames);
win.setFrames(sTmpClientFrames, win.mRequestedWidth, win.mRequestedHeight);
}
这里调用是WindowLayout.computeFrames
具体computeFrames的计算代码较长,主要就是会根据系统的inset情况来决定,比如statusbar,和navigationbar等,然后给app一个合适的frame