由AMS和activityThread的交互理解binder(java层)

在ActivityThread中发现了一个ApplicationThread对象,这个对象是AMS回调app进程的binder服务端;在android的源码中IApplicationThread.aidl是一个aidl接口,android O源码编译,在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/app/目前下面找到了IApplicationThread.java和IActivityManager.java文件,
IApplicationThread.aidl文件会生成一个IApplicationThread.java文件,实际上在这个文件中主要是
public interface IApplicationThread extends android.os.IInterface {
    aidl的函数声明列表
    public static abstract class Stub extends android.os.Binder implements *.IApplicationThread {
        asInterface静态函数,返回proxy实例对象
        asBinder public函数,返回当前stub
        onTransact public函数,接收数据,调用stub的子类实现的aidl的函数
        private static class Proxy implements *.IApplicationThread {
            asBinder public函数,返回Ibinder实例
            aidl的函数实现,在这些函数里面使用ibinder对象transact发送数据给servie端
        }
    }

我靠是一个interface,并不是class;而且interface2个内部类,stub和proxy,stub是服务端的工作部分,proxy是client使用的代理。
由IActivityManager.attachApplication(mAppThread);说起,
1.IActivityManager是ams的client,在调用attachApplication方法时,会将传入的参数IApplicationThread类型,使用asBinder函数将IApplicationThread转换为stub的接口类型Ibinder,使用binder发送到AMS端,在AMS收到Ibinder对象后,使用asInterface静态函数获取IApplicationThread的client代理对象,那么AMS就获取了ApplicationThread的client端对象,使用这个对象回调到ApplicationThread进程,

实现跨进程通信。这里可以理解为在ApplicationThread端拿到AMS的client代理访问AMS,AMS拿到ApplicationThread的clinet代理访问ApplicationThread。

因此要在app层使用binder通讯,考虑activity和service binder流程注意事项:

1. 毫无疑问需要test.aidl文件

2. 为了实际意义上的跨进程通讯,需要给service指定process属性,确保service和activity不再一个进程

3.在service端,需要将service和aidl文件关联起来,为了使得二者取得联系需要继承abstract test.stub 类,并创建一个实例,在onBiner方法中返回这个实例

4.在client端,使用bindservice启动servie,在callback里面使用返回的IBinder对象作为参数,调用stub的静态方法asInterface,获取服务端在client的代理,使用这个代理直接调用aidl的方法,就可以实现跨进程调用。



基于http://blog.csdn.net/jelly_fang/article/details/50488915这个blog看了下细节

研究下bindservice究竟在做什么?
bindservice的过程分析(多进程模型下):
1.bindservice在启动进程中创建一个IServiceConnection(作为ams回调的service端)
2.binder通信将IServiceConnection发送到ams bindservice,
3.ams socket通信,Zygote启动art虚拟机进程
4.art进程binder 到ams启动app层对应的service代码(这里art进程和ams进程来回binder交互)
5.在art进程调用service的onbind方法,获取serviec 代码中实现的IBinder对象,通过binder发送给AMS
6.AMS找到IServiceConnection对象,binder到初始的启动进程中,一路回调到onServiceConnected方法,
7.启动进程的通过onServiceConnected获取到IBinder对象,使用service对应的Stub.asInterface(binder)方法获取service的proxy对象,使用proxy对象实现了跨进程通信为什么拿着IBinder不可以直接调用service的函数(需要解读binder模块的数据发送实现,才可以具体解释):
不过根据虚拟机内存区域的构成可以分析:因为类对象的方法一般保存在方法区,类对象中保存的一般都只是方法对应的地址,方法调用就是直接跳转到对应方法的地址执行;而经过binder通许后,进程切换了,继续使用前一个进程的地址来执行方法必然是非法的,因为不同进程是运行在不同的地址空间中的。保存的数据信息是可以拷贝,正常读取,但是如果是一些地址信息跨进程拷贝了实际上也是没有意义的。
client:_data.writeStrongBinder((((caller!=null))?(caller.asBinder()):(null)));
service:_arg0 = android.app.IApplicationThread.Stub.asInterface(data.readStrongBinder());

client端的数据经过binder发送后,发送对象是IBinder使用的writeStrongBinder方法,发送过去的东西到了service端即使依然是一个Ibinder对象,但是代表的含义应该有了改变,并不是原来的对象,使用这个对象去访问service的方法,必然是非法的。。


PS:发现一个可以跨进程发送消息的类Messenger 
https://www.cnblogs.com/lzjsky/p/4938256.html这个链接包含例子。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值