「安卓framework基础篇11」从WMS到BufferQueue第四篇 - 探索APP的窗口是如何挂载到WMS层级树上(基于AOSP13)
APP进程的事件循环监听到有onResume状态变更请求消息后,会调用ActivityThread.java的handleResumeActivity方法处理消息:
@Overridepublic void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {// 省略// 这里会调用Activiy的onResume方法if (!performResumeActivity(r, finalStateRequest, reason)) {return;}// 这里用ActivityClientRecord里的token对象作为key来查询当前Activiy是否在销毁名单里// 如果在销毁名单里后面的流程就不用继续走了if (mActivitiesToBeDestroyed.containsKey(r.token)) {// 省略return;}// 省略if (r.window == null && !a.mFinished && willBeVisible) {// 省略if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;// 调用WindowManger的addViewwm.addView(decor, l);}// 省略}// 省略}// 省略}
WindowMangerImpl.java 的 addView 方法:
@Overridepublic void addView(@NonNullView view, @NonNullViewGroup.LayoutParams params) {applyTokens(params);// 调用WindowManagerGlobal的addView方法mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,mContext.getUserId());}
WindowManagerGlobal.java 的 addView 方法:
publicvoidaddView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {// 省略ViewRootImpl root;// 省略if (windowlessSession == null) {root = new ViewRootImpl(view.getContext(), display);} else {root = new ViewRootImpl(view.getContext(), display,windowlessSession);}// 省略// 调用 ViewRootImpl 对象的setView方法root.setView(view, wparams, panelParentView, userId);} catch (RuntimeException e) {// BadTokenException or InvalidDisplayException, clean up.if (index >= 0) {removeViewLocked(index, true);}throw e;}}}
ViewRootImpl.java的setView方法:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {synchronized (this) {// 省略// 跨进程调用wms服务创建对应的WindowState和res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,mTempControls);// 省略}}
跨进程会调到 WindowManagerService.java 的 addWindow 方法:
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsVisibilities requestedVisibilities,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {// 省略synchronized (mGlobalLock) {// 省略// 使用binder对象作为token查询是否已存在WindowState,如果已存在则直接返回不重复创建了if (mWindowMap.containsKey(client.asBinder())) {ProtoLog.w(WM_ERROR, "Window %s is already added", client);return WindowManagerGlobal.ADD_DUPLICATE_ADD;}// 省略// Use existing parent window token for child windows since they go in the same token// as there parent window so we can apply the same policy on them.WindowToken token = displayContent.getWindowToken(hasParent ? parentWindow.mAttrs.token : attrs.token);// 省略// 如果token为null,说明当前启动的应用不是普通app应用而是系统应用// 因为只有普通应用有ActivityRecord,而在创建ActivityRecord时会生成一个IBinder类型的唯一tokenif (token == null) {// 省略} else if (rootType >= FIRST_APPLICATION_WINDOW&& rootType <= LAST_APPLICATION_WINDOW) {activity = token.asActivityRecord();// 省略}// 省略// 创建WindowState对象final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);// 省略// 获取触摸事件数据管道final boolean openInputChannels = (outInputChannel != null&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);if (openInputChannels) {// 将触摸事件数据管道绑定到WindowState对象中win.openInputChannel(outInputChannel);}// 省略// 将创建的WindowState放入Map中缓存起来,binder作为key// 省略// 将WindowState挂载到WindowToken/ActivityRecord节点下win.mToken.addWindow(win);// 省略}
最后以一张时序图总结,时序图最下方红框里的步骤是本篇文章说的内容:

粉色背景的步骤是创建和使用Token的步骤,Token是什么?有什么作用?下篇文章我会跟大家一起探索。 蓝色背景的步骤是尝试调用realStartAcvtivityLocked方法创建Activity的步骤。 绿色背景的步骤是执行Activity生命周期回调方法的地方。
夜雨聆风