3 阐述网站建设的步骤过程 9分,wordpress 文章编辑插件,工程建设教育网,广西公司搭建网站公司忽然有一天#xff0c;我想要做一件事#xff1a;去代码中去验证那些曾经被“灌输”的理论。 – 服装… 忽然有一天我想要做一件事去代码中去验证那些曾经被“灌输”的理论。 – 服装学院的IT男 本篇已收录于Activity短暂的一生系列 欢迎一起学习讨论Android应用开发或者WMS VWJB6995 Q707409815 窗口显示流程一共分为以下5篇
窗口显示-流程概览与应用端流程分析
窗口显示-第一步addWindow
窗口显示-第二步relayoutWindow -1
窗口显示-第二步relayoutWindow -2
窗口显示-第三步finishDrawingWindow
正文
在了解完Activity启动流程后现在目标应用的进程已经启动了但是离用户在屏幕上看到Activity下的UI内容还有一段距离。
本文以 WMS 的角度来分析这个流程。
1. 整体流程概述
1.1 涉及模块
WMS 负责管理设备上所有的 Window 所以应用想显示一个 Window 则要通过 WMS 来完成。 而 WMS 毕竟还是上层窗口的内容要显示到屏幕上还需要 SurfaceFlinger 来处理。 整个窗口的显示逻辑会涉及到下图中的三个模块: 应用端: 控制其内部的窗口的添加及 UI 绘制逻辑 WMS 模块: 作为系统窗口管理模块处理应用端的窗口显示逻辑
应用端与 WMS 通信通过匿名 Binder - Session 完成 SurfaceFlinger 模块WMS 只能控制上层的窗口逻辑真正想要在屏幕上显示内容还需要 SurfaceFlinger 来完成
WMS 与 SurfaceFlinger 的通信通过匿名 Binder - Clinent 完成
1.2 流程概览 google 把窗口的显示分为了三个流程 addWindow流程 WMS 是维护系统所有窗口的模块所以应用必须先向 WMS 请求添加窗口这一阶段 WMS 的处理为 为应用端创建对应的 WindowState 并挂载 relayoutWindow流程 addWindow 流程后执行后屏幕上就有新的 WindowState 添加了WMS 也需要对屏幕上所有的窗口执行一遍 layout 来确定各个窗口所在的位置。 而应用端想要绘制 UI 数据则也需要知道自己的窗口大小位置信息并且还需要一个 Surface 来承载 UI 数据。所以这一阶段 WMS 的处理为 为窗口申请 Surface 并返回给应用端计算返窗口的大小位置信息并返回给应用端 finishDrawingWindow流程 执行完上一流程后应用端就可以绘制 UI 了绘制完成后需要将 UI 显示到屏幕上这一步还是需要 WMS 来完成。 通知 SurfaceFlinger 进行显示这个 Surface
在正式看这3个流程之前先看一下应用端内是如何创建一个 Window 的。
2. 应用端–Window创建
应用进程启动后会执行 LaunchActivityItem 和 ResumeActivityItem 这2个事务对应执行到 Activity 的 onCreate 和 onResume 生命周期这其中肯定也涉及到了 Window 相关的操作。
调用链如下
LaunchActivityItem::executeActivityThread::handleLaunchActivityActivityThread::performLaunchActivityInstrumentation::newActivity -- 创建ActivityActivity::attach -- 创建WindowWindow::initWindow::setWindowManagerInstrumentation::callActivityOnCreate Activity::performCreateActivity::onCreate ResumeActivityItem::executeActivityThread::handleResumeActivityActivityThread::performResumeActivity Activity::performResume Instrumentation::callActivityOnResumeActivity::onResume WindowManagerImpl::addView -- 创建ViewRootImplWindowManagerGlobal::addView ViewRootImpl::setView -- 与WMS通信触发窗口的显示逻辑
根据这个调用链可知先执行onResume再执行 addView 而这个 addView 后的逻辑才是触发 Window 显示流程所以执行了 onResume 只是 Activity 可见不代表 View 都显示了这个时候都没触发 WMS 的绘制如果后续的流程中出了问题我们写在 XML 里的布局是不会显示在屏幕上的。以前写App的时候以为执行了onResume屏幕上就显示UI了
这一小节只关心 LaunchActivityItem 部分逻辑看一下应用端创建 Window 的逻辑。 这部分内容和【Activity启动流程-3】末尾内容是重复熟悉的跳过。 2.1 创建Window流程
# ActivityThreadprivate Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {......// 定义windowWindow window null;......// token传递的是ActivityRecord的token// 这里的 window 正常逻辑目前还为nullactivity.attach(...r.token,, window, ...);......}# Activity// 定义Window对象private Window mWindow;final void attach(......) {......// 重点* 1. 创建 PhoneWindowmWindow new PhoneWindow(this, window, activityConfigCallback);// 一些设置mWindow.setWindowControllerCallback(mWindowControllerCallback);// 重点* 2. 将Activity作为回调设置给WindowmWindow.setCallback(this);......// 重点* 3. 设置token为 ActivityRecordmToken token;......// 重点* 4.1 set WindowManagermWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags ActivityInfo.FLAG_HARDWARE_ACCELERATED) ! 0);......// 重点* 4.2 get WindowManagermWindowManager mWindow.getWindowManager();......}public Window getWindow() {return mWindow;} 日常开发中通过 Activity::getWindow 方法返回的其实是 PhoneWindow 这是因为 Window 是个抽象类而 PhoneWindow 是 Window 的唯一子类 创建 PhoneWindow 后有一堆设置这里需要注意 Window::setCallback 方法是将 Activity 设置给了 Window这里有什么用呢 这个是因为 Activity 也实现了 Window.Callback 接口所以能传递 this 这个接口主要是处理 Input 事件的。
Input 事件的传递流程都是先走到 Window因为在 WMS 模块没有 Activity 的概念只有 Window 那么最后是怎么走到 Activity 呢就是这里设置的 setCallback 。当然这个在当前分析的addWindow 流程没有关系但是需要有点印象。 这块token 可以理解为就是 ActivityRecord setWindowManager 和 getWindowManager 这个两个方法写在这乍一看有点矛盾在一个地方 set 又 get 感觉很多余。这是因为这里 set 和 get 返回的对象其实不是同一个对象。
2.2 setWindowManagergetWindowManager
# Window// 应用Tokenprivate IBinder mAppToken;private WindowManager mWindowManager;// wm :WindowManager对象注意下传进来的值// appToken :这个就是AMS中与当前Activity对应的ActivityRecord// appName Activity全类名public void setWindowManager(WindowManager wm, IBinder appToken, String appName,boolean hardwareAccelerated) {// 将ActivityRecord设置给mAppTokenmAppToken appToken;mAppName appName;mHardwareAccelerated hardwareAccelerated;if (wm null) {wm (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);}// 根据强转也能看出 mWindowManager 是 WindowManagerImpl 的类型mWindowManager ((WindowManagerImpl)wm).createLocalWindowManager(this);}public WindowManager getWindowManager() {return mWindowManager;}
这里将传递进来的 wm 强转成 WindowManagerImpl 后调用其 createLocalWindowManager方法。 看的出来这个 wm 就是 WindowManagerImpl 类型。
这里的 WindowManager 其实就是一个接口看命令就 Window 的管理者FrameWork 有很多跨进程通信的类命名方式就是 BP 端叫 XXManager 然后对应的 BN 端就是 XXManagerService 。 但是 这里的 WindowManager 不是这样的他真的就是一个单纯的 java 语言里的接口定义了一些约束然后由 WindowManagerImpl 实现。
另外这里是通过 “getSystemService” 这份方式获取的也容易给人误解他是一个 Service 。其实这个 WindowManager 和其实现类 WindowManagerImpl 与 WindowManagerService 几乎一点关系都没有。
WindowManager 又实现了 ViewManager 接口这个接口中定义了对 View 的三个操作addView removeView updateViewLayout 。
继续看流程返回值想 WindowManagerImpl::createLocalWindowManager 该方法重新创建返回了一个 WindowManagerImpl 对象。 所以说setWindowManager 和 setWindowManager 的不是同一个对象 WindowManagerImpl::createLocalWindowManager 方法如下 # WindowManagerImplpublic WindowManagerImpl createLocalWindowManager(Window parentWindow) {return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);}private WindowManagerImpl(Context context, Window parentWindow,Nullable IBinder windowContextToken) {mContext context;mParentWindow parentWindow;mWindowContextToken windowContextToken;}这边注意的是将 Window 设置给了 mParentWindow。 相当于通过新创建的PhonWindow创建了一个 WindowManagerImpl 作为其mWindowManager的对象。
到这里创建Window相关的就分析完了创建的这个Window其实是 PhoneWindow 。 建议要理清楚 Window, PhoneWindow ,WindowManagerImpl , WindowManager 这几个类的区别和联系不要搞混了 2.3 DecorView
每个 Window 都拥有一个 View
# PhoneWindow.java// This is the top-level view of the window, containing the window decor.// 翻译这是窗户的顶层视图包含窗户装饰。private DecorView mDecor;private void installDecor() {mForceDecorInstall false;if (mDecor null) {mDecor generateDecor(-1);......}......}// 返回 DecorViewOverridepublic final NonNull View getDecorView() {if (mDecor null || mForceDecorInstall) {// 为空就创建installDecor();}return mDecor;}这个 mDecor 是 DecorView 本质上也是一个 View 在 PhoneWindow::generateDecor 方法赋值这个方法有多处会执行最常见的就是我们在 Activity::onCreate 里执行 setContentView 的时候。
# DecorView.java
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {......
}也就是说 Window 通过 mDecor 的变量持有一个 View。
3. 应用端–Window的显示流程
这部分流程由应用端 ResumeActivityItem 开始事务触发最终会执行到 Activity::onResume 生命周期并且也会执行 ViewRootImpl::setView 方法这个方法才是触发 窗口显示的真正逻辑。非Activity窗口也会执行
接下来看一遍代码的执行流程
# ActivityThreadpublic void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {......// 重点* 1. 触发onResumeif (!performResumeActivity(r, finalStateRequest, reason)) {return;}......// 拿到activityfinal Activity a r.activity;......if (r.window null !a.mFinished willBeVisible) {// 将window 设置到 activityRecord中r.window r.activity.getWindow();// 获取DecorViewView decor r.window.getDecorView();// 设置 View 不可见 decor.setVisibility(View.INVISIBLE);// 实际上是WindowManagerImplViewManager wm a.getWindowManager();// 获取参数WindowManager.LayoutParams l r.window.getAttributes();// DecorView设置给Activitya.mDecor decor;// 重点* 2. 设置Activity的windowType,注意这个type才是应用的窗口类型l.type WindowManager.LayoutParams.TYPE_BASE_APPLICATION;......if (a.mVisibleFromClient) {if (!a.mWindowAdded) {// 重点* 3. 执行addView并设置mWindowAddedtruea.mWindowAdded true;wm.addView(decor, l);} else {......}}} else if (!willBeVisible) {......}......if (r.activity.mVisibleFromClient) {// 设置可见r.activity.makeVisible();}......}这段代码信息量还挺多的相关注释已经加在代码上了这里对3个重点单独提一下 performResumeActivity 会触发 onResume 。执行顺序在下面的 addView 之前说明 onResume 只是 Activity 可见而不是 UI 可见 Activity 的 WindowType 为 TYPE_BASE_APPLICATION 1 还有个 TYPE_APPLICATION2 目前已知是在创建 ActivityRecord 时使用 通过 WindowManagerImpl::addView 触发后续逻辑 # WindowManagerImpl// 单例private final WindowManagerGlobal mGlobal WindowManagerGlobal.getInstance()Overridepublic void addView(NonNull View view, NonNull ViewGroup.LayoutParams params) {applyTokens(params);// 这里的mParentWindow 就是PhoneWindowmGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,mContext.getUserId());}这个方法并没有啥复杂的直接调到了 WindowManagerGlobal不过这里也有2个需要注意的点 WindowManagerGlobal 是个单例那就是说一个进程仅此一个 这里将mParentWindow传递了过去上面分析的时候知道这个 mParentWindow 其实就是我们创建的 PhoneWindow # WindowManagerGlobal// 应用内 View 集合UnsupportedAppUsageprivate final ArrayListView mViews new ArrayListView();UnsupportedAppUsage// 应用内 ViewRootImpl 集合private final ArrayListViewRootImpl mRoots new ArrayListViewRootImpl();UnsupportedAppUsage// 应用内 View 参数 集合private final ArrayListWindowManager.LayoutParams mParams new ArrayListWindowManager.LayoutParams();public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {......final WindowManager.LayoutParams wparams (WindowManager.LayoutParams) params;if (parentWindow ! null) {// 重点* 1. 调整 window参数parentWindow.adjustLayoutParamsForSubWindow(wparams);} else {......}// 定义ViewRootImplViewRootImpl root;View panelParentView null;synchronized (mLock) {......// 如果一个窗口执行过 addView 的话再执行就报错int index findViewLocked(view, false);if (index 0) {if (mDyingViews.contains(view)) {// Dont wait for MSG_DIE to make its way through roots queue.mRoots.get(index).doDie();} else {throw new IllegalStateException(View view has already been added to the window manager.);}// The previous removeView() had not completed executing. Now it has.}......IWindowSession windowlessSession null;......// 对于应用来说 windowlessSession 是为null的if (windowlessSession null) {// 重点* 2. 创建ViewRootImplroot new ViewRootImpl(view.getContext(), display);} else {root new ViewRootImpl(view.getContext(), display,windowlessSession);}// 设置参数到 decorViewview.setLayoutParams(wparams);// 重点* 3. 添加到对应集合看得出来在WindowManagerGlobal中这3个对象应该是要一一对应的mViews.add(view);mRoots.add(root);mParams.add(wparams);// do this last because it fires off messages to start doing thingstry {// 重点* 4. ViewRootImpl::setViewroot.setView(view, wparams, panelParentView, userId);} catch (RuntimeException e) {......}}}这段代码最重要的就是做了4件事 Window::adjustLayoutParamsForSubWindow 调整参数比如设置 token title和硬件加速的标志位这3个比较重要的参数 ViewRootImpl 的创建 这个类很重要 WindowManagerGlobal 是进程单例维护了这个应用中多有的 DecorView 而且看得出来定义了3个集合且3个集合的元素是一一对应的 执行 ViewRootImpl::setView 方法传递的 view 就是 PhoneWindow 持有的 DecorView 。 这里是应用端处理窗口的最重要一步也是需要分析的主流程。
3.1 ViewRootImpl::setView
到这里要注意的现在开始就没有对 Window 进行操作了操作的是 DecorView 。
# ViewRootImpl// 与 WMS 通信的 binderfinal IWindowSession mWindowSession;// 对应的DecorViewView mView;public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {synchronized (this) {// 当前第一次执行肯定为nullif (mView null) {// 重点* 将DecorView赋值给 mViewmView view;......mAdded true; // 表示已经addint res; // 定义稍后跨进程add返回的结果// 重点* 非常重要的方法relayoutWindow和finishDrawingWindow都在这触发requestLayout(); InputChannel inputChannel null; // 用于窗口接收inputif ((mWindowAttributes.inputFeatures WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) 0) {inputChannel new InputChannel();}......try {......// 重点* 这里通过binder通信调用WMS的 addWindow方法res mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,mTempControls);......}// 后续流程与addWindow主流程无关但是也非常重要......// 计算一次 Window的尺寸final WindowConfiguration winConfig getConfiguration().windowConfiguration;mWindowLayout.computeFrames(mWindowAttributes, state,displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(),UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH,mInsetsController.getRequestedVisibilities(),getAttachedWindowFrame(), 1f /* compactScale */, mTmpFrames);setFrame(mTmpFrames.frame);......if (res WindowManagerGlobal.ADD_OKAY) {......// 对WMS调用addWindow后的结果判断是什么错误}......// DecorView::getParent 返回的是 ViewRootImpl 的原因view.assignParent(this); ......}}}这个方法是核心方法处理了很多事注释都加上了。为了有一个宏观的印象这里将其触发的各个调用链整理如下
ViewRootImpl::setViewViewRootImpl::requestLayoutViewRootImpl::scheduleTraversals ViewRootImpl.TraversalRunnable::run --- Vsync相关--scheduleTraversalsViewRootImpl::doTraversalViewRootImpl::performTraversals ViewRootImpl::relayoutWindow --- relayoutWindowViewRootImpl::performMeasure --- View绘制三部曲ViewRootImpl::performLayoutViewRootImpl::performDraw ViewRootImpl::createSyncIfNeeded --- 绘制完成finishDrawingWindowSession.addToDisplayAsUser --- addWindow这里要注意虽然看顺序好像 addWindow 流程是在 relayoutWindow 执行前但是因为 doTraversal 是异步的所以还是先执行 addWindow 流程。
可以看到窗口显示的3个流程都在 ViewRootImpl::setView 里触发在看着3个刘之前先看2个变量 mWindowSession 是什么 addToDisplayAsUser 放到第一个参数里的 mWindow 是什么
3.2 mWindowSession 和 mWindow
3.2.1 mWindowSession 是什么
# ViewRootImplfinal W mWindow;final IWindowSession mWindowSession;public ViewRootImpl(Context context, Display display) {this(context, display, WindowManagerGlobal.getWindowSession(),false /* useSfChoreographer */);}public ViewRootImpl(UiContext Context context, Display display, IWindowSession session,boolean useSfChoreographer) {mContext context;mWindowSession session;......mWindow new W(this);......}mWindowSession 是个 Binder 对象用于当前APP进程与WMS跨进程通信 mWindowSession 的赋值在 ViewRootImpl 构造方法 Activity 场景下分析在 WindowManagerGlobal::addView 方法中构造 ViewRootImpl 是2个参数的构造方法所以 mWindowSession 就是 WindowManagerGlobal::getWindowSession 这里提一嘴既然会这么设计那么说明在 Framework 中肯定不是这一种方式获取 Session比如画中画就是另一种以后会提到当前留个印象。 接下来就需要看看 WindowManagerGlobal::getWindowSession 方法。
# WindowManagerGlobalprivate static IWindowSession sWindowSession;UnsupportedAppUsagepublic static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession null) {try {// Emulate the legacy behavior. The global instance of InputMethodManager// was instantiated here.// TODO(b/116157766): Remove this hack after cleaning up UnsupportedAppUsageInputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();IWindowManager windowManager getWindowManagerService();// 赋值sWindowSession windowManager.openSession(new IWindowSessionCallback.Stub() {Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}});} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}// 返回return sWindowSession;}}继续看 WindowManagerService::openSession 。
# WindowManagerServiceOverridepublic IWindowSession openSession(IWindowSessionCallback callback) {return new Session(this, callback);}
# Sessionclass Session extends IWindowSession.Stub implements IBinder.DeathRecipient {final WindowManagerService mService;......Overridepublic int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,requestedVisibilities, outInputChannel, outInsetsState, outActiveControls);}
}所以这里的 WindowManagerGlobal::getWindowSession 返回的就是一个 Session 对象。Session 继承 IWindowSession.Stub并且内部持有 WMS 引用 应用端调用的 Session::addToDisplayAsUser 最终执行的是 WindowManagerService:: addWindow Session 是一个匿名 Binder (没有注册到 ServiceManager)
3.2.2 mWindow是什么
调用 Session::addToDisplayAsUser 方法传递了一个 mWindow 乍一看还以为是把应用端的 Window 对象传递到 WMS 了但是细想也不可能 WMS 模块的业务并不依赖应用端的 Window 对象从上一小节的分析也看到了 mWindow 是 W 类型的变量也是在 ViewRootImpl 的构造方法里赋值的那这个W是什么呢
# ViewRootImplfinal W mWindow;final IWindowSession mWindowSession;public ViewRootImpl(UiContext Context context, Display display, IWindowSession session,boolean useSfChoreographer) {mContext context;mWindowSession session;......mWindow new W(this);......}static class W extends IWindow.Stub {private final WeakReferenceViewRootImpl mViewAncestor;private final IWindowSession mWindowSession;W(ViewRootImpl viewAncestor) {mViewAncestor new WeakReferenceViewRootImpl(viewAncestor);mWindowSession viewAncestor.mWindowSession;}......}ViewRootImpl 下的 mWindow 是其内部类 W 的对象这个 W 继承了 IWindow.Stub那也是用于 binder 通信的 这个 W 是个匿名 Binder 作为 BN 端用于 WMS 调用应用端的相关方法 W 内部有一个 ViewRootImpl 弱引用。
3.2.3 跨进程通信小结
我们知道 WMS 是实名 Binder Service 。从可行性上来说 ViewRootImpl 是完全可以直接通过 Binder 与 WMS 进行直接通信的但是为什么要加这个 IWindowSession 呢 这是因为 WMS 是核心服务系统中有很多地方都需要与其通信所以如果能减少直接与其 Binder 通信的频率也能提升系统效率。
所以 WMS 为每个 APP 端提供了一个匿名实现IWindowSession 处理一些“小请求”减少各个进程直接与 WMS Binder 通信的频率。
这个和 SurfaceFlinger 的设计一致SurfaceFlinger 也提供了一个匿名 Binder Client 。 观点参考-- 《深入理解Android内核设计思想》
4. APP进程处理小结
4.1 流程小结
应用端的流程在 ViewRootImpl::setView 方法中就结束了内部会触发3大流程。 应用进程启动后会执行 2 个事务分别触发到 Activity 的 onCreate 和 onResume 2个常见的生命周期所以这里分为了2个分支。
onCreate 分支 由 LaunchActivityItem 事务触发 handleLaunchActivity 创建 Activity 创建 Window而 Window 是抽象类PhoneWindow 唯一实现类。 执行到 onCreate 生命周期
onResume 分支 由 ResumeActivityItem 事务触发 handleResumeActivity 先触发 onResume 的执行流程 执行 WindowManagerImpl::addView 实际上流程是交给了 WindowManagerGlobal::addView 处理 创建核心类 ViewRootImpl 执行关键函数 ViewRootImpl::setView 这里会触发 WMS 三大流程
3大流程的逻辑还没看但是可以先有个概念:
addWindow 流程 ViewRootImpl 调用 Session::addToDisplayAsUser 触发 WindowManagerService::addWindowrelayoutWindow 流程ViewRootImpl 调用 Session::relayout 触发 WindowManagerService::relayoutWindowfinishDrawingWindow 流程ViewRootImpl 调用 Session::finishDrawing 触发 WindowManagerService::finishDrawingWindow
4.2 关键类小结
给上面分析遇到的一些关键类的知识点单独做个小结 Activity : 是通过反射创建的 通过成员变量 mWindow 持有一个 Window一个应用可以有多个 Activity ,而每个 Activity 的结构都是刚才分析的这些 Activity 被存在 ActivityThread 下的 mActivities 的变量中 PhoneWindowWindow Window 是个抽象类唯一实现是 PhoneWindow 通过成员变量 mDecor 持有一个 View DecorView : 本质上也是一个 View 是开发常说的 “根View” Window 本身是没有内容的真正 UI 载体就是这个 DecorView ViewManager WindowManager : 前面2者都是接口类WindowManagerImpl 实现其接口 WindowManagerImpl WindowManagerImpl 表面上是管理 Window 但是实际业务还是交给了 WindowManagerGlobal WindowManagerGlobal 应用内全局单例是真正的应用内 Window 的总管家但是其实管理的是 Window 下的 DecorView当应用内有 Window 创建后WindowManagerImpl 会调用 WindowManagerGlobal::addView 方法将 DecorView 传递过去WindowManagerGlobal 会为每个 DecorView 创建一个 ViewRootImpl 来管理这棵“View树”内部有3个集合将 Window 的 DecorView 参数 LayoutParams 和新创建的 ViewRootImpl 一一添加到对应的集合中 ViewRootImpl 在 GUI 系统中是应用端的核心类管理一个“View树”负责这个“View树”的绘制等事务同时还需要控制其与 WMS 通信 Session : WMS 为应用端的单独开放的跨进程通信通道 W : 应用端的 Binder Service 会传递到 WMS 中这样 WMS 就可以与 应用端的一个窗口进行通信