您的位置:首页 > 移动开发 > Android开发

第四篇 ANDROID窗口管理服务实现机制

2012-11-16 15:03 731 查看
窗口管理是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中;最后根据窗口能否能够接收键值更新焦点窗口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: