wordpress宝塔CPU爆满,如何做营销型手机网站优化,品牌推广岗位,快三直播十大平台直播间在安卓源码的设计中#xff0c;将将屏幕分为了37层#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析#xff0c;整理出以下几篇。
【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树
【Android 13源码分析】WindowCon…在安卓源码的设计中将将屏幕分为了37层不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析整理出以下几篇。
【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树
【Android 13源码分析】WindowContainer窗口层级-2-构建流程
【Android 13源码分析】WindowContainer窗口层级-3-实例分析
【Android 13源码分析】WindowContainer窗口层级-4-Surface树
本篇为第四篇前面三篇已经将Android窗口树介绍完了但是我们知道安卓真正控制显示的是在SurfaceFlinger层难道说SurfaceFlinger层也有这么一个窗口树吗如果有Framework层构建窗口树的代码这么复杂难道SurfaceFlinger也有这么一段复杂的逻辑吗
首先回答第一个问题SurfaceFlinger层也有这么一个窗口树严格来说是SurfaceFlinger也有一个对应的Layer树。 这是使用Winscope工具看到的当前屏幕信息可以看到在SurfaceFlinger层也有一个和窗口树应用的层级关系并且在WindowState层下面还多了一级多出来的这层右边的属性中有一项“isBuffLayer true”。
先以黑盒的形式补充几个Surface相关的知识点对这块有了解的可跳过。
1. Surface知识黑盒概念 触发创建Surface时就会触发创建出一个Layer所以Surface和Layer是一一对应的只不过在framework层侧重Surface在SurfaceFlinger侧重Layer。 应用层只要有Surface就可以将View的数据绘制保存到Surface中也就可以显示到屏幕上 Layer有多种类型最常见的是“容器类型”和“buff类型”只有“buff类型”的Layer才能保存UI数据。
2 容器类型的创建
前面几篇介绍窗口树的时候知道那些类其实都是“容器”作为容器他们本身是没有UI数据的真正有显示数据的就是 “isBuffLayer true”的这层Layer。
再回答第二个问题SurfaceFlinger没有这么复杂构建Layer树的逻辑因为只要Framework创建一个“容器”类的同时也触发创建一个Surface这样SurfaceFlinger层就也能同步构造出一个LayerSurface树。
2.1 DisplayContent的Surface构建
首先看一下 屏幕DisplayContent对应的Surface是怎么创建的。
在构建流程开始的时候就为 DisplayContent的创建了Surface代码如下 # DisplayContentprivate void configureSurfaces(Transaction transaction) {// 构建一个SurfaceControlfinal SurfaceControl.Builder b mWmService.makeSurfaceBuilder(mSession).setOpaque(true).setContainerLayer() // 设置为容器类型的Layer.setCallsite(DisplayContent);// 设置名字后构建 Display 0 nameXXXmSurfaceControl b.setName(getName()).setContainerLayer().build();// 设置策略并构建显示区域层次结构if (mDisplayAreaPolicy null) {// WMS的getDisplayAreaPolicyProvider方法按返回 DisplayAreaPolicy.Provider// 然后其 instantiate的实现 目前只有DisplayAreaPolicy的内部类DefaultProvidermDisplayAreaPolicy mWmService.getDisplayAreaPolicyProvider().instantiate(mWmService, this /* content */, this /* root */,mImeWindowsContainer);}......}在构建窗口树源码分析的时候知道DisplayContent::configureSurfaces 是在 DisplayContent构造方法里执行的也就是说在构建窗口树的时候创建了DisplayContent容器的同时也创建好了对应的Surface这是第一个映射关系。 注意build的时候 setContainerLayer这个设置 将其设置为容器类型的Layer 2.2 其他容器Surface的创建与挂载
层级树其他的各个容器创建的也会触发创建出对应的一个Surface具体的调用链如下 WindowContainer::addChildWindowContainer::setParentWindowState::onParentChangedWindowContainer::createSurfaceControlWindowContainer::setInitialSurfaceControlPropertiesSurfaceControl.Builder::buildSurfaceControl::init调用链从WindowContainer::addChild 开始是因为每个容器类创建的时候都会挂载到父节点下挂载的方式也就是执行WindowContainer::addChild方法添加到父容器的孩子集合下。
以一个应用的Task容器创建挂载为例 假设其他窗口树已经构建好(也已经有了一个对应的Layer树暂时不知道是怎么来的没关系稍后就明白了)这个时候应用启动了肯定是需要创建一个TaskTask创建好后是还是一个单独的容器这个时候会执行 WindowContainer::addChild 和 WindowContainer::setParent方法执行完后Task就挂着到窗口树上了。
先看一下这2个方法的代码 # WindowContainer// 当前容器的孩子容器集合protected final WindowListE mChildren new WindowListE();CallSuperprotected void addChild(E child, ComparatorE comparator) {......// 1. 添加到集合中也就是挂载if (positionToAdd -1) {mChildren.add(child);} else {mChildren.add(positionToAdd, child);}// Set the parent after weve actually added a child in case a subclass depends on this.// 2. 调用孩子容器设置父节点的方法child.setParent(this);}首先将子容器添加到 mChildren 集合中然后调用子容器的 setParent 方法。 这么2步执行后 孩子与父容器就有绑定关系了也就是成功挂载到了父节点执行。细品其实就是java集合操作 先看一下这2个方法的代码 # WindowContainer// 当前容器的孩子容器集合protected final WindowListE mChildren new WindowListE();CallSuperprotected void addChild(E child, ComparatorE comparator) {......// 1. 添加到集合中也就是挂载if (positionToAdd -1) {mChildren.add(child);} else {mChildren.add(positionToAdd, child);}// Set the parent after weve actually added a child in case a subclass depends on this.// 2. 调用孩子容器设置父节点的方法child.setParent(this);}首先将子容器添加到 mChildren 集合中然后调用子容器的 setParent 方法。 这么2步执行后 孩子与父容器就有绑定关系了也就是成功挂载到了父节点执行。细品其实就是java集合操作
setParent 方法具体代码如下 # WindowContainer// 父节点private WindowContainerWindowContainer mParent null;final protected void setParent(WindowContainerWindowContainer parent) {if (parent null) {Slog.d(TAG, setParent old mParent ,new parent ,this window this ,callers Debug.getCallers(6));}final WindowContainer oldParent mParent;mParent parent;......onParentChanged(mParent, oldParent);......}现在 Task 就成功找到组织了挂着到窗口树上了。 但是这个时候SurfaceFlinger那边还是没变化的所以继续看后续流程。 # WindowContainervoid onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,PreAssignChildLayersCallback callback) {super.onParentChanged(newParent, oldParent);// 正常肯定是有父节点的if (mParent null) {return;}if (mSurfaceControl null) {// If we dont yet have a surface, but we now have a parent, we should// build a surface.// 父亲有了但是自身还为null则触发创建自身Surface的逻辑createSurfaceControl(false /*force*/);} else {......// 有则进行 reparentreparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl);}......}// 重点触发Surface的创建void createSurfaceControl(boolean force) {setInitialSurfaceControlProperties(makeSurface());}注释比较详细就不多说了这里肯定是走createSurfaceControl()逻辑然后注意makeSurface()方法会创建出Surface然后再调用setInitialSurfaceControlProperties。先看 makeSurface 方法 # WindowContainer// 当前容器的Surfaceprotected SurfaceControl mSurfaceControl;SurfaceControl.Builder makeSurface() {// 拿到父节点调用makeChildSurfacefinal WindowContainer p getParent();// 传递当前也就是Taskreturn p.makeChildSurface(this);}SurfaceControl.Builder makeChildSurface(WindowContainer child) {// 拿到父亲final WindowContainer p getParent();// Give the parent a chance to set properties. In hierarchy v1 we rely// on this to set full-screen dimensions on all our Surface-less Layers.// 调用父亲的makeChildSurface方法再调用setParent return p.makeChildSurface(child).setParent(mSurfaceControl);}这里方法虽然不多但是逻辑有点绕做一下解释 是子容器调用的 makeChildSurface 方法那子容器类就是 Task父容器就是 DefaultTaskDisplayArea 执行 父容器 makeChildSurface方法的时候又调用了getParent 获取父容器执行 makeChildSurface眉头一皱事情并不简单这是开始递归了。 先不管递归总之肯定的是 makeChildSurface方法不管怎么递归返回的还是一个SurfaceControl.Builder然后调用setParent将DefaultTaskDisplayArea的Surface设置为其父节点。 这样一来结果就是 Task调用 父容器的makeChildSurface后创建出了一个Surface并且挂载到了父容器DefaultTaskDisplayArea的下面。 知道结果后还是要弄清楚 递归方法是怎么创建 Task对应的Surface的 对于递归调用最终要的就是找到递归结束的条件当前这个递归结束的条件就是 DisplayContent 类重写了makeChildSurface方法也就是说调到 DisplayContent::makeChildSurface 就意味着递归的结束。 DisplayContent作为一个屏幕的最底层的容器肯定是会调用到的毕竟 DefaultTaskDisplayArea也是挂载在这个树上的。 所以现在来看看 DisplayContent::makeChildSurface方法 # DisplayContentOverrideSurfaceControl.Builder makeChildSurface(WindowContainer child) {SurfaceSession s child ! null ? child.getSession() : getSession();// 创建一个容器类型 Surface的Builderfinal SurfaceControl.Builder b mWmService.makeSurfaceBuilder(s).setContainerLayer();if (child null) {return b;}// 设置容器名return b.setName(child.getName()).setParent(mSurfaceControl);}这里的参数 child 就是Task, 首先创建一个容器类型 SurfaceControl.Builder 设置name当前场景是把Task的名字设置过去 然后设置一下父亲为DisplayContent的Surface 这里要注意这里设置父节点最终是无效的会被覆盖掉因为上面分析看到了把 DefaultTaskDisplayArea设置为Task父容器。从代码的执行顺序上来说DisplayContent的这次setParent先执行会被后面的覆盖掉。 从结果来看Task也确实是挂在DefaultTaskDisplayArea下的。 不可能每个容器都直接作为DisplayContent的子节点 调用链执行完了SurfaceFlinger层也创建并且挂载好了Task的Surface。 到这里Framework层的窗口树 SurfaceFlinger的Surface树构建的差不多了但是手机上还是不会有内容的为什么呢 因为这些都是 “容器”真正的显示需要有Buff类型的Surface。 再看一次这个图 对应的窗口树到了WindowState就结束了 SurfaceFliner 这边可以看到WindowState下还有一个节点这个节点才是真正有UI数据的 Layer。 需要体会一下区别 在Activity启动流程中时执行到目标应用进程创建时会触发Task和ActivityRecord创建和挂载。 这个时候WindowState还没出现另外到这一步Activity的onCreate也没执行到所以界面上肯定是没有UI显示的。
Activity进程创建后会先执行[addWindow流程]触发 WindowState的创建和挂载但是这步执行完也还是没有画面的 因为WindowState也是一个“容器”。 真正触发显示图层创建的是在【relayoutWindow】流程具体的流程不是当前的主题目前只关注【relayoutWindow】流程中“Buff”类型图层的创建。
3.1 流程概览
这里才是第一次执行relayoutWindow 创建真正显示的surface的地方 relayoutWindow的调用链如下
WindowManagerService::relayoutWindowWindowManagerService::createSurfaceControlWindowStateAnimator::createSurfaceLocked -- 创建“Buff” 类型SurfaceWindowStateAnimator::resetDrawState -- 设置窗口状态为DRAW_PENDINGWindowSurfaceController::initSurfaceControl.Builder::buildSurfaceControl::initWindowSurfaceController::getSurfaceControl -- 给应用端Surface赋值开始撸代码
# WindowManagerService 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) {......result createSurfaceControl(outSurfaceControl, result, win, winAnimator);......}createSurfaceControl 方法有4个参数
outSurfaceControl: WMS创建好一个Surface后还需要返回给应用端用于View的绘制就是通过这个参数由参数命名也可以知道这是一个“出参”。result 方法执行结果win: 当前窗口对应的WindowState,稍后创建Surface会挂载到这个WindowState节点之下winAnimatorWindowStateAnimator对象管理窗口状态和动画稍后通过其内部方法创建Surface
# WindowManagerServiceprivate int createSurfaceControl(SurfaceControl outSurfaceControl, int result,WindowState win, WindowStateAnimator winAnimator) {// 1. 创建WindowSurfaceController对象WindowSurfaceController surfaceController;try {// 2. 创建“Buff”类型SurfaceTrace.traceBegin(TRACE_TAG_WINDOW_MANAGER, createSurfaceControl);surfaceController winAnimator.createSurfaceLocked();} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}if (surfaceController ! null) {// 3. 出参给应用端surfaceController.getSurfaceControl(outSurfaceControl);// 打印日志outSurfaceControl复制到了framework的值ProtoLog.i(WM_SHOW_TRANSACTIONS, OUT SURFACE %s: copied, outSurfaceControl);}......return result;}
这个方法主要有三步都是围绕着 WindowSurfaceController 来的 先创建出一个WindowSurfaceController 对象 surfaceController 通过WindowStateAnimator::createSurfaceLocked 对 surfaceController 赋值根据方法名猜测是创建了一个Surface 通过 WindowSurfaceController::getSurfaceControl,给应用端 Surface 赋值
这么看来重点是在第二步 WindowStateAnimator::createSurfaceLocked 是如何创建Surface的。
# WindowStateAnimatorWindowSurfaceController mSurfaceController;// WindowState的状态int mDrawState;WindowSurfaceController createSurfaceLocked() {final WindowState w mWin;if (mSurfaceController ! null) {return mSurfaceController;}w.setHasSurface(false);// 打印窗口状态ProtoLog.i(WM_DEBUG_ANIM, createSurface %s: mDrawStateDRAW_PENDING, this);// 重点* 1. 重置窗口状态resetDrawState();......// 重点* 2. 创建WindowSurfaceControllermSurfaceController new WindowSurfaceController(attrs.getTitle().toString(), format,flags, this, attrs.type);......return mSurfaceController;}这里有2个重点 设置窗口状态为 DRAW_PENDING 创建Surface
3.2 设置窗口状态–DRAW_PENDING
# WindowStateAnimatorvoid resetDrawState() {// 设置windowState状态为DRAW_PENDINGmDrawState DRAW_PENDING;if (mWin.mActivityRecord null) {return;}if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {mWin.mActivityRecord.clearAllDrawn();}}WindowState有很多状态以后会单独说这里需要注意
WindowState状态是保存在WindowStateAnimator中WindowStateAnimator::createSurfaceLocked方法会将WindowState状态设置为DRAW_PENDING表示等待绘制。
3.3 创建“Buff”类型Surface
继续回到主流程看看 WindowSurfaceController 的构造方法
# WindowSurfaceControllerSurfaceControl mSurfaceControl;WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,int windowType) {mAnimator animator;// 1. 也会作为Surface的nametitle name;mService animator.mService;// 2. 拿到WindowStatefinal WindowState win animator.mWin;mWindowType windowType;mWindowSession win.mSession;Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, new SurfaceControl);// 3. 重点* 构建Surface也是通过makeSurface 方法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);// 高版本都为BLASTif (useBLAST) {// 4. 重点* 设置为“Buff”图层b.setBLASTLayer();}// 触发buildmSurfaceControl b.build();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}这个方法有4个点
第一个参数传递的字符串最终也会作为Surface的name获取到WindowState对象后面会设置为创建Surface的父节点构建出一个Surface对象 注意name和 父节点的设置。 另外可以知道也是通过makeSurface()方法构建的 这个方法在 2.1小结看到是构建出一个“容器”类型的Surface。将Surface设置为“Buff”类型这个非常重要因为上一步默认还是“容器”类型所以需要设置成“Buff”类型再后面就是build出一个Surface了
那么到这里Surface的创建就完成了这里可能有的人如果对Surface知识不太清楚的话会比较迷糊WindowSurfaceControllerSurfaceControllerSurface到底是什么关系这个不在当前流程的重点暂且理解为同级吧有WindowSurfaceController就可以拿到内部的SurfaceController而SurfaceController又可以获取到Surface。
3.4 返回Surface到应用端
最后再来看一下 WMS这边创建好后的Surface是如何设置给应用端的。
应用端View的绘制信息都是保存到Surface上的因为必定要有一个Buff类型的Surface也就是上面流程中创建的这个Surface。
应用端的ViewRootImpl触发WMS的relayoutWindow会传递一个出参 outSurfaceControl过来 现在WMS会通过以下方法将刚刚创建好是Surface传递到应用端。
这样一来应用端就有了可以保持绘制数据的Surface然后就可以执行 View::draw。
# WindowSurfaceControllervoid getSurfaceControl(SurfaceControl outSurfaceControl) {// 将framework层的SurfaceControl copy给应用层传递过来的outSurfaceControloutSurfaceControl.copyFrom(mSurfaceControl, WindowSurfaceController.getSurfaceControl);}