6.Android内核 创建窗口的过程(一)






   从WmS的角度来观察,一个窗口并不是一个Window类,而是一个View类。当WmS收到用户

的消息后,需要把消息派发到窗口,View类本身并不能直接接收WmS传递过来的消息真正接收

用户消息的必须是IWindow类,而实现IWindow类的是ViewRoot.W类每一个W内部都包含了一

个View变量



   WmS并不会介意View是属于哪一个应用程序的,WmS会按照一定的规则判断哪一个View处于活动

状态,然后把用户消息给W类,W类再把用户消息传递给W类内部的View变量,剩余的消息处理就由

View对象去完成了





WmS判断活动View ->WmS把消息传递给W ->W把消息传递给自己内部的View变量 ->View去处理 








窗口的类型



Framework定义了三种窗口类型,三种类型的定义在WindowManager类中。


   1.第一种应用窗口。指该窗口对应一个Activity,由于加载Activity是由AmS完成的,因此,对于应用程

序而言,要创建一个应用类窗口,只能在Activity内部完成。


   2.第二种子窗口。指该窗口必须有一个父窗口,父窗口可以是一个应用类型窗口,也可以是任何其他类型

的窗口。


   3.第三种系统窗口。系统窗口不需要对应任何Activity,也不需要有父窗口。对于应用程序而言,理论上是无

法创建系统窗口的,因为所有的应用程序都没有这个权限,然而系统进程却可以创建系统窗口。




   WindowManager类对这三种类型进行了细化,把每一种类型都用一个int常量表示,这些实际上代表了

窗口对应的层(Layer)。WmS在进行窗口叠加时,会按照该int常量的大小分配不同层,int值越大,代表层

的位置越靠上面,即所谓的z-order



这里要讲解一下z-order 。


z-order:Z 和 Order。 在Z坐标轴上的排列顺序,即物件在垂直的 Z 坐标轴上的上下位置关系


z:三度空间里的 Z 坐标轴。


order:排列顺序。





应用窗口类型


我们来参考一下WindowManager源代码


        /**
         * Start of window types that represent normal application windows.
         */
        public static final int FIRST_APPLICATION_WINDOW = 1;
        
        /**
         * Window type: an application window that serves as the "base" window
         * of the overall application; all other application windows will
         * appear on top of it.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_BASE_APPLICATION   = 1;
        
        /**
         * Window type: a normal application window.  The {@link #token} must be
         * an Activity token identifying who the window belongs to.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_APPLICATION        = 2;
    
        /**
         * Window type: special application window that is displayed while the
         * application is starting.  Not for use by applications themselves;
         * this is used by the system to display something until the
         * application can show its own windows.
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_APPLICATION_STARTING = 3;
    
        /**
         * End of types of application windows.
         */
        public static final int LAST_APPLICATION_WINDOW = 99;



应用窗口类型
定义 意义
FIRST_APPLICATION_WINDOW = 1
第一个应用窗口
TYPE_BASE_APPLICATION   = 1
第一个应用窗口
TYPE_APPLICATION        = 2
所有Activity对应的窗口
TYPE_APPLICATION_STARTING = 3
Activity启动时,可以指定一个启动窗口首先显示,直到真正的Activity窗口配置好后,删除该启动窗口,显示Activity窗口
LAST_APPLICATION_WINDOW = 99
最后一个应用窗口


所以的Activity默认的窗口类型都是TYPE_APPLICATION,WmS在进行窗口叠加时,会动态改变应用窗口的

层值,但层值不会大于99。






子窗口类型


WindowManager源码部分


        /**
         * Start of types of sub-windows.  The {@link #token} of these windows
         * must be set to the window they are attached to.  These types of
         * windows are kept next to their attached window in Z-order, and their
         * coordinate space is relative to their attached window.
         */
        public static final int FIRST_SUB_WINDOW        = 1000;
    
        /**
         * Window type: a panel on top of an application window.  These windows
         * appear on top of their attached window.
         */
        public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;
    
        /**
         * Window type: window for showing media (such as video).  These windows
         * are displayed behind their attached window.
         */
        public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;
    
        /**
         * Window type: a sub-panel on top of an application window.  These
         * windows are displayed on top their attached window and any
         * {@link #TYPE_APPLICATION_PANEL} panels.
         */
        public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2;

        /** Window type: like {@link #TYPE_APPLICATION_PANEL}, but layout
         * of the window happens as that of a top-level window, <em>not</em>
         * as a child of its container.
         */
        public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
        
        /**
         * Window type: window for showing overlays on top of media windows.
         * These windows are displayed between TYPE_APPLICATION_MEDIA and the
         * application window.  They should be translucent to be useful.  This
         * is a big ugly hack so:
         * @hide
         */
        public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4;
    
        /**
         * End of types of sub-windows.
         */
        public static final int LAST_SUB_WINDOW         = 1999;


