Android AIDL简介

来源:互联网 发布:邮件收发软件 编辑:程序博客网 时间:2024/06/03 17:40

Android AIDL简介

通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的service。在Android平台中,一个进程通常不能访问其他进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。编写这种伪装代码相当的枯燥乏味,好在我们提供了AIDL工具可以来做这件事。

AIDL(Android接口描述语言)是一个IDL语言,它可以生成一段代码,使在一个Android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。

AIDL IPC的机制是基于接口的,和COM或Corba类似,但它是轻量级的。它使用代理类在客户端和实现层间传递值。

在开始本章之前,先向大家介绍COM的一个概念---------Proxy/Stub结构(代理/存根结构)


打个比方,你到自动取款机上去取款;你就是客户,取款机就是你的代理;你不会在乎钱具体放在那里,你只想看到足够或更多的钱从出口出来(这就是com的透明性)。你同银行之间的操作完全是取款机代理实现。你的取款请求通过取款机,传到另一头,银行的服务器,他也没有必要知道你在哪儿取钱,他所关心的是你的身份,和你取款多少。当他确认你的权限,就进行相应的操作,返回操作结果给取款机,取款机根据服务器返回结果,从保险柜里取出相应数量的钱给你。你取出卡后,操作完成。取款机不是直接同服务器连接的,他们之间还有一个“存根”,取款机与存根通信,服务器与存根通信。从某种意义上说存根就是服务器的代理。(参考COM代理与存根)

AIDLFramework层的架构,如下图:


换而言之,Android就是在传统的C/S架构中加入了一层,实现IPC。图中表明,AIDL类似COM的Proxy/Stub架构。不过是现在android自己的序列化类Pacel。

以USB Mass Storage架构举例。看看到底什么是AIDL的framework层的实现。编写好aidl文件,运用aidl工具生成IMountService.java文件,如下所示(删除部分内容,方便举例)

/*

 * This file is auto-generated.  DO NOT MODIFY.

 * Original file: frameworks/base/core/java/android/os/storage/IMountService.aidl

 */

package android.os.storage;

/** WARNING! Update IMountService.h and IMountService.cpp if you change this file.

 * In particular, the ordering of the methods below must match the 

 * _TRANSACTION enum in IMountService.cpp

 * @hide - Applications should use android.os.storage.StorageManager to access

 * storage functions.

 */

public interface IMountService extends android.os.IInterface

{

    /** Local-side IPC implementation stub class. */

    public static abstract class Stub extends android.os.Binder implements android.os.storage.IMountService

    {                 

             @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

             {

                       switch (code)

                       {

                       。。。。。。。。。。。

                                case TRANSACTION_registerListener:

                                {

                                         data.enforceInterface(DESCRIPTOR);

                                         android.os.storage.IMountServiceListener _arg0;

                                         _arg0 = android.os.storage.IMountServiceListener.Stub.asInterface(data.readStrongBinder());

                                         this.registerListener(_arg0);

                                         reply.writeNoException();

                                         return true;

                                }

                       

                       。。。。。。。。。。。

                       

                       return super.onTransact(code, data, reply, flags);

             }

             

             private static class Proxy implements android.os.storage.IMountService

             {

                       。。。。。。。。。。。。。。。。

                       /**

                        * Registers an IMountServiceListener for receiving async

                        * notifications.

                        */

                       public void registerListener(android.os.storage.IMountServiceListener listener) throws android.os.RemoteException

                       {

                                android.os.Parcel _data = android.os.Parcel.obtain();

                                android.os.Parcel _reply = android.os.Parcel.obtain();

                                try {

                                         _data.writeInterfaceToken(DESCRIPTOR);

                                         _data.writeStrongBinder((((listener!=null))?(listener.asBinder()):(null)));

                                         mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);

                                         _reply.readException();

                                }

                                finally {

                                         _reply.recycle();

                                         _data.recycle();

                                }

                       }

                       。。。。。。。。。。。。。。。。

    }

可以看到IMountService 中的Stub继承Binder和IMountService

看过源代码,我们不难发现上图中对应的角色:

Client ------ StorageManager

Proxy ------ IMountServie.Stub.Proxy

Parcel ------对象序列化类,数据只有继承Parcelable才能进行RPC

Stub ------ IMountService.Stub

Server ------ MountService

当StorageManager调用MountService方法时,例如调用registerListener,步骤如下:

²  进入IMountServie.Stub.Proxy找到对应的方法registerListener。

²  IMountServie.Stub.ProxyregisterListener利用Parcel将函数调用的序列化为android理解的结构

²  调用onTransact函数,onTransact根据参数,找到对应registerListener Switch-case语句执行

²  数据通过Binder机制进行写操作,客户端调用阻塞,等待服务端reply

²  服务端处理完request返回

²  客户端取回数
0 0