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端提供服务。