Android------Binder java层浅析

提示:android源码7.1

在这篇文章中我将讲解java层的binder框架,相比较native层的binder就相对比较容易理解了,毕竟很多人都用过aidl,理解起来也不会那么费劲。如果你打开源码的Binder.java和IBinder.java,一定看过前面的注释,下面是本人的翻译,可能有误,不想看的直接跳过

1>首先是Binder.java

/**
 * Base class for a remotable object, the core part of a lightweight
 * remote procedure call mechanism defined by {@link IBinder}.
 * This class is an implementation of IBinder that provides
 * standard local implementation of such an object.
它是一个远程对象的基础类,被IBinder定义的一个轻量级的远程程序调用机制,
这个类是IBinder的一个实现,它用这样一个对象提供了标准本地实现

 *

Most developers will not implement this class directly, instead using the
 * aidl tool to describe the desired
 * interface, having it generate the appropriate Binder subclass.  You can,
 * however, derive directly from Binder to implement your own custom RPC
 * protocol or simply instantiate a raw Binder object directly to use as a
 * token that can be shared across processes.
大多数的开发者不会直接实现这个类,取而代之的是用aidl工具去描述想要的接口,
用它去自动生成适当的binder子类。你可以,然而,从binder中直接提取来实现你自定义的RPC协议
或者直接简单的初始化一个未加工的Binder对象来用作一个可以在进程间共享的标记。

 *

This class is just a basic IPC primitive; it has no impact on an application's
 * lifecycle, and is valid only as long as the process that created it continues to run.
 * To use this correctly, you must be doing so within the context of a top-level
 * application component (a {@link android.app.Service}, {@link android.app.Activity},
 * or {@link android.content.ContentProvider}) that lets the system know your process
 * should remain running.


这个类是一个原始的基本IPC,他对应用的生命周期没有影响,而且仅仅当创建它的程序还在运行时
才有效。
要想正确的使用它,你必须用一个顶层的应用组件(Service,Acitivty,ContentProvider)的context来这样做
好让系统知道你的程序还在运行。
 *
 *

You must keep in mind the situations in which your process
 * could go away, and thus require that you later re-create a new Binder and re-attach
 * it when the process starts again.  For example, if you are using this within an
 * {@link android.app.Activity}, your activity's process may be killed any time the
 * activity is not started; if the activity is later re-created you will need to
 * create a new Binder and hand it back to the correct place again; you need to be
 * aware that your process may be started for another reason (for example to receive
 * a broadcast) that will not involve re-creating the activity and thus run its code
 * to create a new Binder.


 *
 * @see IBinder
 */
你必须知道你的程序会挂掉的情况,而且那会需要你稍后重新创建一个Binder,当程序再次启动后
重新链接他。举个例子,如果你用Activity使用它,这个activity的进程可能会在启动后的任何时间被杀掉;
如果这个activity稍后被重新创建,你将需要重创建一个BInder而且再次放回原来的位置;
你必须注意你的进程可能因为别的原因(例如收到一个广播)被重启,这不包含重建activity,而且会运行他的代码来创建一个Binder


2>然后是IBinder.java

