Android Camera中的aidl与binder (一)- 基础知识
首先要明确,aidl文件是用来在跨进程访问的过程中定义接口的,其在android系统的编译过程中会被aidl工具生成一个java文件和三个c++头文件,以ICameraService.aidl为例:
\frameworks\av\camera\aidl\android\hardware\ICameraService.aidl
其生成目标的路径是:
\out\soong\.intermediates\frameworks\base\framework\android_common\gen\aidl\frameworks\av\camera\aidl\android\hardware\camera2
和
\out\soong\.intermediates\frameworks\av\camera\libcamera_client\android_arm_armv8-a_cortex-a73_core_shared\gen\aidl\android\hardware\
去分别研究一下它们的作用:
首先看一下ICameraService.java:
代码结构可以看出,这里定义了之前看代码很常见的ICameraService.Stub和ICameraService.Stub.Proxy两个内部类
其中Stub类就是java binder的服务端,Proxy类就是代理端,
可以看到Stub类和Proxy类都实现了ICameraService的接口,简单画一下类图关系:
这两个类分别是什么作用呢,可以从他们实现的方法介入分析:
\out\soong\.intermediates\frameworks\base\framework\android_common\gen\aidl\frameworks\av\camera\aidl\android\hardware\ICameraService.java
首先可以看到,Stub类是一个抽象类,一般来说,开发者需要继承这个类来实现服务端的功能
其次,重点关注一下onTransact方法:
可以很清楚地看到,switch中通过不同的case来从序列化传输的data中取出参数,然后调用Stub类自身的抽象方法,这些方法等待开发者的实现
而这些case的枚举分别标识了AIDL文件中定义的接口:
有onTransact就说明这是一个被动调用的方法,transact在哪呢,这就要提到另一个内部类Proxy:
先说结论:Proxy类就是跨进程访问过程中,client端获取到的server端的代理,所有client端的call都是通过Proxy类进行IPC
结论的解释稍后详细说明
可以看到Proxy类中已经自动封装好了所有AIDL中声明的接口,并通过调用mRemote对象的transact方法传递IPC调用到server端
282行可以看到刚刚在Stub类中定义的那些枚举,和AIDL接口是一一对应的
mRemote是IBinder类型的对象,在IBinder的实现类Binder.java中,可以找到transact的实现,这里就能看到通往onTransact的调用了,onTransact的重载在我们之前提到的Stub端,即真正实现server功能的地方
\frameworks\base\core\java\android\os\Binder.java
ps:被重载的父类onTransact也清楚地在注释中表示,这个方法需要被重载
至此,Stub类和Proxy类的联系和处在c/s两端的位置我们大致有了初步了解,接下来看看这两个类应该如何使用
还是以cameraService为例进行研究,还记得上一节留下的问题吗
“Proxy类就是跨进程访问过程中,client端获取到的server端的代理,所有client端的call都是通过Proxy类进行IPC”
这个结论是怎么得出的?看完这节我们就能解释它。
到CameraManager中去看一下
先关注cameraService对象的来历,毕竟之后的调用都是通过这个对象进行,这里就要去看asInterface的实现了:
\out\soong\.intermediates\frameworks\base\framework\android_common\gen\aidl\frameworks\av\camera\aidl\android\hardware\ICameraService.java
这里试着分析一下,31行queryLocalInterface的调用是IBinder的方法,实现在Binder.java:
\frameworks\base\core\java\android\os\Binder.java
这里提到的mOwner和mDescriptor都在attachInterface中赋值
而attachInterface又是在哪里赋值的呢
往回看可以发现是在ICameraService.java,内部类Stub的构造中,把this(即Stub类)传入attachInterface
至此,可以理清asInterface的逻辑:
31行调用queryLocalInterface搜索IInterface是否有本地接口(是否有Stub类进行过构造)
32行可以看到通过一个判断来区分了返回的对象类型,如果上一步调用时构造过Stub类,就返回当前的iin对象,即ICameraService.Stub类,我们知道Stub类是server的实现,也就是说此时不用进行IPC,反推出此时应该是同进程的调用;
而如果没有构造过Stub类对象(CameraService就是如此),queryLocalInterface将返回null,此刻asInterface返回一个ICameraService.Stub.Proxy对象,并把IBinder对象传入,构造出Proxy类,Proxy类中持有IBinder对象,其实现就是服务端Stub的工作,此时也就是跨进程调用的情形啦。
参考:
https://www.kancloud.cn/alex_wsc/android-deep3/416260
https://blog.csdn.net/qq_38401088/article/details/123606752?spm=1001.2014.3001.5502
https://blog.csdn.net/scnuxisan225/article/details/49970217?spm=1001.2014.3001.5502