您的位置:首页 > 移动开发 > Android开发

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

2017-09-02 15:55 267 查看
提示: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的一个实现,它用这样一个对象提供了标准本地实现

 * <p>Most developers will not implement this class directly, instead using the

 * <a href="{@docRoot}guide/components/aidl.html">aidl</a> 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对象来用作一个可以在进程间共享的标记。

 * <p>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.</p>

这个类是一个原始的基本IPC,他对应用的生命周期没有影响,而且仅仅当创建它的程序还在运行时

才有效。

要想正确的使用它,你必须用一个顶层的应用组件(Service,Acitivty,ContentProvider)的context来这样做

好让系统知道你的程序还在运行。

 *

 * <p>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.</p>

 *

 * @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

 *

 * <p>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()返回。

这是一个期待的行为当调用一个在当前进程中存在的对象,而且这个潜在的进程内通讯机制保证了这些同样适用于

进程之间。

 *

 * <p>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对象被作为一个唯一的身份来使用(用来作为一个象征或者其他目的)

能够在进程间被管理。

 * <p>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中的线程又可以继续执行了。

事实上,别的进程似乎会作为额外的线程来使用,这些线程你不会在你自己的进程中去创建执行。

 * <p>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对象时同样也是当调用本地对象时就保证了递归的概念

 *

 * <p>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:

 * <ul>

 * <li> 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.

 * <li> The {@link #pingBinder()} method can be called, and will return false

 * if the remote process no longer exists.

 * <li> 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.

 * </ul>

 *

 * @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情况下的关系图:



是不是一目了然,接口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从底层到上层依次为

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 源码