/**
 * Base interface for a remotable object, the core part of a lightweight
 * remote procedure call mechanism designed for high performance when
 * performing in-process and cross-process calls.  This
 * interface describes the abstract protocol for interacting with a
 * remotable object.  Do not implement this interface directly, instead
 * extend from {@link Binder}.
远程对象的基本接口,它是一个轻量级的远程程序调用机制的核心部分,这样设计是为了高性能的
进程内和进程间调用。这个接口描述了一个远程对象交互的抽象协议,不要直接实现这个接口,转而继承Binder
 *
 *

The key IBinder API is {@link #transact transact()} matched by
 * {@link Binder#onTransact Binder.onTransact()}.  These
 * methods allow you to send a call to an IBinder object and receive a
 * call coming in to a Binder object, respectively.  This transaction API
 * is synchronous, such that a call to {@link #transact transact()} does not
 * return until the target has returned from
 * {@link Binder#onTransact Binder.onTransact()}; this is the
 * expected behavior when calling an object that exists in the local
 * process, and the underlying inter-process communication (IPC) mechanism
 * ensures that these same semantics apply when going across processes.
IBinder的核心API是transact()方法,他被Binder.onTransact()方法所匹配。
这些方法让你能发送一个调用请求给IBinder对象而且收到一个调用请求给到Binder对象,各个的。
这个事物API是同步的,就像一个transact的调用请求,他不会返回直到目标通过Binder.onTransact()返回。
这是一个期待的行为当调用一个在当前进程中存在的对象,而且这个潜在的进程内通讯机制保证了这些同样适用于
进程之间。

 *
 *

The data sent through transact() is a {@link Parcel}, a generic buffer
 * of data that also maintains some meta-data about its contents.  The meta
 * data is used to manage IBinder object references in the buffer, so that those
 * references can be maintained as the buffer moves across processes.  This
 * mechanism ensures that when an IBinder is written into a Parcel and sent to
 * another process, if that other process sends a reference to that same IBinder
 * back to the original process, then the original process will receive the
 * same IBinder object back.  These semantics allow IBinder/Binder objects to
 * be used as a unique identity (to serve as a token or for other purposes)
 * that can be managed across processes.
 *
通过transact方法传递的数据是一个Parcel,它是一个通用的缓存数据也包含了一些它内容的元数据。
这个元数据用来在缓存中管理IBinder对象的引用,以至于那些引用能被用来管理作为缓存在进程间传递。
这个机制保证了当一个IBinder对象被写入一个Parcel中而且传递给另外的进程,如果别的一些进程在同样的
IBinder中传递了一个引用返回给了原来的进程,那么原来的进程将会收到相同的IBinder对象。
这种概念让IBinder/Binder对象被作为一个唯一的身份来使用(用来作为一个象征或者其他目的)
能够在进程间被管理。
 *

The system maintains a pool of transaction threads in each process that
 * it runs in.  These threads are used to dispatch all
 * IPCs coming in from other processes.  For example, when an IPC is made from
 * process A to process B, the calling thread in A blocks in transact() as
 * it sends the transaction to process B.  The next available pool thread in
 * B receives the incoming transaction, calls Binder.onTransact() on the target
 * object, and replies with the result Parcel.  Upon receiving its result, the
 * thread in process A returns to allow its execution to continue.  In effect,
 * other processes appear to use as additional threads that you did not create
 * executing in your own process.
系统在每个程序运行的里面都管理这一个事物线程池。这些线程被用来派发来自与别的进程的所有的IPCs
举个例子,当一个IPC在A与B进程间被创建时,这个在A中调用的线程在transact()中阻塞了,当他发送事物给B进程时。下一个在B中可利用的线程收到了发来的事物,在目标对象上调用Binder.onTransact(),而且通过Parcel结果回答。当收到哦这个回答后,A中的线程又可以继续执行了。
事实上,别的进程似乎会作为额外的线程来使用,这些线程你不会在你自己的进程中去创建执行。

 *

The Binder system also supports recursion across processes.  For example
 * if process A performs a transaction to process B, and process B while
 * handling that transaction calls transact() on an IBinder that is implemented
 * in A, then the thread in A that is currently waiting for the original
 * transaction to finish will take care of calling Binder.onTransact() on the
 * object being called by B.  This ensures that the recursion semantics when
 * calling remote binder object are the same as when calling local objects.
Binder系统在进程间也会支持递归,比如,如果一个A进程执行一个事物给B进程,
当B在一个被A进程实现了的IBinder中调用transact来处理这个事物时,那么在等待原来的事物完成的
线程A会关注被B调用的对象执行Binder.onTransact()
当调用远程binder对象时同样也是当调用本地对象时就保证了递归的概念
 *
 *

When working with remote objects, you often want to find out when they
 * are no longer valid.  There are three ways this can be determined:
 *


     *
  • The {@link #transact transact()} method will throw a
     * {@link RemoteException} exception if you try to call it on an IBinder
     * whose process no longer exists.
     *
  • The {@link #pingBinder()} method can be called, and will return false
     * if the remote process no longer exists.
     *
  • The {@link #linkToDeath linkToDeath()} method can be used to register
     * a {@link DeathRecipient} with the IBinder, which will be called when its
     * containing process goes away.
     *

 *
 * @see Binder
 */

当使用远程对象时,你经常想要发现他们什么时候不再有用,下面有三个方法可以考虑:
1如果你试着在一个不再存在的进程的IBinder中调用transact()方法会抛出一个RemoteException。2.当远程进程不存在时,pingBinder()方法将被回调,而且返回错误
3.linkToDeath()方法能被用来注册一个关联IBinder的DeathRecipient,并且当它所在的进程消失后它将被回调。


这里我把要用到的java文件先列举出来:

rameworks/base/core/java/androd/os/IInterface.java

frameworks/base/core/java/android/os/BInder.java

frameworks/base/core/java/androd/os/IBinder.java

frameworks/base/core/java/androd/os/IServiceManager.java

frameworks/base/core/java/androd/os/ServiceManager.java

frameworks/base/core/java/androd/os/ServiceManagerNative.java

frameworks/base/core/java/com/android/internal/os/BinderInternal.java




本文的内容作一下梳理:

1.binder的java layer存在的意义

2.java 层的结构

3.java层的servicemanager结构分析



1》这里我先来讲讲java层binder存在的意义,第一是对下层中间件的封装,使得android应用可以参与到Binder通信当中,二是在Binder frameworks中引入了intent功能。


2》讲一下java 层的结构

