Android P WMS(1) -- wms简介

Android P WMS(2) -- wms初始化

Android O WMS(3) -- addwindow

Android P WMS(4) -- removewindow

Android P WMS(5) -- relayoutWindow

Android P WMS(6) -- windowanimator

Android P WMS(7) --wms 问题种类和debug技巧

Android P WMS(8) --View SYstem 简介

Android P WMS(9) --Surface

1.APP启动addWindow过程

我们在WMS addWindow添加打印堆栈log

//在WMS添加如下堆栈
@WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,Rect outContentInsets, Rect outStableInsets, Rect outOutsets,DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {new Exception("William WindowManagerService stack").printStackTrace(); //add log  

然后在launcher点击启动settings,log如下。第一次在启动splash screen时执行addWindow,来至于SplashScreenStartingData.createStartingSurface,第二次是启动settings主界面  com.android.settings/com.android.settings.Settings。这一部分可以参考:

Android悬浮窗TYPE_TOAST小结: 源码分析

Android解析WindowManager(三)Window的添加过程


//发现启动settings时,会先启动Splash Screen(启动画面也叫欢迎页)
1077  1148 W System.err: java.lang.Exception: William WindowManagerService stack
1077  1148 W System.err:    at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1157)
1077  1148 W System.err:    at com.android.server.wm.Session.addToDisplay(Session.java:205)
1077  1148 W System.err:    at android.view.ViewRootImpl.setView(ViewRootImpl.java:771)
1077  1148 W System.err:    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
1077  1148 W System.err:    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
1077  1148 W System.err:    at com.android.server.policy.PhoneWindowManager.addSplashScreen(PhoneWindowManager.java:3214)
1077  1148 W System.err:    at com.android.server.wm.SplashScreenStartingData.createStartingSurface(SplashScreenStartingData.java:56)
1077  1148 W System.err:    at com.android.server.wm.AppWindowContainerController$1.run(AppWindowContainerController.java:170)
1077  1148 W System.err:    at android.os.Handler.handleCallback(Handler.java:873)
1077  1148 W System.err:    at android.os.Handler.dispatchMessage(Handler.java:99)
1077  1148 W System.err:    at android.os.Looper.loop(Looper.java:193)
1077  1148 W System.err:    at android.os.HandlerThread.run(HandlerThread.java:65)
1077  1148 W System.err:    at com.android.server.ServiceThread.run(ServiceThread.java:44)
1077  1148 V WindowManager: Window Window{e56651a u0 Splash Screen com.android.settings} client=android.view.ViewRootImpl$W@f2667c5 token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}} (Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}) params={(0,0)(fillxfill) ty=APPLICATION_STARTING wanim=0x10302f8
1077  1148 V WindowManager: Attaching Window{e56651a u0 Splash Screen com.android.settings} token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}}
1077  1148 V WindowManager: addWindow: New client android.view.ViewRootImpl$W@f2667c5: window=Window{e56651a u0 Splash Screen com.android.settings} Callers=com.android.server.wm.Session.addToDisplay:205 android.view.ViewRootImpl.setView:771 android.view.WindowManagerGlobal.addView:356 android.view.WindowManagerImpl.addView:93 com.android.server.policy.PhoneWindowManager.addSplashScreen:3214 //然后才add settings window(com.android.settings/com.android.settings.Settings)
1077  1236 W System.err: java.lang.Exception: William WindowManagerService stack
1077  1236 W System.err:    at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1157)
1077  1236 W System.err:    at com.android.server.wm.Session.addToDisplay(Session.java:205)
1077  1236 W System.err:    at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:129)
1077  1236 W System.err:    at com.android.server.wm.Session.onTransact(Session.java:164)
1077  1236 V WindowManager: Window Window{c70e488 u0 com.android.settings/com.android.settings.Settings} client=android.os.BinderProxy@d12a82b token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}} (Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}) params={(0,0)(fillxfill) sim={forwardNavigation} ty=BASE_APPLICATION wanim=0x10302f8
1077  1236 V WindowManager: Attaching Window{c70e488 u0 com.android.settings/com.android.settings.Settings} token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}}
1077  1236 V WindowManager: First window added to Session{d84ba9c 3168:1000}, creating SurfaceSession
1077  1236 V WindowManager: addWindow: New client android.os.BinderProxy@d12a82b: window=Window{c70e488 u0 com.android.settings/com.android.settings.Settings} Callers=com.android.server.wm.Session.addToDisplay:205 android.view.IWindowSession$Stub.onTransact:129 com.android.server.wm.Session.onTransact:164 android.os.Binder.execTransact:731 <bottom of call stack>

