网上讲解 Aidl 的文章很多,都比较详细,这里就不再重复了。本人更偏重与 Framework 和 Native,对 APP 没有发言权,文章中可能出现错误,请理解。这篇侧重于一下表面看不到的实现,碎片化的做些分析。
Binder Stub
Stub 是 Binder 服务端的对象,用来做为对 Binder 实体的描述。在 Aidl 生成的 Java 文件中,Stub 类被创建,一个简单的示例如下。
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.aidltest.aidlserver.IAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.aidltest.aidlserver.IAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.aidltest.aidlserver.IAidlInterface interface,
* generating a proxy if needed.
*/
public static com.aidltest.aidlserver.IAidlInterface asInterface(android.os.IBinder obj)
{if ((obj==null)) {return null;}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.aidltest.aidlserver.IAidlInterface))) {return ((com.aidltest.aidlserver.IAidlInterface)iin);
}
return new com.aidltest.aidlserver.IAidlInterface.Stub.Proxy(obj);
}
@Override 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
{......
重要的接口说明如下,
- asInterface:获取 Binder 代理,如果不存在这新建一个 Proxy 对象返回。
- asBinder:获取 Binder 实体,服务端直接返回 this。
- onTransact:Binder 传输接口,Aidl 自动生成了传输命令,服务端仅需要实现 Aidl 中声明的函数。
通常情况下,服务端在初始化时会创建一个 Stub 对象作为 Binder 实体,在 onBinder() 将其返回,这样客户端就可以获取到 Binder 实体。
Binder Proxy
Proxy 为 Binder 客户端的对象,做为 Binder 代理进行跨进程调用。Aidl 生成的代码如下,
private static class Proxy implements com.aidltest.aidlserver.IAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{mRemote = remote;}
@Override public android.os.IBinder asBinder()
{return mRemote;}
public java.lang.String getInterfaceDescriptor()
{return DESCRIPTOR;}
@Override public int add(int a, int b) throws android.os.RemoteException
{......
重要接口如下,
- asBinder:获取 Binder 实体,客户端返回 remote。
- getInterfaceDescriptor:获取 Binder 的服务接口描述。
客户端在 bindService 成功后会回调到客户端的 onServiceConnected(),同时返回 Binder 实体。之后就可以调用 Stub.asInterface() 将 Binder 实体转换为 Binder 代理。
调用流程
整个 Aidl 调用流程比较简单,其中涉及 bindService 流程在之前的文章中已经分析过。
通过 Aidl 进行跨进程通信时实现非常简单,只需要按 Aidl 中限定的接口在服务端进行实现,就可以通过客户端进行调用。复杂的连接过程和传输过程已经被底层屏蔽。如果仅仅时使用 Aidl,实际上可以不需要理解 Binder。