窗口管理能够说是Android系统中最复杂的一部分,主要是它涉及的模块比较多,虽说是窗口管理,但除了WindowManagerService还包括SurfaceFlinger服务、Linux的共享内存及tmpfs文件系统、Binder通讯、InputManagerService、动画、VSYNC同步技术等,一篇文章不可能分析彻底,可是能够首先对于窗口的显示与管理有一个大概的轮廓,再分块分解,涉及的知识点大概以下:bash
既然是概述,咱们不妨直观的思考一个问题,Activity是如何呈现到屏幕上的,或者说View是如何被绘制到屏幕上来的?或多或少,开发者都知道WindowManagerService是负责Android的窗口管理,可是它其实只负责管理,好比窗口的添加、移除、调整顺序等,至于图像的绘制与合成之类的都不是WMS管理的范畴,WMS更像在更高的层面对于Android窗口的一个抽象,真正完成图像绘制的是APP端,而完成图层合成的是SurfaceFlinger服务。这里经过一个简单的悬浮窗口来探索一下大概流程:socket
TextView mview=new TextView(context);
...<!--设置颜色 样式-->
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
wmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
wmParams.format = PixelFormat.RGBA_8888;
wmParams.width = 800;
wmParams.height = 800;
mWindowManager.addView(mview, wmParams);复制代码
以上代码能够在主屏幕上添加一个TextView并展现,而且这个TextView独占一个窗口。在利用WindowManager.addView添加窗口以前,TextView的onDraw不会被调用,也就说View必须被添加到窗口中,才会被绘制,或者能够这样理解,只有申请了依附窗口,View才会有能够绘制的目标内存。当APP经过WindowManagerService的代理向其添加窗口的时候,WindowManagerService除了本身进行登记整理,还须要向SurfaceFlinger服务申请一块Surface画布,其实主要是画布背后所对应的一块内存,只有这一块内存申请成功以后,APP端才有绘图的目标,而且这块内存是APP端同SurfaceFlinger服务端共享的,这就省去了绘图资源的拷贝,示意图以下:动画
以上是抽象的图层对应关系,能够看到,APP端是能够经过unLockCanvasAndPost直接同SurfaceFlinger通讯进行重绘的,就是说图形的绘制同WMS没有关系,WMS只是负责窗口的管理,并不负责窗口的绘制,这一点其实也能够从IWindowSession的binder通讯接口看出来:spa
interface IWindowSession {
int add(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, out Rect outContentInsets,
out InputChannel outInputChannel);
int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
out InputChannel outInputChannel);
int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out Rect outFrame, out Rect outOverscanInsets,
out Rect outContentInsets, out Rect outVisibleInsets,
out Configuration outConfig, out Surface outSurface);
void remove(IWindow window);
...
}复制代码
从参数就能够看出,APP与WindowManagerService通讯的时候没有任何View相关的信息,更不会说将视图的数据传递给WMS,基本都是以IWindow为基本单位进行通讯的,因此涉及的操做也都是针对窗口的,好比整个窗口的添加、移除、大小调整、分组等,单单从窗口显示来看,WMS的做用确实很明确,就是在服务端登记当前存活窗口,后面还会看到,这会影响SurfaceFlinger的图层混合,能够说是为SurfaceFlinger服务的。3d
在对于平常开发来讲,WMS的窗口分组有时候会对开发带来影响,若是不知道窗口分组管理,可能有点忙迷惑,好比Dialog必须使用Activity的Context,PopupWindow不能做为父窗口,尤为要避免做为Webview的容器等,这些都跟WMS窗口的组织有关系。PopupWindow、Dialog、Activity三者都有窗口的概念,但又各有不一样,Activity属于应用窗口、PopupWindow属于子窗口,而Dialog位于二者之间,从性质上说属于应用窗口,可是从直观理解上,比较像子窗口(其实不是)。Android中的窗口主要分为三种:系统窗口、应用窗口、子窗口,Toast就属于系统窗口,而Dialog、Activity属于应用窗口,不过Dialog必须依附Activity才能存在。PopupWindow算是子窗口,必须依附到其余窗口,依附的窗口可使应用窗口也能够是系统窗口,可是不能是子窗口。代理
固然,WMS的做用不只只是管理窗口,它还负责窗口动画、Touch事件等,后面会逐个模块分析。code
既然WMS的做用只是窗口管理,那么图形是怎么绘制的呢?而且这些绘制信息是如何传递给SurfaceFlinger服务的呢?每一个View都有本身的onDraw回调,开发者能够在onDraw里绘制本身想要绘制的图像,很明显View的绘制是在APP端,直观上理解,View的绘制也不会交给服务端,否则也太不独立了,但是View绘制的内存是何时分配的呢?是谁分配的呢?咱们知道每一个Activity能够看作是一个图层,其对应一块绘图表面其实就是Surface,Surface绘图表面对应的内存实际上是由SurfaceFlinger申请的,而且,内存是APP与SurfaceFlinger间进程共享的。实现机制是基于Linux的共享内存,其实就是MAP+tmpfs文件系统,你能够理解成SF为APP申请一块内存,而后经过binder将这块内存相关的信息传递APP端,APP端往这块内存中绘制内容,绘制完毕,通知SF图层混排,以后,SF再将数据渲染到屏幕。其实这样作也很合理,由于图像内存比较大,普通的binder与socket都没法知足需求,内存共享的示意图以下:orm
其实整个Android窗口管理简化的话能够分为如下三部分cdn
做者:看书的小蜗牛
原文连接: Android窗口管理分析(1):窗口管理及主观理解blog
仅供参考,欢迎指正