Android解析WindowManager(三)Window的添加过程

1.0 概述

WindowManager对Window进行管理,说到管理那就离不开对Window的添加、更新和删除的操作,在这里我们把它们统称为Window的操作。对于Window的操作,最终都是交由WMS来进行处理。窗口的操作分为两大部分,一部分是WindowManager处理部分,另一部分是WMS处理部分。我们知道Window分为三大类,分别是:Application Window(应用程序窗口)、Sub Windwow(子窗口)和System Window(系统窗口),对于不同类型的窗口添加过程会有所不同,但是对于WMS处理部分,添加的过程基本上是一样的, WMS对于这三大类的窗口基本是“一视同仁”的。

1.1 Activity的添加过程

@frameworks/base/core/java/android/app/ActivityThread.javafinal void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {...   r = performResumeActivity(token, clearHide, reason);//1           ...if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm = a.getWindowManager();//2WindowManager.LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;if (r.mPreserveWindow) {a.mWindowAdded = true;r.mPreserveWindow = false;ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}if (a.mVisibleFromClient && !a.mWindowAdded) {a.mWindowAdded = true;wm.addView(decor, l);//3}}

注释1处的performResumeActivity方法最终会调用Activity的onResume方法。在注释2处得到ViewManager类型的wm对象,
在注释3处调用了wm的addView方法,而addView方法的实现则是在WindowManagerImpl中,此后的过程在上面的系统窗口的添加过程已经讲过,
唯一需要注意的是addView的第一个参数是DecorView。

1.2 系统窗口的添加过程

三大类窗口的添加过程会有所不同,这里以系统窗口StatusBar为例,StatusBar是SystemUI的重要组成部分,具体就是指系统状态栏,用于显示时间、电量和信号等信息。我们来查看StatusBar的实现类PhoneStatusBar的addStatusBarWindow方法,这个方法负责为StatusBar添加Window,如下所示。

@/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
private void addStatusBarWindow() {makeStatusBarView();mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);mRemoteInputController = new RemoteInputController(mHeadsUpManager);mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}@/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
public void add(View statusBarView, int barHeight) {// Now that the status bar window encompasses the sliding panel and its// translucent backdrop, the entire thing is made TRANSLUCENT and is// hardware-accelerated.mLp = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,barHeight,WindowManager.LayoutParams.TYPE_STATUS_BAR,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,PixelFormat.TRANSLUCENT);mLp.token = new Binder();mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;mLp.gravity = Gravity.TOP;mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;mLp.setTitle("StatusBar");mLp.packageName = mContext.getPackageName();mStatusBarView = statusBarView;mBarHeight = barHeight;mWindowManager.addView(mStatusBarView, mLp);   //mWindowManagermLpChanged = new WindowManager.LayoutParams();mLpChanged.copyFrom(mLp);}//WindowManager继承ViewManager,因此还是在ViewManager
@frameworks/base/core/java/android/view/WindowManager.java
/*** The interface that apps use to talk to the window manager.* </p><p>
@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {//包括addview update remove
@/frameworks/base/core/java/android/view/ViewManager.java
public interface ViewManagerpublic void addView(View view, ViewGroup.LayoutParams params);public void updateViewLayout(View view, ViewGroup.LayoutParams params);public void removeView(View view);
}//WindowManagerImpl具体实现addView
public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();@Overridepublic void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);}@frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {...//参数检查final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;if (parentWindow != null) {parentWindow.adjustLayoutParamsForSubWindow(wparams);//1} else {...}ViewRootImpl root;View panelParentView = null;...root = new ViewRootImpl(view.getContext(), display);//2view.setLayoutParams(wparams);mViews.add(view);mRoots.add(root);//3mParams.add(wparams);}try {root.setView(view, wparams, panelParentView);//4} catch (RuntimeException e) {...}}/*** We have one child*/
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {synchronized (this) {try {mOrigWindowType = mWindowAttributes.type;mAttachInfo.mRecomputeGlobalAttributes = true;collectViewAttributes();res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mInputChannel);}
}@/frameworks/base/services/core/java/com/android/server/wm/Session.java
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,Rect outOutsets, InputChannel outInputChannel) {return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,  //就调用到了wms::addWindowoutContentInsets, outStableInsets, outOutsets, outInputChannel);
}

