Binder AIDL proxy stub
Binder与AIDL?
Android中有多种IPC机制,如AIDL,Messenger,Socket,ContentProvider,但是这些机制底层大都用了Binder机制来实现的,什么是Binder?要了解Android系统中的IPC我们首先要了解的就是Binder;
1、Binder机制原理
Binder机制原理:
1.客户端获取服务端的代理对象(proxy)
在客户端建立一个服务端进程的代理对象
2.客户端通过调用代理对象向服务端发送请求。
3.代理对象将用户请求通过Binder驱动发送到服务器进程;
4.服务端进程处理客户端发过来的请求,处理完之后通过Binder驱动返回处理结果给客户端的服务端代理对象;
5.代理对象将请求结果进一步返回给客户端进程。
2、Binder机制的组成
1.Client、Server、ServiceManager均在用户空间中实现,而Binder驱动程序则是在内核空间中实现的;
2.Server进程先注册一些Service到ServiceManager中,ServiceManager负责管理这些Service并向Client提供相关的接口;
3.必须先从ServiceManager中获取该Service的相关信息,Client根据得到的Service信息与Service所在的Server进程建立通信,之后Clent就可以与Service进行交互了;
4.Binder驱动程序提供设备文件/dev/binder与用户空间进行交互,Client、Server和ServiceManager通过open和ioctl文件操作函数与Binder驱动程序进行通信;
5.Client、Server、ServiceManager三者之间的交互都是基于Binder通信的,所以通过任意两者这件的关系,都可以解释Binder的机制。
3、AIDL的实现
- 首先是服务端:我们首先创建一个AIDL文件,其实就是定义我们的方法接口
https://github.com/WaterYuanData/AIDL/blob/master/aidlservice/src/main/aidl/com/example/aidlservice/IDataInterface.aidl
接下来我们创建一个Service,我们在Service中实现了我们定义的AIDL接口,并且服务端在绑定接口的时候将服务端的IBinder对象返回给客户端;
https://github.com/WaterYuanData/AIDL/blob/master/aidlservice/src/main/java/com/example/aidlservice/RoomService.java
配置
https://github.com/WaterYuanData/AIDL/blob/master/aidlservice/src/main/AndroidManifest.xml
客户端拿到服务端的IBinder对象就可以调用服务端的方法了; - 客户端实现如下:
和服务端定义一个一模一样的aidl文件(包名、方法名,参数必须一致)
绑定服务端的服务
客户端拿到服务端的IBinder对象就可以调用服务端的方法了;
https://github.com/WaterYuanData/AIDL/blob/master/aidlclient/src/main/java/com/example/aidlclient/MainActivity.java
其中iDataInterface = IDataInterface.Stub.asInterface(service);
如果客户端和服务端在同一个进程下,那么asInterface()将返回Stub对象本身,否则返回Stub.Proxy对象。
参考:https://www.jianshu.com/p/b9b3051a4ff6
4、理解proxy与stub的工作流程
我们声明的接口IMyAidlInterface包含了一个静态内部类Stub,并且Stub也继承了IMyAidlInterface,所以Stub是IMyAidlInterface的具体实现,而Stub又是一个抽象类,最终的实现在RemoteService中
Stub内部包含了一个静态内部类Proxy,同样实现了接口IMyAidlInterface
可以通过前面的例子梳理一下Stub-proxy的工作流程
RemoteService中的IBinder对象mServiceBinder是Stub的具体实现,在RemoteService和activity绑定的时候被返回
被返回的mServiceBinder最终是作为onServiceConnected中的参数,
Activity端会调用Stub中的静态方法asInterface,mServiceBinder作为参数,最后拿到IMyAidlInterface接口对象myAidlInterface
在asInterface方法中首先会判断Binder是否处在当前进程,否则构造Proxy并返回,构造Proxy时,把mServiceBinder赋值给mRemote,Proxy中实现的接口getInformation会调用mRemote的transact方法,而Binder的通信是靠transact和onTransact实现的,最后会走到Stub的onTransact,完成对mServiceBinder的调用
所以,aidl通信体现着代理模式的设计思想,RemoteService具体实现了Stub,Proxy是Stub在本地Activity的代理对象,Proxy与Stub依靠transact和onTransact通信,Proxy与Stub的封装设计最终很方便地完成了Activity与RemoteService跨进程通信
.aidl编译后才会生成.java文件
https://www.jianshu.com/p/b5611c9b4d22
Stub和Stub.Proxy。它们有什么区别呢?
- 如果在同一个进程下的话,那么asInterface()将返回服务端的Stub对象本身,因为此时根本不需要跨进称通信,那么直接调用Stub对象的接口就可以了,返回的实现就是服务端的Stub实现,也就是根本没有跨进程通信;
- 如果不是同一个进程,那么asInterface()返回是Stub.Proxy对象,该对象持有着远程的Binder引用,因为现在需要跨进程通信,所以如果调用Stub.Proxy的接口的话,那么它们都将是IPC调用,它会通过调用transact方法去与服务端通信。
https://blog.csdn.net/scnuxisan225/article/details/49970217
5、AIDL传输数据限制
非基本类型需要显式引用,不超过1M