android 窗口管理服务实现机制

来源:互联网 发布:java中wait的用法 编辑:程序博客网 时间:2024/05/16 10:35
窗口管理是ANDROID框架一个重要部分,主要包括如下功能:
      (1)Z-ordered的维护
      (2)窗口的创建、销毁
      (3)窗口的绘制、布局
      (4)Token管理,AppToken
      (5)活动窗口管理(FocusWindow)
      (6)活动应用管理(FocusAPP)

      (7)输入法管理
      (8)系统消息收集与分发

       这些功能主要有一个窗口管理服务和相应的客户端来实现,实现机制是标准的ANDROID系统服务实现机制--基于代理模式和CORBA模式的实现机制:客户端通过远程代理使用BINDER驱动与服务进行交互.






     窗口管理的整个类图如下:

       整个类图包括客户端和服务端两大部分,服务端的类主要有WindowManagerService、WindowState、Session、SurfaceSession、Surface等主要类。WindowManagerService、Session派生自各自的本地桩(STUB)。而这些桩和连同远程访问代理都是通过AIDL 文件自动生成的,STUB提供了服务管理接口的本地IPC桩实现,且派生自Binder类,远程访问代理Proxy提供了服务管理接口的远端实现,代理根据本地服务的引用访问本地服务,实现远端访问本地服务的目的。因此借助STUB 提供IPC本地服务访问接口,Proxy提供远端访问接口,可以实现客户端访问服务的目标。
      如下是根据AIDL文件自动生成的IWindowManager.java和IWindowSession.java代码片断。

