6.5 统一的通信接口AIDL

AIDL(Android Interface Definition Language, Android接口定义语言)用于定义C/S体系结构中Server端可以提供的服务调用接口,框架层提供的Java系统服务接口大多由AIDL语言定义。Android提供了AIDL工具,可以将AIDL文件编译成Java文件。

6.5.1 AIDL实例

本节以power服务为例分析AIDL的使用,power服务对应的AIDL文件位于frameworks/base/core/java/android/os/IPowerManager.aidl,代码如下:


package android.os;

import android.os.WorkSource;

/*@hide/

interface IPowerManager

{

//WARNING:changes in acquireWakeLock()signature must

//be reflected in IPowerManager.cpp/h

void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);

……

boolean isScreenOn();

……

}


有了AIDL文件,便可以将其路径放入Android.mk文件中,这样编译时可自动将其转化为Java文件。对于IPowerManager.aidl文件,其对应的编译文件是frameworks/base/Android.mk,代码如下:


LOCAL_SRC_FILES+=\

……

core/java/android/os/IPowerManager.aidl\

……


编译frameworks后,AIDL工具会将其转化为IPowerManager.java文件,代码如下:


package android.os;

/*@hide/

//IPowerManager继承了IInterface接口

public interface IPowerManager extends android.os.IInterface{

/*IPowerManager的内部抽象类Stub继承Binder并实现IPowerManager。

*Stub并没有实现IPowerManager定义的接口方法,因此其为abstract类型。

具体的Java系统服务将继承Stub,并实现Stub未实现的方法/

public static abstract class Stub extends android.os.Binder

implements android.os.IPowerManager{

private static final java.lang.String DESCRIPTOR=

"android.os.IPowerManager";

public Stub(){

/*将当前对象及DESCRIPTOR分别存入父类Binder的

成员变量mOwner和mDescriptor中/

this.attachInterface(this, DESCRIPTOR);

}

//实现IBinder接口的直接子类是Binder和BinderProxy

public static android.os.IPowerManager asInterface(

android.os.IBinder obj){

if((obj==null)){

return null;

}

//BinderProxy的queryLocalInterface方法返回null

//Binder的queryLocalInterface方法返回mOwner

android.os.IInterface iin=(android.os.IInterface)

obj.queryLocalInterface(DESCRIPTOR);

//if对应Binder,将Binder转化为IPowerManager

if(((iin!=null)&&(iin instanceof

android.os.IPowerManager))){

return((android.os.IPowerManager)iin);

}

//对应BinderProxy,将其转化为Proxy

return new android.os.IPowerManager.Stub.Proxy(obj);

}

public android.os.IBinder asBinder(){

return this;

}

public boolean onTransact(int code, android.os.Parcel data,

android.os.Parcel reply, int flags)

throws android.os.RemoteException{

switch(code){

……

case TRANSACTION_isScreenOn:{

data.enforceInterface(DESCRIPTOR);

boolean_result=this.isScreenOn();

reply.writeNoException();

reply.writeInt(((_result)?(1):(0)));

return true;

}

}

//Stub的内部类Proxy也实现了IPowerManager

private static class Proxy implements android.os.IPowerManager{

private android.os.IBinder mRemote;//BinderProxy

Proxy(android.os.IBinder remote){

mRemote=remote;

}

public android.os.IBinder asBinder(){

return mRemote;

}

public java.lang.String getInterfaceDescriptor(){

return DESCRIPTOR;

}

……

//Proxy实现了调用isScreenOn接口

public boolean isScreenOn()throws

android.os.RemoteException{

……

mRemote.transact(

Stub.TRANSACTION_isScreenOn,

_data,_reply,0);

_reply.readException();

_result=(0!=_reply.readInt());

}finally{

_reply.recycle();

_data.recycle();

}

return_result;

}

……

}//Proxy定义结束

……

//定义服务接口方法的请求码(code),用于Client与Server匹配请求

static final int TRANSACTION_acquireWakeLock=

(android.os.IBinder.FIRST_CALL_TRANSACTION+0);

static final int TRANSACTION_isScreenOn=

(android.os.IBinder.FIRST_CALL_TRANSACTION+13);

……

}//Stub定义结束

//定义于IPowerManager中的接口方法,由子类Stub、Proxy及Java系统服务实现

public void acquireWakeLock(int flags, android.os.IBinder lock,

java.lang.String tag, android.os.WorkSource ws)

throws android.os.RemoteException;

public boolean isScreenOn()throws android.os.RemoteException;

……

}


由以上代码可知,开发人员只需要在AIDL文件中定义Server端可以提供的服务方法,AIDL工具便可以将其转化为Java文件。转化后的Java文件包含C/S体系结构的以下内容:

服务接口(IPowerManager)。

服务在Client端的代理(Proxy)。

服务存根(Stub)。

Binder类型与IInterface类型的转换接口(asInterface和asBinder方法)。

服务方法请求码(每一个需要通过Binder通信调用的服务方法都有一个请求码,用于Binder通信时,Proxy标记要调用Service的哪个方法。对于acquireWakeLock方法,其请求码为TRANSACTION_acquireWakeLock)。

由于AIDL工具建立了基于Binder的C/S体系结构的通用组件,开发者可以专注于开发服务的功能,而不需要理会具体的通信结构,这就大大提高了服务开发的效率。在本例中,PowerManagerService只需要继承IPowerManager.Stub,并实现IPowerManager中定义的服务接口,便可以向Client端提供服务。