Android内核剖析之Binder

来源:互联网 发布:淘宝客店铺推广链接 编辑:程序博客网 时间:2024/06/07 17:14

Binder用于完成进程间通信(IPC),即把多个进程“别”在一起

Binder工作在Linux层面,属于一个驱动,这个驱动不需要硬件

 

一、Binder框架:

Binder是一个框架,提供了服务端接口,Binder驱动,客户端三个模块

 

服务端:一个Binder服务端实际上就是一个Binder类的对象,该对象一旦创建,内部就启动一个隐藏线程。该线程接下来接受Binder驱动发送来的消息,收到消息后,会执行Binder对象的onTransact()函数,并按照该函数的参数执行不同的服务代码

 

Binder驱动:任意一个服务端Binder对象被创建时,同时会在Binder驱动中创建一个Binder对象mRemote。客户端通过mRemote对象访问远程服务。

 

客户端:要想访问远程服务,必须获取远程服务在Binder对象中对应的mRemote引用。获得mRemote对象后就可以调用其transact()方法

 

 

二、onTransact(int code,Parcel data,Parcelreply,int flags)和transact(int code,Parcel data,Parcelreply,int flags)

 

code:变量用于标识期望调用服务端的那个函数

data:表示要传递给远程Binder服务的包裹

rely:用户服务端把返回的结果放入其中

flags:执行IPC调用的模式。0表示双向,服务端会返回一定的数据;1表示单向,不返回数据

 

 

三、两个问题:

1. 客户端如何获取服务端的Binder对象引用

2. 客户端和服务端必须先约定好两件事情(服务端函数的参数的顺序和函数不同的int型标识)

 bindService(Intentservice,ServiceConnection conn,int flags)

第二个参数是个interface类,该interface的定义如以下代码:

public interface ServiceConnection{

       public void  onServiceConnected(ComponentName name,IBinderservice);

       public void  onServiceDisConnected(ComponentName name)

}

当客户端请求Ams启动某个Service后,该Service如果正常启动,那么Ams就会远程调用ActivityThread类中的ApplicationThread对象,调用的参数包含Service的Binder引用,然后在ApplicationThread中会回调bindService中的conn接口。这样客户端就可以在onServiceConnected()方法中将其参数Service保存为一个全局变量。

 

关于第二个问题,Android提供了一个AIDL工具,可以将一个aidl文件转换为一个java类,这个类同时重载了onTransact()和transact()方法,统一了存入包裹和读取包裹参数。

关于AIDL:

定义了一个java 接口IXXXX

定义了一个Proxy类,该类将作为客户端访问远程服务端的代理。为了解决第二个问题——统一包裹内写入参数的顺序。

定义一个Stub类,主要由服务端来调用。继承Binder类,实现了IXXXX接口

定义了int常量,为了解决第二个问题——统一服务端函数不同的int型标识。

Stub类中,还提供了一个asInterface()函数,作用是:如果是从远程获取服务端的Binder,则会返回Binder驱动中的Binder对象(Proxy);而如果从服务端进程内部获取Binder,则会获取服务端本身的Binder对象。

 

四、ServiceManager对象

1. 在应用程序编程时,经常通过getSystemService(String serviceName)方法获取一个系统服务,那么这些系统服务的Binder引用时如何传递给客户端的呢,系统服务不是通过

startService()启动的。

2. getSystemService(StringserviceName)函数的实现是在ContextImpl类中,该函数所返回的Service比较多,这些Service一般都由ServiceManager管理

3. ServiceManager是一个独立进程,其作用是管理各种系统服务,它本身也是一个Service,可通过BinderInternal.getContextObject()获取该Service的引用,可以通过ServiceManager提供的方法获取其他系统Service的Binder引用。这种设计的好处是系统中仅仅暴露一个全局的Binder引用

4. 客户端一般不能直接通过Binder引用去访问具体的服务,而是通过一个Manager,相应的Manager类对客户端是可见的,而远程的服务类对客户端是隐藏的。简单的来说,即先通过ServiceManager获取远程服务的Binder引用,然后使用这个Binder引用去构造一个客户端本地可以访问的Manager,然后客户端可以通过该Manager去访问远程的服务。如:系统不希望用户直接去访问Ams,而是经过ActivityManager类去访问。