[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
publicinterface IWindowManager extendsandroid.os.IInterface
{
publicstatic abstract class Stub extendsandroid.os.Binder implementsandroid.view.IWindowManager
{
privatestatic final java.lang.String DESCRIPTOR = "android.view.IWindowManager";
publicStub()
{
this.attachInterface(this, DESCRIPTOR);
}
publicstatic android.view.IWindowManager asInterface(android.os.IBinder obj)
{
if((obj==null)) {
returnnull;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if(((iin!=null)&&(iininstanceofandroid.view.IWindowManager))) {
return((android.view.IWindowManager)iin);
}
returnnew android.view.IWindowManager.Stub.Proxy(obj);
}
publicandroid.os.IBinder asBinder()
{
returnthis;
}
@Overridepublic boolean onTransact(intcode, android.os.Parcel data, android.os.Parcel reply, intflags) throwsandroid.os.RemoteException
{
switch(code)
{
}
}
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
publicandroid.os.IBinder asBinder()
{
returnmRemote;
}
publicboolean startViewServer(intport) throwsandroid.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(port);
mRemote.transact(Stub.TRANSACTION_startViewServer, _data, _reply, 0);//通过服务的远端引用发出访问请求。
}
}


客户端都通过如下接口获得窗口管理服务远端代理对象,该接口首先通过ServiceManager(0号服务)的getService接口使用窗口管理服务在ServiceManager中登记时使用的服务名字获得窗口管理服务的引用,并传进IWindowManager.Stub.asInterface 获得一个窗口管理服务远端代理对象,然后使用该远端代理对象访问窗口管理服务。
[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
staticIWindowManager getWindowManager() {
  
        synchronized(sStaticInit) {
  
            if(sWindowManager == null) {
  
                sWindowManager = IWindowManager.Stub.asInterface(
  
                        ServiceManager.getService("window"));
  
            }
  
            returnsWindowManager;
  
        }
  
}


Session对象也是服务端提供的供客户端可以访问的对象,服务端使用Session对象指示一个客户端与窗口管理服务交互实现窗口操作的会话,通常为每个与窗口管理交互的进程打开一个Session对象,在服务端维护一个Session对象列表管理每一个Session,在Session会话期间,客户端可以通过该Session对象与窗口管理服务实现窗口交互,如窗口的创建、销毁、绘制、布局等保证一个Session期间窗口状态的一致。
     Session对象在一个进程新建第一个窗口时使用窗口管理接口的openSession接口创建,第一个窗口新建期间也创建一个SurfaceSession对象用来实现窗口和视图绘制操作。SurfaceSession对象用来与SurfaceFliger 服务建立连接,实现窗口和视图在显示硬件上的实际输出工作。
服务端的Surface类是一个处理窗口输出的对象,窗口和视图使用Surface类进行实际的绘制.
     服务端为每个窗口创建一个Surface对象,并在该对象中通过JNI创建一个C++层负责绘制的SurfaceControl对象,并把该Surface对象创建的SurfaceControl对象的引用传给客户端的Surface对象中,因此客户端的Surface对象就可以使用和服务端Surface对象一样的SurfaceControl对象进行绘制控制了.
     服务端使用WindowState对象代表每一个窗口,每一个窗口的WindowState对象依据窗口的Z-ordered 放在mWindows数组中,也根据客户端窗口对应的W类对象放到mWindowMap中


[Java] 纯文本查看 复制代码
?
1
2
3
finalArrayList<WindowState> mWindows;
  
    mWindowMap.put(client.asBinder(), win);


每个窗口都对应一个WindowToken标记和AppWindowToken标记,服务端使用WindowToken唯一标识每一个窗口,并在addWindow函数中根据标示客户端窗口的attrs.token为键值保存到窗口服务的HashMap 变量中mTokenMap.
[Java] 纯文本查看 复制代码
?
1
mTokenMap.put(attrs.token, token);

attrs.token 是窗口布局参数中LayoutParams的一个binder 对象,在客户端LocalWindowManager新建窗口addView时赋值,主窗口类型对应ACTIVITY的AppToken,子窗口类型对应主视图的WindowToken。
[Java] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
9
publicstatic class LayoutParams extendsViewGroup.LayoutParams
  
            implementsParcelable {
  
       
  
            publicIBinder token = null;
  
      }

使用AppWindowToken对象标识与窗口绑定的ACTIVITY, 在ACTIVITY启动时赋值,并也依据对应窗口的Z-ordered放在mAppTokens数组中.
[Java] 纯文本查看 复制代码
?
1
finalArrayList<AppWindowToken> mAppTokens = newArrayList<AppWindowToken>();

客户端负责窗口操作的主要有四个类 :
      ViewRootImpl 视图处理类,继承自Handler,实现客户端窗口及VIEW与窗口管理服务的交互和事件处理,因此ViewRootImpl是一个中介模式的采用。内部也有一个W类对象mWindow,派生自IWindow.Stub,是代表客户端窗口的一个桩对象,窗口管理服务通过该对象与客户端交互。客户端与窗口服务打开的会话保存在sWindowSession变量中,因此客户端使用sWindowSession与窗口管理服务发送请求,窗口管理服务使用mWindow向客户端回送应答,借助ViewRootImpl的两个BINDER对象实现客户端与窗口服务服务的双向交互。


     WindowManagerImpl是客户端WindowManager管理接口的实现,用来通过ViewRootImpl发送窗口的创建、销毁和布局请求等。
VIEW类是视图的基类,视图的主 View通过AttachInfo对象借助ViewRootImpl绑定到窗口,ViewRootImpl也作为主视图的ViewParent。AttachInfo是视图的内部类
     下面是一个打开一个窗口的序列图:

      1 )客户端在创建窗口时调用getWindowManager获得本地窗口管理对象,并调用其addView函数,在这里为窗口的布局参数赋值,如窗口标题、包名字、token值、flag值等;
      2)接着调用本地窗口管理对象的超类CompatModeWrapper的addView函数;
      3)CompatModeWrapper是WindowManagerImpl的包装类,采用了桥接模式,达到实现和抽象的分离目的. 因此CompatModeWrapper函数addView转而调用WindowManagerImpl的addView函数;
      4)WindowManagerImpl的addView函数首先查看要add的视图是否已经存在,若不存在时实例化一个ViewRootImpl对象,并把view和ViewRootImpl对象及布局参数保存到本地数组中,接着调用ViewRootImpl对象的setView函数;
      5)ViewRootImpl对象的setView函数首先请求进行窗口的第一次布局(调用requestLayout),然后根据窗口属性是否支持输入实例化一个InputChannel,然后通过服务端远程代理对象sWindowSession向服务端发出新建窗口的请求(调用其add接口);最后还要registerInputChannel和把视图assignParent;
      6)服务端的Session对象收到addwindow的请求,就调用窗口管理服务的addWindow函数来完成新建窗口的任务,完成实际创建窗口的工作。首先实例化一个WindowState对象代表新建的窗口,接着使用客户端窗口的BINDER对象(W对象)为键值把WindowState对象放入mWindowMap中,并根据Z-ORDER放入WindowState的数组中,还要调用WindowState对象的attach函数与Session完成绑定,并在SurfaceSession没有创建时完成创建;然后新建或获得WindowToken,并使用传进来的客户端窗口布局参数中的token值把WindowToken放入mTokenMap中;最后根据窗口能否能够接收键值更新焦点窗口。转自固弘博客 
0 0
原创粉丝点击