Architecture of I19tSDK AIDLs
根据图示的内容,整个I19tSDK
的部分分为两大块,即Server
端和Client
端
Server端
跟所有的AIDL调用一样,Server
端是以AIDL Stub
为基础的。从UML class图的关系图可以看到,Stub的汇聚点是BinderProvider
:
- 继承自Android
ContentProvider
- addService到
ServiceCache
,建立与RegionRecognizerService
的依赖关系 - 持有
ServiceFetcher
对象,该对象为IServiceFetcher.Stub
子类实例
Client端
通过ServiceManagerNative
创建了Client端的服务获取中台:
- 通过
ProviderCaller
和Server端的BinderProvider
发生联系 - 持有
IServiceFetch
,通过ServiceFetch
查询到Server端的ServiceCache
,获取远端Service - 通过getService方法,获取到
IRegionRecognizer
的client实例
时序图
从整个运行的过程来看,分为两大部分:
- 第一部分是Server & Client初始化。
- 第二部分是通过Client端的Proxy Service获取Server端Service的具体能力。
初始化
如下图所示:
- 整个流程的发起方式
I19tCore
调用startup
,通过startup
会调用到ServiceManagerNative
中 - 在
ServiceManagerNative
的startup
中,会直接调用ProviderCaller
的call
函数,其中传入的参数为:MethodConstants.INIT_SERVICE
,意思是本次调用会初始化操作。 - 由于
ProviderCaller
实际是一个ContentResolver
的wrapper,因此就通过authority查找到了对应注册在AndroidManifest中的ContentProvider
,即BinderProvider:private static final String SERVICE_CP_AUTH = “com.blackshark.i19tsdk.syncprovider”;
- 由于
ContentProvider
的call
是一个同步调用,因此Client端会阻塞,进入到Server端继续进行下一步逻辑的处理,而由于此时ContentProvider
并没有运行,因此会先调用onCreate
函数进行初始化操作 - 在
BinderProvider
的onCreate
中,我们主要完成了Remote Service的初始化,即XXXService.systemReady
,以及添加Service到本地的ServiceCache中 - 在完成
onCreate
函数后,由Android ContentProvider的机制所限定,会继续跑到call
函数,根据我们传入的arg:MethodConstants.INIT_SERVICE
,我们直接做bypass,不予处理即可。 - 至此,整个从Client端发起的
startup
流程就走完了,从Server端一路返回到Client,放开阻塞后Client代码继续运行。
通过借用ContentProvider的arg参数,完成了同步初始化Server端运行环境的业务,避免了使用AIDL Service异步start的问题,避免了使用回调函数监听onBinder的问题。
一个业务逻辑
Client端的recognize识别,如下图所示:
需要注意的是,以上的流程是已经在经历了第一部分初始化业务之后了。
- 外部App需要发起一次识别操作,首先需要初始化对应的Recognizer。
- 通过
RegionRecognizer.getInstance
获取RegionRecongizer实例 - 由于是第一次在Client端初始化RegionRecognizer,因此会尝试与远端服务建立联系,这里就需要通过
ServiceManagerNative
来做桥梁 - 仿照第一部分初始化的流程,这里借用
ProviderCaller
来进行同步IPC动作,旨在获取ServiceFetcher
的Proxy代理对象mServiceFetcher,该对象通过Bundle传回 - 通过
ServiceFetcher
对象获取到远程XXXXService
的Binder实例 - 通过
XXXXX.Stub.asInterfaces
把Binder实例转化为本地的Proxy对象 - 在做具体业务
recognize
时,通过上面获取到的Proxy对象,调用到远程的实际Service完成对应的业务。
以上两个步骤,也是借用了Android ServiceManager的逻辑,通过在Client端建立一个Service大管家,保存各个Service的Proxy实例,使得Client端在每次使用具体Service时不用都去跑一遍IPC,以达到简化流程的目的。同时,通过ServiceFetcher对象,建立了Client端与Server端的服务映射关系。