ANDROID窗口管理服务实现机制

来源:互联网 发布:audition cs6 mac破解 编辑:程序博客网 时间:2024/04/29 23:56
窗口管理是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代码片断。

 

 public interface IWindowManager extends android.os.IInterface
{
  public static abstract class Stub extends android.os.Binder implements android.view.IWindowManager
  {
     private static final java.lang.String DESCRIPTOR = "android.view.IWindowManager";
     public Stub()
     {
        this.attachInterface(this, DESCRIPTOR);
     }
     public static android.view.IWindowManager asInterface(android.os.IBinder obj)
     {
       if ((obj==null)) {
          return null;
       }
       android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
       if (((iin!=null)&&(iin instanceof android.view.IWindowManager))) {
         return ((android.view.IWindowManager)iin);
       }
         return new android.view.IWindowManager.Stub.Proxy(obj);
     }
     public android.os.IBinder asBinder()
     {
       return this;
     }
     @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
     {
        switch (code)
        { 
        }
     }
     Proxy(android.os.IBinder remote)
     {
       mRemote = remote;
     }
     public android.os.IBinder asBinder()
     {
        return mRemote;
      }
      public boolean startViewServer(int port) throws android.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 获得一个窗口管理服务远端代理对象,然后使用该远端代理对象访问窗口管理服务。

  static IWindowManager getWindowManager() {

        synchronized (sStaticInit) {

            if (sWindowManager == null) {

                sWindowManager = IWindowManager.Stub.asInterface(

                        ServiceManager.getService("window"));

            }

            return sWindowManager;

        }

}

     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中

   

    final ArrayList<WindowState> mWindows;

    mWindowMap.put(client.asBinder(), win);

     每个窗口都对应一个WindowToken标记和AppWindowToken标记,服务端使用WindowToken唯一标识每一个窗口,并在addWindow函数中根据标示客户端窗口的attrs.token为键值保存到窗口服务的HashMap 变量中mTokenMap.

     mTokenMap.put(attrs.token, token);

     attrs.token 是窗口布局参数中LayoutParams的一个binder 对象,在客户端LocalWindowManager新建窗口addView时赋值,主窗口类型对应ACTIVITY的AppToken,子窗口类型对应主视图的WindowToken。

     public static class LayoutParams extends ViewGroup.LayoutParams

            implements Parcelable {

      

            public IBinder token = null;

      }

      使用AppWindowToken对象标识与窗口绑定的ACTIVITY, 在ACTIVITY启动时赋值,并也依据对应窗口的Z-ordered放在mAppTokens数组中.

      final ArrayList<AppWindowToken> mAppTokens = new ArrayList<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
原创粉丝点击