2.Window的添加过程(WMS部分)

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public int addWindow(Session session, IWindow client, int seq,WindowManager.LayoutParams attrs, int viewVisibility, int displayId,Rect outContentInsets, Rect outStableInsets, Rect outOutsets,InputChannel outInputChannel) {int[] appOp = new int[1];int res = mPolicy.checkAddPermission(attrs, appOp);//1if (res != WindowManagerGlobal.ADD_OKAY) {return res;}...synchronized(mWindowMap) {if (!mDisplayReady) {throw new IllegalStateException("Display has not been initialialized");}final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);//2if (displayContent == null) {Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "+ displayId + ".  Aborting.");return WindowManagerGlobal.ADD_INVALID_DISPLAY;}...if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {//3parentWindow = windowForClientLocked(null, attrs.token, false);//4if (parentWindow == null) {Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;}if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW&& parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;}}...
}
...
}

WMS的addWindow返回的是addWindow的各种状态,比如添加Window成功,无效的display等等,这些状态被定义在WindowManagerGlobal中。 
注释1处根据Window的属性,调用WMP的checkAddPermission方法来检查权限,具体的实现在PhoneWindowManager的checkAddPermission方法中,如果没有权限则不会执行后续的代码逻辑。注释2处通过displayId来获得窗口要添加到哪个DisplayContent上,如果没有找到DisplayContent,则返回WindowManagerGlobal.ADD_INVALID_DISPLAY这一状态,其中DisplayContent用来描述一块屏幕。注释3处,type代表一个窗口的类型,它的数值介于FIRST_SUB_WINDOW和LAST_SUB_WINDOW之间(1000~1999),这个数值定义在WindowManager中,说明这个窗口是一个子窗口,不了解窗口类型取值范围的请阅读Android解析WindowManager(二)Window的属性这篇文章。注释4处,attrs.token是IBinder类型的对象,windowForClientLocked方法内部会根据attrs.token作为key值从mWindowMap中得到该子窗口的父窗口。接着对父窗口进行判断,如果父窗口为null或者type的取值范围不正确则会返回错误的状态。

   ...AppWindowToken atoken = null;final boolean hasParent = parentWindow != null;WindowToken token = displayContent.getWindowToken(hasParent ? parentWindow.mAttrs.token : attrs.token);//1final int rootType = hasParent ? parentWindow.mAttrs.type : type;//2boolean addToastWindowRequiresToken = false;if (token == null) {if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {Slog.w(TAG_WM, "Attempted to add application window with unknown token "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}if (rootType == TYPE_INPUT_METHOD) {Slog.w(TAG_WM, "Attempted to add input method window with unknown token "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}if (rootType == TYPE_VOICE_INTERACTION) {Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}if (rootType == TYPE_WALLPAPER) {Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}...if (type == TYPE_TOAST) {// Apps targeting SDK above N MR1 cannot arbitrary add toast windows.if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,parentWindow)) {Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}}final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();token = new WindowToken(this, binder, type, false, displayContent,session.mCanAddInternalSystemWindow);//3} else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {//4atoken = token.asAppWindowToken();//5if (atoken == null) {Slog.w(TAG_WM, "Attempted to add window with non-application token "+ token + ".  Aborting.");return WindowManagerGlobal.ADD_NOT_APP_TOKEN;} else if (atoken.removed) {Slog.w(TAG_WM, "Attempted to add window with exiting application token "+ token + ".  Aborting.");return WindowManagerGlobal.ADD_APP_EXITING;}} else if (rootType == TYPE_INPUT_METHOD) {if (token.windowType != TYPE_INPUT_METHOD) {Slog.w(TAG_WM, "Attempted to add input method window with bad token "+ attrs.token + ".  Aborting.");return WindowManagerGlobal.ADD_BAD_APP_TOKEN;}}...

addWindow方法总结
addWindow方法分了3个部分来进行讲解,主要就是做了下面4件事: 
1. 对所要添加的窗口进行检查,如果窗口不满足一些条件,就不会再执行下面的代码逻辑。 
2. WindowToken相关的处理,比如有的窗口类型需要提供WindowToken,没有提供的话就不会执行下面的代码逻辑,有的窗口类型则需要由WMS隐式创建WindowToken。 
3. WindowState的创建和相关处理,将WindowToken和WindowState相关联。 
4. 创建和配置DisplayContent,完成窗口添加到系统前的准备工作。

参考链接:

Android悬浮窗TYPE_TOAST小结: 源码分析

Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程

Android解析WindowManager系列

http://androidxref.com/8.0.0_r4/

《深入理解Android:卷III》

