mDeferredRequests++;
return;
}
int loopCount = 6;
do {
mTraversalScheduled = false;
performSurfacePlacementLoop();
mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
loopCount–;
} while (mTraversalScheduled && loopCount > 0);
mService.mRoot.mWallpaperActionPending = false;
}
其中,mDeferDepth
表示延迟进行布局的计数器,mDeferredRequests
表示在延迟布局时,请求进行Surface Placement的次数,这两个值都是为了优化性能而添加,当系统状态发生了多个变化时,会延迟摆放过程,直到变化完成后一次性进行。
这里还设置了一个循环体,遍历执行内部的 performSurfacePlacementLoop()
方法,最多执行6次。
mTraversalScheduled表示是否有收到执行遍历的请求,它只有在一个地方设置为true:
// frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
void requestTraversal() {
// 设置为true
mTraversalScheduled = true;
if (mDeferDepth > 0) {
mDeferredRequests++;
return;
}
// 在andriod.animation线程进行
mService.mAnimationHandler.post(mPerformSurfacePlacement);
}
performSurfacePlacementLoop()如下:
// frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
private void performSurfacePlacementLoop() {
// 如果处于窗口摆放过程,直接返回
if (mInLayout) {
return;
}
// 如果defaultDisplay.mWaitingForConfig为true表示DisplayContent在等待更新配置,此时不进行窗口放置,待配置完成后再进行
final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
if (defaultDisplay.mWaitingForConfig) {
return;
}
// 表示在进行窗口摆放
mInLayout = true;
…
try {
// 进入RootWindowContainer中
mService.mRoot.performSurfacePlacement();
// 重置值
mInLayout = false;
// 是否DisplayContent仍然需要进行放置操作
if (mService.mRoot.isLayoutNeeded()) {
if (++mLayoutRepeatCount < 6) {
requestTraversal();
} else {
mLayoutRepeatCount = 0;
}
} else {
mLayoutRepeatCount = 0;
}
} catch (RuntimeException e) {}
}
这个方法中,mInLayout表示是否在进行窗口Surface的摆放工作,这里将会进入RootWindowContainer#performSurfacePlacement()
方法,从WMS树结构的根节点开始,开始对WMS树进行遍历。
2.RootWindowContainer#performSurfacePlacementNoTrace()中原子操作进行定位
在这个方法中,在Transaction对象上进行原子操作,进行所有窗口的定位:
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
void performSurfacePlacementNoTrace() {
…
// 开启事务
mWmService.openSurfaceTransaction();
try {
// 执行原子操作
applySurfaceChangesTransaction();
} catch (RuntimeException e) {
} finally {
// 提交事务
mWmService.closeSurfaceTransaction(“performLayoutAndPlaceSurfaces”);
}
…
}
这个方法中:
-
- 首先,通过WMS#openSurfaceTransaction()方法,获取一个SurfaceControl#sGlobalTransaction对象;
-
- 然后执行applySurfaceChangesTransaction()进行所有SurfaceControl的遍历;
-
- 最后通过WMS#closeSurfaceTransaction()方法,对sGlobalTransaction上的一系列SurfaceControl进行提交,发送给SurfaceFlinger。整个过程中,所有SurfaceControl的原子操作就是通过sGlobalTransaction来进行。
我们接着看applySurfaceChangesTransaction()方法,这里会每个DisplayContent进行遍历:
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
private void applySurfaceChangesTransaction() {
mHoldScreenWindow = null;
mObscuringWindow = null;
final DisplayContent defaultDc = mWmService.getDefaultDisplayContentLocked(); // 默认DisplayContent
final DisplayInfo defaultInfo = defaultDc.getDisplayInfo(); // 默认DisplayContent对应逻辑屏信息
final int defaultDw = defaultInfo.logicalWidth; //逻辑屏宽高
final int defaultDh = defaultInfo.logicalHeight;
…
//遍历每个DisplayContent,对每个Display中的Surface进行Placement操作
final int count = mChildren.size();
for (int j = 0; j < count; ++j) {
final DisplayContent dc = mChildren.get(j);
dc.applySurfaceChangesTransaction();
}
// 通知DMS进行Display侧的属性调整
mWmService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
// 将mDisplayTransaction合并到sGlobalTransaction上
SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
}
这个方法中,通过mDisplayTransaction对象对几个特殊SurfaceControl进行了操作。mDisplayTransaction是一个单独的事务对象,专门用于对Display相关的原子操作,当完成DisplayContent#applySurfaceChangesTransaction()后,会合并到全局Transaction对象中。
3.DisplayContent#applySurfaceChangesTransaction()
接下来会遍历DisplayContent,执行每个DisplayContent的applySurfaceChangesTransaction()方法,DisplayContent对象和逻辑屏是一对一关系,代表一个逻辑屏的显示容器。
DisplayContent#applySurfaceChangesTransaction()方法如下:
// frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
void applySurfaceChangesTransa