关于征求网站建设的意见工地包工接活十大平台
关于征求网站建设的意见,工地包工接活十大平台,大型网站制作怎么样,计算机软件工程师证怎么考Android 的 WMS#xff08;Window Manager Service#xff09;是一个关键组件#xff0c;负责管理窗口的创建、显示、布局和交互等。Window 的操作有两大部分#xff0c;一部分是 WindowManager 来处理#xff0c;一部分是 WMS 来处理#xff0c;如下图所示#xff1a; … Android 的 WMSWindow Manager Service是一个关键组件负责管理窗口的创建、显示、布局和交互等。Window 的操作有两大部分一部分是 WindowManager 来处理一部分是 WMS 来处理如下图所示 WindowManager 中通过 WindowManagerGlobal 创建 ViewRootImpl 也就是 View 的根。在 ViewRootImpl 中完成对 View 的绘制等操作然后通过 IPC 获取到 Session最终通过 WMS 来进行处理。WindowManager 部分的管理流程前面已经介绍这里我们来看一下 WMS 对 Window 的管理。
一、调用流程
1、WM到WMS 我们都知道 Window 的添加最后是通过 ViewRootImpl.addTodisplay 方法来完成的我们先来看一下
ViewRootImpl
源码位置/frameworks/base/core/java/android/view/ViewRootImpl.java
final IWindowSession mWindowSession;public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {synchronized (this) {if (mView null) {……try {……res mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,mTempControls);}……}}
}这里调用了 mWindowSession.addToDisplayAsUser 来完成最后的添加可以看到 IWindowSession 是一个接口类真正实现该接口的是 Session 类。
Session
源码位置/frameworks/base/services/core/java/com/android/server/wm/Session.java
final WindowManagerService mService;Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
} 可以看到最终是通过 WMS 来完成添加的。需要注意的是WMS 并不关心 View 的具体内容他只关心各个应用显示的界面大小、层级值等这些数据到包含在 WindowManager.LayoutParams 中。也就是上面的 atrs 属性。 addWindow 的第二个参数是一个 IWindow 类型这是 App 暴露给 WMS 的抽象实例在 ViewRootImp 中实例化与 ViewRootImpl 一一对应同时也是 WMS 向 App 端发送消息的 Binder 通道。
二、WMS窗口添加
WindowManagerService
源码位置/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsState requestedVisibility,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {Arrays.fill(outActiveControls, null);int[] appOp new int[1];final boolean isRoundedCornerOverlay (attrs.privateFlags PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) ! 0;// 1.检查权限mPolicy的实现类是PhoneWindowManager。int res mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName, appOp);if (res ! ADD_OKAY) {return res;}……synchronized (mGlobalLock) {……// 2.通过displayId获取Window要添加到哪个DisplayContent。final DisplayContent displayContent getDisplayContentOrCreate(displayId, attrs.token);if (displayContent null) {// 没有找到对应的显示屏幕return WindowManagerGlobal.ADD_INVALID_DISPLAY;}……// 3.判断type的窗口类型(100-1999)如果是子类型必须要有父窗口并且父窗口不能是子窗口类型。if (type FIRST_SUB_WINDOW type LAST_SUB_WINDOW) {parentWindow windowForClientLocked(null, attrs.token, false);if (parentWindow null) {// 试图添加带有非窗口令牌的窗口return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;}if (parentWindow.mAttrs.type FIRST_SUB_WINDOW parentWindow.mAttrs.type LAST_SUB_WINDOW) {// 试图添加带有子标记的窗口return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;}}……ActivityRecord activity null;final boolean hasParent parentWindow ! null;// 4.对子窗口使用与父窗口使用的令牌因此我们可以对它们应用相同的策略。WindowToken token displayContent.getWindowToken(hasParent ? parentWindow.mAttrs.token : attrs.token);// 如果这是一个子窗口与父窗口类型相同的检查规则。final int rootType hasParent ? parentWindow.mAttrs.type : type;boolean addToastWindowRequiresToken false;// 5. token为null。if (token null) {if (hasParent) {// 对子窗口使用现有的父窗口令牌。token parentWindow.mToken;} else if (mWindowContextListenerController.hasListener(windowContextToken)) {// 如果用户提供的话尊重窗口上下文令牌final IBinder binder attrs.token ! null ? attrs.token : windowContextToken;final Bundle options mWindowContextListenerController.getOptions(windowContextToken);token new WindowToken.Builder(this, binder, type).setDisplayContent(displayContent).setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow).setRoundedCornerOverlay(isRoundedCornerOverlay).setFromClientToken(true).setOptions(options).build();} else {// 6.且不是应用窗口或者是其他类型的窗口则窗口就是系统类型(例如 Toast)。// 进行隐式创建 WindowToken这说明我们添加窗口时是可以不向WMS提供WindowToken的。final IBinder binder attrs.token ! null ? attrs.token : client.asBinder();token new WindowToken.Builder(this, binder, type).setDisplayContent(displayContent).setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow).setRoundedCornerOverlay(isRoundedCornerOverlay).build();}} else if (rootType FIRST_APPLICATION_WINDOW rootType LAST_APPLICATION_WINDOW) {// 7、判断是否为应用窗口如果是将WindowToken转换为应用程序窗口的ActivityRecord。activity token.asActivityRecord();if (activity null) {// 试图添加带有非应用程序令牌的窗口return WindowManagerGlobal.ADD_NOT_APP_TOKEN;} else if (activity.getParent() null) {// 试图添加具有退出应用程序的窗口return WindowManagerGlobal.ADD_APP_EXITING;} else if (type TYPE_APPLICATION_STARTING) {if (activity.mStartingWindow ! null) {// 试图用已经存在的开始窗口向令牌添加开始窗口return WindowManagerGlobal.ADD_DUPLICATE_ADD;}if (activity.mStartingData null) {// 试图向令牌添加起始窗口但已被清除return WindowManagerGlobal.ADD_DUPLICATE_ADD;}}} else if (rootType TYPE_INPUT_METHOD) {if (token.windowType ! TYPE_INPUT_METHOD) {// 试图添加带有错误令牌的输入法窗口return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}}……// 8.创建WindowState保存窗口的所有状态信息在WMS中WindowState与窗口是一一对应的关系。final WindowState win new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId, session.mCanAddInternalSystemWindow);// 9.判断请求添加窗口的客户端是否已经死亡如果死亡则不会执行下面逻辑。if (win.mDeathRecipient null) {return WindowManagerGlobal.ADD_APP_EXITING;}if (win.getDisplayContent() null) {return WindowManagerGlobal.ADD_INVALID_DISPLAY;}final DisplayPolicy displayPolicy displayContent.getDisplayPolicy();// 10.根据窗口的type类型对窗口的LayoutParams的一些成员变量进行修改。displayPolicy.adjustWindowParamsLw(win, win.mAttrs);win.updateRequestedVisibility(requestedVisibility);// 11.准备将窗口添加到系统中res displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);if (res ! ADD_OKAY) {return res;}……// 12.将WindowState添加到mWindowMap中mWindowMap是各种窗口的集合。mWindowMap.put(client.asBinder(), win);……boolean imMayMove true;// 13.添加窗口。将WindowState添加到对应的WindowToken中实际上就是保存在WindowToken的父类 WindowContainer这样WindowToken就包含了相同组件的WindowState。win.mToken.addWindow(win);}return res;
} WMS 的 addWindow 方法返回的是 addWindow 的各种状态例如添加成功、失败、无效的 display 等这些状态定义在 WindowManagerGloabl 中 。 通过上面的流程App 到 WMS 注册窗口的流程就完了WMS 为窗口创建了用来描述状态的 WindowState接下来就会为新建的窗口显示次序然后再去申请 Surface才算是真正的分配了窗口。 这里对 WMS 的 addWindow 流程做一个总结 首先检查权限 接着从 mRootRootWindowContainer中获取 DisplayContent 如果没有就会根据 displayId 创建一个新的 DisplayContent 接着就是 type 类型的判断如果是子类型就必须要获取到他的父窗口 接着使用 DisplayContent 获取当前或者父窗口获取 token如果为 null 就排除子窗口和其他的窗口剩下的就是可以不用携带 token 的窗口WMS 会隐式的创建窗口 token。如果不等于 null 就判断是应用窗口就将 token 转为 ActivityRecord后面还有一大堆窗口判断只要是不满足就直接 return。 类型判断完成后就会创建 WindowState并且传入 WMS、IWindow、token 等。WindowState 里面保存了窗口的所有信息。WindowState 与窗口一一对应。 接着就执行调用了 WindowState 的 attache 、initAppOpsState 等方法。WindowState 创建完成后就会被添加到 mWindowMap 中可以 IWindow 的 Binder 为 keyWindowState 为 value 添加进去。 最后就是 win.mToken.addWindow(win) 然后将 WindowState 添加到 WindowToken 中。因为 WindowToken 是可以复用的所以这里的关系就是每个 WindowToken 都会保存对应的 WindowState而每个 WindowState 也都会都持有 WindowToekn。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/87216.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!