前两天看到Service的onBind函数返回值的三种情况(扩展Binder对象,Messenger,aidl),一直在想他们内部的实现有什么不一样的,网上很多文章都介绍了Service的绑定过程,但是并没有介绍对于跨进程与非跨进程,对于不同的返回值,其具体有什么区别,以及具体是怎么实现的。这篇文章就根据源码分析Android究竟是在哪部分来控制跨进程与非跨进程Binder的传输的,Binder究竟是怎么传输的。
首先看一下Service的绑定中,Binder跨进程与非跨进程的区别代码中的体现。
Service跨进程绑定与非跨进程绑定的表象
我们都知道如果使用aidl跨进程在onServiceConnection函数中需要这样使用new TestInterface.Stub.Proxy(binder)
(TestInterface是aidl声明的接口,并且在Service的onBind中返回new TestInterface.Stub()
)。如果是普通扩展Binder对象,那么直接强制类型转换就可以了TestBinder(binder)
(TestBinder是Binder子类,并且在Service的onBind中返回new TestBinder()
)。如果想知道onServiceConnection的参数binder具体是怎么样的,其实直接在ServiceConnection的onServiceConnection回调函数中,以及在Service的onBind中分别打印一下Binder就好了,如下代码
//Service onBind
public Binder onBind(){
Binder binder ; //这里并没有初始化,可以使扩展Binder,也可以是aidl的Stub
Log.i("TestLog","onBind: "+binder.hashCode()+","+binder.toString());
return binder;
}
//ServiceConnection
ServiceConnection connection = new ServiceConnection(){
public void onServiceConnection(ComponentName component, Binder binder){
Log.i("TestLog","onServiceConnection: "+binder.hashCode()+","+binder.toString());//跨进程时会binder是一个BinderProxy对象,非跨进程时跟onBind返回的对象一模一样。
}
}
通过设置Service的android:process,可以将Service远程进程与相同进程进行实验。
通过log可以发现,如果是跨进程的话,在ServiceConnection的onServiceConnection返回的结果是一个BinderProxy对象,与onBind中打印的结果是不一致的。如果是非跨进程,在onServiceConnection与onBind的打印的内容是一模一样的。使用aidl跨进程与非跨进程,使用扩展Binder非跨进程都是一样的。这里跟onBind是返回扩展Binder,返回扩展aidl自动产生Stub类还是Messenger是没有关系的,只跟是否跨进程有关。
从这里可以看出,如果是跨进程则返回BinderProxy,非跨进程则返回原来在onBind中返回的对象。我困惑的问题是,Android是怎么实现这个根据不同的进程来返回不同的结果呢?因为是Service绑定,所以先看一下Service的绑定过程。
Service绑定过程
绑定过程
首先简单介绍一下Service的绑定过程:
1. Activity通过bindService请求绑定相应的Service(由Intent指定),并设置了ServiceConnection回调接口。
2. 实际上会调用ContextImpl.bindService,然后调用ActivityManagerNative.getDefault().bindService,也就是通过IPC调用ActivityManagerService的bindService函数,之后会调用ActiveServices的bindServiceLocked。
3. 在bindServiceLocked中,先通过retrieveServiceLocked创建ServiceRecord,这个就是对应着我们想要绑定的Service。
4. 然后根据结果创建ConnectionRecord,将ServiceConnection保存在这里面。
5. 判断指定的Service是否启动,如果没有则启动服务,通过ApplicationThreadProxy(app.thread)远程调用ApplicationThread的scheduleCreateService来发送Message给主线程消息循环(ActivityThread,ActivityThread.H),启动服务。如果是远程进程服务,ActivityManagerService会开一个新的进程(startProcessLocked),然后将Service运行在新的Process中。
6. 绑定服务,通过ApplicationThreadProxy(app.thread)远程调用ApplicationThread的scheduleBindService来发送Message给主线程消息循环(ActivityThread,ActivityThread.H),绑定服务(handleBindService)。这里看一下源码: