IBinder IBinder是一个接口,它代表了一种跨进程传输的能力;只要实现了这个接口,就能将这个对象进行跨进程传递;这是驱动底层支持的;在跨进程数据流经驱动的时候,驱动会识别IBinder类型的数据,从而自动完成不同进程Binder本地对象以及Binder代理
public interface IBinder { //得到某个接口的描述字符串 public String getInterfaceDescriptor() throws RemoteException; //查询某个本地接口,如果是远程接口的话返回null public IInterface queryLocalInterface(String descriptor); //用于在客户端发起方法调用,这个方法可能是本地方法,也可能是远程调用 public boolean transact(int code, Parcel data, Parcel reply, int flags); }Binder Binder实现了IBinder接口,提供了跨进程的具体实现; 对于Server进程来说,Binder指的是Binder本地对象; 对于Client来说,Binder会被转化为一个BinderProxy对象。
public class Binder implements IBinder { //接口实体 private IInterface mOwner; //接口的描述字符串 private String mDescriptor; public IInterface queryLocalInterface(@NonNull String descriptor) { if (mDescriptor != null && mDescriptor.equals(descriptor)) { return mOwner; } return null; } //Binder对象发起函数调用实际上就是调用一个本地方法,这个方法运行在客户端 public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { ... //由于客户端和服务端都是Binder对象自己,所以就直接调用自己的onTransact方法 boolean r = onTransact(code, data, reply, flags); return r; } //onTransact用于客户端发起方法调用时,把回复写进reply,这个方法运行在服务端 protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { if (code == INTERFACE_TRANSACTION) { reply.writeString(getInterfaceDescriptor()); return true; } else if (code == DUMP_TRANSACTION) { ... } else if (code == SHELL_COMMAND_TRANSACTION) { ... } return false; } }BinderProxy BinderProxy代表远程进程的Binder对象的本地代理;BinderProxy类也实现了IBinder接口,所以它也具有跨进程传输的能力;实际上,在跨越进程的时候,Binder驱动会自动完成Binder和BinderProxy两个对象的转换。
final class BinderProxy implements IBinder { //代理调用的肯定是远程方法了,所以直接返回null public IInterface queryLocalInterface(String descriptor) { return null; } //BinderProxy自己没有onTransact方法,而是通过本地方法间接调用自己对应Binder的onTransact public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { ... return transactNative(code, data, reply, flags); } }IInterface IInterface代表的就是远程server对象具有什么能力。具体来说,就是aidl里面的接口
Stub 它是一个实现了IInterface的Binder对象,它跨进程地提供了IInterface的功能
首先定一个简单的aidl接口
package com.example.test.app; interface ICompute { int add(int a, int b); }自动生成类: 生成了一个大类和几个内部类,这里拆解一下:
ICompute.aidl同名的java接口: 这个接口非常简单,只有aidl中同名的方法 并且实现了IInterface,表明这个接口是可以跨进程向其他进程提供AIDL中定义的功能;
public interface ICompute extends android.os.IInterface { public int add(int a, int b) throws android.os.RemoteException; }Stub: Stub是ICompute接口的一个内部类,对应一个Binder对象,是Servie对其他进程提供服务的实体,它是提供服务的
public static abstract class Stub extends android.os.Binder implements com.example.test.app.ICompute { static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); private static final java.lang.String DESCRIPTOR = "com.example.test.app.ICompute"; public Stub() { this.attachInterface(this, DESCRIPTOR); } //通过此方法将IBinder转换为服务接口 public static com.example.test.app.ICompute asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } //查询本地接口,即是否是服务端自己在调用该接口; android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.example.test.app.ICompute))) { //服务端自己在调用该接口,直接类型强转就可以; return ((com.example.test.app.ICompute) iin); } //其他客户端进程在调用服务接口,返回一个代理对象; return new com.example.test.app.ICompute.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } //此方法运行在server端,当代理对象发出请求后处理并返回结果 @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_add: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); int _result = this.add(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } }Proxy: Proxy是Stub的内部类,对应一个BinderProxy对象,Client通过这个对象请求调用Stub提供的接口 Proxy持有一个远程的IBinder对象,与server进程交互依赖此IBinder对象;
private static class Proxy implements com.example.test.app.ICompute { 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; } //代理对象要做的就是把数据序列化然后发送给server进程 @Override public int add(int a, int b) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(a); _data.writeInt(b); //此方法运行在客户端进程,发送数据并等待结果 mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } }IBinder接口代表跨进程调用的能力,子类Binder代表Server端本身,子类BinderProxy代表Server在Client的远程代理; transact代表proxy发起远程调用,onTrasact代表Server处理请求; 调用的方法通过方法描述符定位,方法的参数通过序列化的方式传递; 要实现跨进程通信就要针对一个接口实现一个Stub和一个Proxy,它们分别代表Server本身和Server的远程代理;AIDL只是用自动生成的代码简化了这个过程