子窗口类型
定义 意义
FIRST_SUB_WINDOW        = 1000
第一个子窗口
TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW
应用窗口的子窗口, PopupWindow的默认类型
TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1
尚未使用
TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2
尚未使用
TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3
OptionMenu、ContextMenu 的默认类型
TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4
尚未使用
LAST_SUB_WINDOW         = 1999
最后一个子窗口


创建子窗口时,客户端可以指定窗口类型介于1000〜1999之间,而WmS在进行窗口叠加时,会动态调整层值。






系统窗口类型


WindowManager源码部分:


        /**
         * Start of system-specific window types.  These are not normally
         * created by applications.
         */
        public static final int FIRST_SYSTEM_WINDOW     = 2000;
    
        /**
         * Window type: the status bar.  There can be only one status bar
         * window; it is placed at the top of the screen, and all other
         * windows are shifted down so they are below it.
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
    
        /**
         * Window type: the search bar.  There can be only one search bar
         * window; it is placed at the top of the screen.
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
    
        /**
         * Window type: phone.  These are non-application windows providing
         * user interaction with the phone (in particular incoming calls).
         * These windows are normally placed above all applications, but behind
         * the status bar.
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
    
        /**
         * Window type: system window, such as low power alert. These windows
         * are always on top of application windows.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;

        /**
         * Window type: keyguard window.
         * In multiuser systems shows on all users' windows.
         * @removed
         */
        public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;

        /**
         * Window type: transient notifications.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
        
        /**
         * Window type: system overlay windows, which need to be displayed
         * on top of everything else.  These windows must not take input
         * focus, or they will interfere with the keyguard.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
        
        /**
         * Window type: priority phone UI, which needs to be displayed even if
         * the keyguard is active.  These windows must not take input
         * focus, or they will interfere with the keyguard.
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
        
        /**
         * Window type: panel that slides out from the status bar
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
    
        /**
         * Window type: dialogs that the keyguard shows
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
        
        /**
         * Window type: internal system error windows, appear on top of
         * everything they can.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
        
        /**
         * Window type: internal input methods windows, which appear above
         * the normal UI.  Application windows may be resized or panned to keep
         * the input focus visible while this window is displayed.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;

        /**
         * Window type: internal input methods dialog windows, which appear above
         * the current input method window.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;

        /**
         * Window type: wallpaper window, placed behind any window that wants
         * to sit on top of the wallpaper.
         * In multiuser systems shows only on the owning user's window.
         */
        public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;

        /**
         * Window type: panel that slides out from over the status bar
         * In multiuser systems shows on all users' windows.
         */
        public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;

        /**
         * End of types of system windows.
         */
        public static final int LAST_SYSTEM_WINDOW      = 2999;



系统窗口类型
定义 意义
FIRST_SYSTEM_WINDOW     = 2000
第一个系统窗口
TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW
状态条窗口
TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1
搜索条窗口
TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2
来电显示窗口
TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3
警告对话框
TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4
屏保
TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5
Toast对应的窗口
TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6
尚未使用
TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7
在屏幕保护下的
来电显示窗口
TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8
似乎等同于滑动状态条后出现的窗口
TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9
屏保弹出的对话框
TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10
系统错误窗口
TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11
输入法窗口
TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12
输入法中备选框对应的窗口
TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13
墙纸对应的窗口
TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14
滑动状态条后出现的窗口
LAST_SYSTEM_WINDOW      = 2999
最后一个系统窗口


当具备创建系统窗口权限时,创建系统窗口可以指定层值在2000〜2999之间,WmS在进行窗口叠

加时,会动态调整该层值。所不同的是,由于有些系统窗口只能出现一个,即不能添加多个,否则

用户会觉得很乱,比如输入法窗口,再比如系统状态条窗口,因此,WmS在接收到创建窗口的消息

时,会进行一定的检查,确保该窗口只能被创建一次







token变量的定义