Android O WMS(3) -- addwindow相关推荐

  1. android wms各个类的作用,Android系统服务 —— WMS

    "可以毫不夸张的说,Android的framework层主要是由WMS.AMS还有View所构成,这三个模块穿插交互在整个framework中,掌握了它们之间的关系和每一个逻辑步骤,你对fr ...

  2. android 13 WMS/AMS系统开发-窗口层级相关SurfaceFlinger图层创建 第三节

    创建Surfacelinger的图层堆栈打印添加: 更多内容qqun:422901085 https://ke.qq.com/course/5992266#term_id=106217431 代码位置 ...

  3. android ams wms view,android Gui系统之WMS(1)

    SurfaceFlinger 前面说的,就是一个surface的合成.SurfaceFlinger就是一个默默的记录着,它不会对surface的内容有什么改动. WMS(WindowsManagerS ...

  4. 【Android】WMS(一)Window的类型和标志

    Window.WindowManager.WMS区别 Window: Window 是 Android 中的一个视图容器,代表整个屏幕或 Activity 的一部分.每个 Window 都有自己的 S ...

  5. Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程

    前言 在本系列的上一篇文章中,我们学习了WMS的诞生,WMS被创建后,它的重要的成员有哪些?Window添加过程的WMS部分做了什么呢?这篇文章会给你解答. 1.WMS的重要成员 所谓WMS的重要成员 ...

  6. Android开发中的WMS详细解析

    /   今日科技快讯   / 近日,小冰公司宣布对旗下人工智能数字员工产品线启动年度升级.本次升级加强的技术包括大模型对话引擎.3D神经网络渲染.超级自然语音及AIGC人工智能内容生成.小冰公司计划将 ...

  7. WMS(一):Window的添加过程

    作者:刘望舒 链接:https://www.jianshu.com/p/aadfb70f25e2 前言 在此前的系列文章中我们学习了WindowManager体系和Window的属性,这一篇我们接着来 ...

  8. WindowManager如何被Android深度解析(3)

    前言 在此前的系列文章中我们学习了WindowManager体系和Window的属性,这一篇我们接着来讲Window的添加过程.建议阅读此篇文章前先阅读本系列的前两篇文章. 1.概述 WindowMa ...

  9. 《深入理解Android 卷III》第四章 深入理解WindowManagerService

    <深入理解Android 卷III>即将公布,作者是张大伟.此书填补了深入理解Android Framework卷中的一个主要空白.即Android Framework中和UI相关的部分. ...

  10. android token机制_Android之window机制token验证

    前言 很高兴遇见你~ 欢迎阅读我的文章 这篇文章讲解关于window token的问题,同时也是Context机制和Window机制这两篇文章的一个补充.如果你对Android的Window机制和Co ...

最新文章

  1. linux 内核 sscanf,linux sscanf()
  2. Selenium-js弹窗浮层
  3. JAVA的JDBC连接数据库以及读取数据库数据
  4. DayDayUp之Job:牛客网—算法工程师—剑指offer之66道在线编程(解决思路及其代码)——21~40
  5. .net Mvc Controller 接收 Json/post方式 数组 字典 类型 复杂对象
  6. 分计算iv值_快捷、经济、实用的光伏及IV曲线测试仪PVPM 1500X
  7. 【珍藏】 2012.NET开发必看资料53个+经典源码77个—下载目录
  8. 调试系列2:bugreport实战篇
  9. 关于系统响应函数OnSysCommand
  10. python 股票指标库talib_Talib金融库的使用
  11. WAPI协议完整性测试解析系列(之一)WAI子类型的协议完整性测试
  12. Win10系统怎么安装cab文件?
  13. Laravel 登录验证,md5验证,自定义验证,自定义表
  14. clean-label backdoor attacks 论文笔记
  15. 配色工具Material Design
  16. 机器学习中precision和accuracy区别
  17. 『解决办法』UBUNTU自带拼音输入法无法正常输入
  18. JDK软件安装+环境变量配置图文详解(Win10环境)
  19. xampp 可道云_Windows下用kodexplorer可道云在本地搭建私有云的步骤
  20. 三步掩模行业调研报告 - 市场现状分析与发展前景预测

热门文章

  1. LabVIEW用高速数据流盘
  2. 库存商品计算成本的几种方法
  3. arcgis 计算面积
  4. UltraEdit注册机 及使用方法详解
  5. idea 调用webservice接口
  6. 尚学堂马士兵struts2 课堂笔记(一)
  7. linux测试wifi信噪比,无线网络中信噪比(SNR)计算
  8. wps里为什么没有华文楷体_是谁动了我的字体?为什么Word或PPT换台电脑打开字体就变了呢?...
  9. 【项目源码】JavaWeb网上购书系统
  10. 基于组态软件的35kV变电站监控系统设计简介