Android Binder跨进程与非跨进程的传输异同源码分析

前两天看到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)。这里看一下源码:


                
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值