token的含义为象征、符号、代表等。在创建窗口时,多处定义了和token相关的变量,而无论该

变量具体的名称是什么,该变量的类型一般都是一个IBinder对象。既然是IBinder对象,其作用也

是显而易见的,即为了进行IPC调用。而与创建窗口相关的IPC对象一般只有两种,一种指向某个

W类的token另一种指向某个HistoryRecord的token。其中HistoryRecord对象AmS内部

为运行的每一个Activity创建的一个Binder对象,客户端的Activity可以通过该Binder对象通知当前

Activity的状态



token相关的源码
位置 定义
Activity IBinder mToken
Window IBinder mAppToken
WindowManager.LayoutParams IBinder token
ViewRoot
View.AttachInfo mAttachlnfo;
View View.AttachInfo mAttachlnfo;
View.AttachInfo
IBinder mWindowToken;
IBinder mPanelParentWindowToken;
IWindow mWindow;






Activity中的mToken


AmS内部为每一个运行的Activity都创建一个IBinder对象,该对象的的名字定义为mToken。该变量的值

是在Activity.attach()函数中完成的。


6.Android内核 创建窗口的过程(一)_第1张图片






Window中的mAppToken


每一个Window对象中都有一个mAppToken变量,注意这里说的是Window对象,而不是窗口。开

头就提过,一个窗口本质上是一个View,而Window类却是一个应用窗口的抽象,这就好比Window

侧重于一个窗口的交互,而窗口(View)则侧重于窗口的显示。所以,mAppToken并不是W 类的引用,事

实上正如其名称所指,它是AmS在远程为每一个Activity创建的IBinder的引用


事实上,Window类中还有其他的Binder对象,同时由于Window并不一定要对应一个Activity,因

此,如果Window类不属于某个Activity,mAppToken的变量则为空,否则mAppToken的值与Activity

中的mToken值是相同的。





WindowManager.LayoutParams 中的 token


WindowManager.LayoutParams中token的意义正如其所在的类的名称,该类是在添加窗口

时指定该窗口的布局参数,而token的意义正是指定该窗口对应的Binder对象,因为WmS需要

该Binder对象,以便对客户端进行IPC调用。



该token变量的值可以有三种


   1.如果创建的窗口是应用窗口,token的值和Window中mAppToken值相同。


   2.如果创建的窗口为子窗口,token为其父窗口的W 对象。


   3.如果创建的窗口是系统窗口,token值为空。






View中的token


ViewRoot,客户端的每一个窗口都对应一个ViewRoot对象,该对象内部的mAttachlnfo是该对

象被构造时同时创建的。该变量的类型和View对象中的mAttachlnfo相同。


View类中的mAttachlnfo,其含义是当该View对象被真正作为某个窗口 W 类的内部View时,该

变量就会被赋值为ViewRoot中的mAttachlnfo。在一般情况下,屏幕上所有的View对象的mAttachlnfo

都是被赋值过的,因为当W类中的View被添加为一个真正的窗口后,ViewRoot会调用performTraversal()

方法,而该方法则会调用View或者ViewGroup的dispatchToWindow()方法。在后者调用中,会把ViewRoot

中的mAttachlnfo赋值给View中的mAttachlnfo,所以,同一个窗口中包含的所有View对象,其内部的

mAttachlnfo的内容都是相同的


6.Android内核 创建窗口的过程(一)_第2张图片



ViewRootImpl构造时初始化mAttachInfo -> W中的View被添加为真正的窗口后 -> 

ViewRootImpl调用performTraversal() -> 调用View或者ViewGroup的dispatchToWindow()方法 ->

ViewRoot中的mAttachlnfo赋值给View中的mAttachlnfo

 




mAttachlnfo变量中,包含了三个Binder变量。


1.mWindowToken,指的是该窗口对应的W 对象。


2.mPanelParentWindowToken, 如果该窗口是子窗口的,那么该变量即为父窗口中的W 对

象。该变量赋值和mWindowToken是互斥的,因为mWindowToken如果不为空,则意味着该

窗口没有父窗口。


3.mWindow,注意,也是一个Binder对象,但它却更是一个IWindow对象,关于IBinder
由此也可以看出,mWindowToken似乎是多余的,因为mWindowToken=IWindow.asBinder()

只是多了一个变量而已,使用起来更方便。



6.Android内核 创建窗口的过程(一)_第3张图片





















你可能感兴趣的:(6.Android内核 创建窗口的过程(一))