I19tSDK SYNC AIDLs

Architecture of I19tSDK AIDLs

uml.png-61.3kB

根据图示的内容,整个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的具体能力。

初始化

如下图所示:
startup.png-24.4kB

  • 整个流程的发起方式I19tCore调用startup,通过startup会调用到ServiceManagerNative
  • ServiceManagerNativestartup中,会直接调用ProviderCallercall函数,其中传入的参数为:MethodConstants.INIT_SERVICE,意思是本次调用会初始化操作。
  • 由于ProviderCaller实际是一个ContentResolver的wrapper,因此就通过authority查找到了对应注册在AndroidManifest中的ContentProvider,即BinderProvider:

    private static final String SERVICE_CP_AUTH = “com.blackshark.i19tsdk.syncprovider”;

  • 由于ContentProvidercall是一个同步调用,因此Client端会阻塞,进入到Server端继续进行下一步逻辑的处理,而由于此时ContentProvider并没有运行,因此会先调用onCreate函数进行初始化操作
  • BinderProvideronCreate中,我们主要完成了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识别,如下图所示:
recognize.png-37.3kB

需要注意的是,以上的流程是已经在经历了第一部分初始化业务之后了。

  1. 外部App需要发起一次识别操作,首先需要初始化对应的Recognizer。
  2. 通过RegionRecognizer.getInstance获取RegionRecongizer实例
  3. 由于是第一次在Client端初始化RegionRecognizer,因此会尝试与远端服务建立联系,这里就需要通过ServiceManagerNative来做桥梁
  4. 仿照第一部分初始化的流程,这里借用ProviderCaller来进行同步IPC动作,旨在获取ServiceFetcher的Proxy代理对象mServiceFetcher,该对象通过Bundle传回
  5. 通过ServiceFetcher对象获取到远程XXXXService的Binder实例
  6. 通过XXXXX.Stub.asInterfaces把Binder实例转化为本地的Proxy对象
  7. 在做具体业务recognize时,通过上面获取到的Proxy对象,调用到远程的实际Service完成对应的业务。

以上两个步骤,也是借用了Android ServiceManager的逻辑,通过在Client端建立一个Service大管家,保存各个Service的Proxy实例,使得Client端在每次使用具体Service时不用都去跑一遍IPC,以达到简化流程的目的。同时,通过ServiceFetcher对象,建立了Client端与Server端的服务映射关系。