在java层次,与binder相关的接口或类的关系如下:



上图中的形式在源码中经常会出现,比如我们熟知的servicemanger,但是在实际使用中,我们并不需要编写上面的XXXNative,XXXProxy,它们会由工具自动生成,用户只需要继承XXXNative编写一个具体的XXXService即可,这个XXXService就是远程通信的服务实体类,XXXProxy则是其对应的代理类。


在实际开发中,我们习惯会使用aidl,比如我们编写一个IMyService.aidl文件,构建工具会自动为我们生成一个IMyService.java文件,下面我给出aidl情况下的关系图:

Android------Binder java层浅析_第1张图片

是不是一目了然,接口IMyService会继承IInterface。IMyService.java中会生成一个抽象类IMyService.Stub,还有一个代理类IMyService.Proxy,它们都实现了IMyService接口,

IMyService.Stub还继承了Binder,在IMyService.Proxy中还会有一个mRemote对象,这个mRemote其实就是一个BInderProxy对象。

private android.os.IBInder mRemote;

Binder中有一个onTransact方法,而stub重写了这个方法,这个方法有三个重要参数,int code,Parcel data,Parcel reply,分别对应了被调函数编号,参数包,响应包。当Proxy发起一个请求,服务端中响应的响应线程会通过JNI调用到stub类,然后执行里面的execTransact方法,进而转到onTransact方法。


这里我还要提一下应用程序,应用程序框架层,系统服务三者之间的关系。

Android------Binder java层浅析_第2张图片


据我自己的理解,我觉得android从底层到上层依次为

Linux内核层------硬件抽象层------JNI层------系统服务层------Binder IPC层------应用程序框架层------app层

android中的应用程序框架层会以SDK的形式开放给开发者使用,而系统中的核心服务有的是由zygote启动的,大多数是由systemserver进程启动的,平时开发中用到的各种manager,它们都对应有自己的managerservice,比如ActivityManager,它对应的就有ActivityManagerService,它们之间就是通过binder机制通讯的,调用ActivityManager的进程和ActivityManagerService的进程并不是一个进程。










3》讲一下java层的servicemanger

前面的ServiceManager篇其实我已经讲过java层的servicemanager了,这里再继续讲的细一点。



前面的文章里我已经讲过native层的servicemanager了,java层的结构如上图所示,还有一点不够完整,IServiceManager是继承于IInterface的,抽象类ServiceManagerNative继承与Binder,实现了IServiceManager,ServiceManagerProxy实现了IServiceManager,ServiceManagerProxy的构造函数会给ServiceManagerProxy内置一个IBinder对象,实际上就是一个BinderProxy


那么是怎样拿到ServiceManager的了,是通过ServiceManager.java的getIServiceManager方法:

 private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }
是不是有似成相识的感觉,对了,它和native层获取ServiceManager的方法很相似,BinderInternal的getContextObject()方法是一个native方法,对应的是
android_util_Binder.cpp的android_os_BinderInternal_getContextObject方法,该方法和native层一样会得到一个BpBinder(0),只不过在返回的时候做了转换,转成了java层的对象。再来看下ServiceManagerNative的asInterface方法,
static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        
        return new ServiceManagerProxy(obj);
    }

这里我给你们分析一下,如果调用者与ServiceManager在同一进程,那么这个obj指的就是Binder对象,我们看下binder的queryLocalInterface方法
public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

这个descriptor是在IServiceManager中定义的

static final String descriptor = "android.os.IServiceManager";

在ServiceManagerNative的构造方法中会初始化这个值
public ServiceManagerNative()
    {
        attachInterface(this, descriptor);
    }
看下BInder的attachInterface方法
public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

mOwner是一个IInterface,这里把它赋给了ServiceManagerNative,把mDescriptor赋值为android.os.IServiceManager,这里就非常清楚了,如果是在同一进程,这里就会返回ServiceManagerNative,实际上我们的调用者是在另一进程,所以我们接着分析,看到代码是return new ServiceManagerProxy(obj);
直接返回了一个ServiceManagerProxy(obj),ServiceManagerProxy就是ServiceManager的代理接口,说白了,返回的就是一个包含了BpBinder(0)的代理接口ServiceManagerProxy。

至此,就拿到了ServiceManager,可以通过它来进行各种添加和获取操作了。


参考文献:《深入解析Android5.0系统》;《Android开发艺术探索》;《深入理解Android卷1》;《深入理解Android卷3》;;红茶一杯话binder------点击打开链接;gityuan的binder系列------点击打开链接;罗升阳的binder系列------点击打开链接;Andriod Binder机制------点击打开链接;Android深入浅出之binder机制------点击打开链接;理解Android的binder机制-----点击打开链接;轻松理解Androidbinder------点击打开链接;binder service入门------点击打开链接





你可能感兴趣的:(android,Binder)