在上篇博客中提到WMS的addWindow方法中将Window对应的WindowToken和WindowState挂载到窗口层级树上,它们只是内存中的对象并没有做窗口绘制的动作。这篇博客将讲述Window添加到窗口层级树后,窗口绘制的过程。
1.窗口relayout的过程
在屏幕刷新的时候Choreographer会执行mTraversalRunnable
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
//省略代码
performTraversals();
//省略代码
}
}
最后会在performTraversals方法中执行relayoutWindow方法
private void performTraversals() {
//省略代码
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|| mForceNextWindowRelayout) {
//省略代码
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
//省略代码
} catch (RemoteException e) {
} finally {
//省略代码
}
//省略代码
}
//省略代码
}
relayoutWindow方法又会调用到Session.中
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
//省略代码
if (LOCAL_LAYOUT) {
//省略代码
} else {
//省略代码
relayoutResult = mWindowSession.relayout(mWindow, params,
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,
//省略代码
}
//省略代码
}
Session是跨进调用,Session又会调用到WMS中
@Override
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
//省略代码
int res = mService.relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
outActiveControls, outSyncSeqIdBundle);
//省略代码
return res;
}
到了WMS中这里主要做了两件事情:
1.1.创建绘制使用的WindowSurfaceController
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) {
//省略代码
synchronized (mGlobalLock) {
//省略代码
if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
//省略代码
if (shouldRelayout) {
try {
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
//省略代码
}
}
//省略代码
}
//省略代码
}
createSurfaceControl方法会调用调用到WindowStateAnimator方法中的createSurfaceLocked
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
WindowState win, WindowStateAnimator winAnimator) {
//省略代码
WindowSurfaceController surfaceController;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
surfaceController = winAnimator.createSurfaceLocked();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
//省略代码
}
createSurfaceControl方法会调用调用到
WindowSurfaceController createSurfaceLocked() {
final WindowState w = mWin;
//省略代码
w.setHasSurface(false);
//省略代码
resetDrawState();
//省略代码
try {
//省略代码
mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,
flags, this, attrs.type);
//省略代码
w.setHasSurface(true);
//省略代码
} catch (OutOfResourcesException e) {
//省略代码
} catch (Exception e) {
//省略代码
}
//省略代码
mLastHidden = true;
if (DEBUG) Slog.v(TAG, "Created surface " + this);
return mSurfaceController;
}
1.1.1.设置了mDrawState = DRAW_PENDING
void resetDrawState() {
mDrawState = DRAW_PENDING;
if (mWin.mActivityRecord == null) {
return;
}
if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {
mWin.mActivityRecord.clearAllDrawn();
}
}
1.1.2.创建了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);
}
WindowSurfaceController才是用来绘制的的SurfaceControl.前边的博客中讲过在addChild的过程中Window会创建对应的SurfaceControll这些SurfaceControl都是CONTAINER类型,只有这里的WindowSurfaceController它是BLAST用于绘制的
1.2.计算出Window的摆放位置
performSurfacePlacement方法计算Window的摆放位置
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) {
//省略代码
// 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 */);
//省略代码
}
//省略代码
}
这里方法调用的层级比较多省去中间调用的部分,最后会直接调用到DisplayContent类中的
applySurfaceChangesTransaction方法,执行performLayout,计算出Window的摆放位置
// TODO: Super unexpected long method that should be broken down...
void applySurfaceChangesTransaction() {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
//省略代码
// Perform a layout, if needed.
performLayout(true /* initial */, false /* updateInputWindows */);
//省略代码
}
performLayout方法最后执行到performLayoutNoTrace方法
private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) {
//省略代码
// 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 */);
//省略代码
}
这里通过forAllWindows遍历所有的Window
private final Consumer<WindowState> mPerformLayout = w -> {
//省略代码
if (!gone || !w.mHaveFrame || w.mLayoutNeeded) {
//省略代码
getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);
//省略代码
}
//省略代码
};
forAllWindows遍历所有的Window,mPerformLayout 它是一个WindowState类型的回调函数,在遍历所有Window的时候遇到WindowState时就会执行这个方法。主要会执行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.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
sTmpClientFrames);
//省略代码
}
layoutWindowLw中就会执行computeFrames方法计算中Window的摆放位置。
跨进程调用图
2.finishDrawing的过程
2.1.App进程的入口方法还是performTraversals
boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw();
if (!cancelAndRedraw) {
createSyncIfNeeded();
}
createSyncIfNeeded方法中会调用到reportDrawFinished方法
private void createSyncIfNeeded() {
//省略代码
final int seqId = mSyncSeqId;
mSyncId = mSurfaceSyncer.setupSync(transaction -> {
// Callback will be invoked on executor thread so post to main thread.
mHandler.postAtFrontOfQueue(() -> {
mSurfaceChangedTransaction.merge(transaction);
reportDrawFinished(seqId);
});
});
//省略代码
}
reportDrawFinished方法中通过Session又跨进程调用finishDrawing
private void reportDrawFinished(int seqId) {
if (DEBUG_BLAST) {
Log.d(mTag, "reportDrawFinished " + Debug.getCallers(5));
}
try {
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, seqId);
} catch (RemoteException e) {
Log.e(mTag, "Unable to report draw finished", e);
mSurfaceChangedTransaction.apply();
} finally {
mSurfaceChangedTransaction.clear();
}
}
2.2.SystemServer进程逻辑
public void finishDrawing(IWindow window,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);
}
Session中调用WMS的finishDrawingWindow
void finishDrawingWindow(Session session, IWindow client,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
//省略代码
try {
synchronized (mGlobalLock) {
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 {
//省略代码
}
}
2.2.1.执行WindowState的finishDrawing方法
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
//省略代码
final boolean layoutNeeded =
mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
//省略代码
}
调用WindowStateAnimator的finishDrawingLocked
boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
boolean forceApplyNow) {
//省略代码
boolean layoutNeeded = false;
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);
}
mDrawState = COMMIT_DRAW_PENDING;
layoutNeeded = true;
}
//省略代码
return layoutNeeded;
}
这里最主要的时将mDrawState 的状态由DRAW_PENDING改变为COMMIT_DRAW_PENDING,并返回为true
2.2.2.执行mWindowPlacerLocked.requestTraversal(),这方方法经过多层调用又会执行到DisplayContent.java中的applySurfaceChangesTransaction方法
// TODO: Super unexpected long method that should be broken down...
void applySurfaceChangesTransaction() {
//省略代码
// Perform a layout, if needed.
performLayout(true /* initial */, false /* updateInputWindows */);
//省略代码
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
try {
forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
prepareSurfaces();
//省略代码
}
2.2.2.1.前边讲过performLayout会计算出Window的摆放位置
2.2.2.2.在relayoutWindow的时候执行applySurfaceChangesTransaction方法时由于mDrawState = DRAW_PENDING导致forAllWindows执行mApplySurfaceChangesTransaction回调时退出,这次执行到这里时mDrawState = COMMIT_DRAW_PENDING就会往下执行
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
//省略代码
// Moved from updateWindowsAndWallpaperLocked().
if (w.mHasSurface) {
// Take care of the window being ready to display.
final boolean committed = winAnimator.commitFinishDrawingLocked();
//省略代码
}
}
//省略代码
};
WindowState还是执行到了WindowStateAnimator的commitFinishDrawingLocked
// This must be called while inside a transaction.
boolean commitFinishDrawingLocked() {
if (DEBUG_STARTING_WINDOW_VERBOSE &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
+ drawStateToString());
}
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
ProtoLog.i(WM_DEBUG_ANIM, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s",
mSurfaceController);
mDrawState = READY_TO_SHOW;
boolean result = false;
final ActivityRecord activity = mWin.mActivityRecord;
if (activity == null || activity.canShowWindows()
|| mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = mWin.performShowLocked();
}
return result;
}
这里可以看到当mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW的时候就退出了,这次mDrawState == COMMIT_DRAW_PENDING就不会退出了,会继续往下执行,mDrawState 改编为 READY_TO_SHOW;
由于我们添加的是一个System Window不是Activity所这里会执行mWin.performShowLocked()
boolean performShowLocked() {
//省略代码
if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
return false;
}
//省略代码
mWinAnimator.mDrawState = HAS_DRAWN;
//省略代码
}
return true;
}
至此整个Window的mDrawState 已经走到了HAS_DRAWN状态,完成了Window的finishDrawing操作
Window的finishDrawing方法调用逻辑图3.prepareSurfaces过程
prepareSurfaces是在完成finishDrawing后mDrawState = HAS_DRAWN时在DisplayContent.java的applySurfaceChangesTransaction方法中执行的
void applySurfaceChangesTransaction() {
//省略代码
prepareSurfaces();
//省略代码
}
DisplayContent.java的prepareSurfaces看似什么都没做,其实它调用了super的prepareSurfaces
@Override
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);
}
}
DisplayContent–>DispalyArea.Dimmable–>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();
}
}
其实是调用到WindowState的prepareSurfaces方法
@Override
void prepareSurfaces() {
mIsDimming = false;
applyDims();
updateSurfacePositionNonOrganized();
// Send information to SurfaceFlinger about the priority of the current window.
updateFrameRateSelectionPriorityIfNeeded();
updateScaleIfNeeded();
mWinAnimator.prepareSurfaceLocked(getSyncTransaction());
super.prepareSurfaces();
}
最后是调用到WindowStateAnimator的prepareSurfaceLocked
void prepareSurfaceLocked(SurfaceControl.Transaction t) {
final WindowState w = mWin;
//省略代码
if (w.isParentWindowHidden() || !w.isOnScreen()) {
//省略代码
} else if (mLastAlpha != mShownAlpha
|| mLastHidden) {
//省略代码
boolean prepared =
mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);
if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) {
if (showSurfaceRobustlyLocked(t)) {
//省略代码
}
}
}
//省略代码
}
最重要的是调用showSurfaceRobustlyLocked方法
*/
private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
boolean shown = mSurfaceController.showRobustly(t);
if (!shown)
return false;
t.merge(mPostDrawTransaction);
return true;
}
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);
t.show(mSurfaceControl);
if (mAnimator.mIsWallpaper) {
EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE,
mAnimator.mWin.getDisplayId(), 1 /* request shown */);
}
return true;
}
这里最终调用t.show(mSurfaceControl)方法交给了SurfaceFlinger来绘制
prepareSurfaces过程的方法调用图