Android Binder框架实现之Java层Binder服务跨进程调用源码分析

   日期:2020-08-28     浏览:119    评论:0    
核心提示:Android Binder框架实现之Java层Binder服务跨进程调用源码分析前言  兜兜转转几个春秋,通过前面的博客Android Binder框架实现之Framework层Binder服务注册过程源码分析和Android Binder框架实现之Java层获取Binder服务源码分析我们终于将Android Framework层的Binder框架整体分析完毕了,而我们也可以通过ServiceManagerProxy的getService获取远程Java BInder服务的代理端IXXXServ

Android Binder框架实现之Java层Binder服务跨进程调用源码分析



前言

  兜兜转转几个春秋,通过前面的博客Android Binder框架实现之Framework层Binder服务注册过程源码分析Android Binder框架实现之Java层获取Binder服务源码分析我们终于将Android Framework层的Binder框架整体分析完毕了,而我们也可以通过ServiceManagerProxy的getService获取远程Java BInder服务的代理端IXXXServiceManagerProxy,而我恩今天的博客将来了解这最后一段逆缘,即我们获取远程Java Binder服务的的代理端IXXXServiceManagerProxy以后怎么通过它跨进程调用到Java Binder服务实体端(这里我们以AMP跨进程调用AMS为例说明)。

  • 注意:本篇的介绍是基于Android 7.xx平台为基础的,其中涉及的代码路径如下:
framework/base/core/java/android/os/
  ---IInterface.java
  ---IServiceManager.java
  ---ServiceManager.java
  ---ServiceManagerNative.java(内含ServiceManagerProxy类)

framework/base/core/java/android/os/
  ---IBinder.java
  ---Binder.java(内含BinderProxy类)
  ---Parcel.java

framework/base/core/java/com/android/internal/os/
  ---BinderInternal.java

framework/base/core/jni/
  ---AndroidRuntime.cpp
  ---android_os_Parcel.cpp
  ---android_util_Binder.cpp
  
frameworks/native/libs/binder/BpBinder.cpp
frameworks/native/include/binder/IBinder.h
frameworks/native/libs/binder/Binder.cpp
frameworks/native/include/binder/Parcel.h
frameworks/native/libs/binder/Parcel.cpp
frameworks/base/core/jni/core_jni_helpers.h
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks//base/core/java/android/app/ActivityThread.java

  • 为了后续的书写方便会将ActivityManagerService简述为AMS,ServiceManager简述为SM,ServiceManagerProxy简述为SMP,ServiceManagerNative简述为SMN,ActivityManagerProxy简称AMP, ActivityManagerNative简称AMN以上特此申明!并且在这里附上Java跨进程调用Framework Binder服务整体流程图:



一.AMP跨进程调用AMS服务流程分析


1.1 AMP服务代理端的获取

  还记得我们在前面博客中Android Binder框架实现之Java层获取Binder服务源码分析中我们以AMS服务为例,讲述了怎么获取其远程服务代理端AMP,在正式开始流程分析前我们先看看AMS的家族关系的类图结构(包括服务端和远程服务代理端的),如下:

  • 这里我们可以看到AMS服务代理端AMP继承于接口业务类IActivityManager,从而可以使第三方应用在获取到AMS远程代理端以后可以忽略跨进程调用如同使用本地对象一样使用AMS提供的业务逻辑方法。而其AMP的数据传输最后都是通过mRemote的transact方法来实现的,而这个mRemote又是AMP在构造的时候new AMP(BinderProxy(BpBidner(handle)))传入的。

  • 而我们的BinderProxy由对应的BpBinder构造而来,且BinderProxy与BpBinder相互引用,BinderProxy的transact()方法会通过JNI层调用到对应的成员变量mObject中的BpBinder的transact()方法;

  • 通过JNI层的支持,native层的JavaBBinder对象对java层的Binder持有引用,在Binder初始化时即通过JavaBBinderHolder持有了Java Binder的引用,Java Binder的引用保存在JavaBBinder的成员变量mObject中,因此AMP响应时是由JavaBBinder这个BBinder的子类通过JNI层通知上层Java Binder继而实现java层服务的响应请求。

总之关于这三者的具体关系的获取,可以参见Android Binder框架实现之Java层获取Binder服务源码分析博客,而三者之间的关系可以使用如下的示意图来表示,如下:



1.2 AMP跨进程调用AMS远程服务

//ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager
	    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
	            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
	            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
	        Parcel data = Parcel.obtain();
	        Parcel reply = Parcel.obtain();
	        data.writeInterfaceToken(IActivityManager.descriptor);
	        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
			..
			//这里的mRemote指向BinderProxy
	        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
	        ...
	        reply.readException();
	        int result = reply.readInt();
	        reply.recycle();
	        data.recycle();
	        return result;
	    }
}

  这里我们以AMP的startActivity方法的跨进程调度为例,这个流程和前面博客Java层获取Binder服务的调度逻辑是一样的,其基本操作逻辑如下:

  • 先执行BinderProxy对象的transact()方法通过JNI层的传递调用到Native层中对应的BpBinder(handle)的transact()方法
  • 接下来就是通过BpBinder中的IPCThreadState与Binder驱动进行交互了

上述的流程我们已经烂熟于心了,这个不是重点,重点是AMS怎么获取Binder服务传递过来的信息,并相应服务请求!


1.2 AMS服务怎么影响远程端调度请求

  在前面的博客 Android系统启动之SystemServer大揭秘中我们分析到了在system_server进程的其中过程中会调用如下的代码逻辑:

	//app_main.cpp
    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//开启binder线程,是不是有中似曾相识的熟悉感觉
    }

ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver(),在binder系列文章中Android Binder框架实现之Binder服务的消息循环有关于该部分的详细的讲解,这里就不过多阐述了。这样将当前线程注册到Binder驱动程序中,这样我们创建的线程就加入了Binder线程池中,这样新创建的system_server进程就支持Binder进程间通信了。即我们system_server进程中IPCThread线程会不断向Binder驱动查看是否有请求数据的到来,而此时AMP的数据通过Binder驱动传递过来了,我们的AMS服务的进程就会通过IPCThread线程接收到。至于这其中的复杂调用逻辑过程,就不是本篇的重点可以参见Android Binder框架实现之之Binder Native Service的Java调用流程

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服