Binder作为Android中最主要的进程间通讯方式,它涉及到的主要有以下这几个方面
Binder通信采用了C/S架构,它和TCP/IP网络通讯有很多相似的地方。
TCP/IP网络通讯最典型的一个过程(例如访问百度首页:)如下;
Client端要访问一个域名,需要先访问DNS服务器查询域名对应的ip地址。
当然,如果Client端已经知道http地址对应的ip地址,可以跳过这一步。比如Windows系统中就内置了一个hosts文件,可以直接查询到常用网址对应的ip地址。
DNS服务端返回域名对应的ip地址。
Client连接这个ip地址,与Service端进行通讯。
其中,在这中间充当桥梁的硬件是路由器,它负责将根据ip地址选择合适的路径,将数据投递到正确的目标位置。
Binder通讯中,Binder驱动就相当于是这个路由器,ServiceManger就是DNS服务商。
智能指针在Binder中比比皆是,所以我们先来回顾下智能指针的知识。
指针
Android应用开发使用的语言主要是Java,Java和C/C++有一个很大的不同,就是Java没有指针的概念,它被Java隐藏在了底层。 C/C++中指针是非常重要的一个概念。是一把非常锋利的武器,然而这把武器用不好,就会伤到我们自己。 C/C++中指针常见的问题有这些
指针没有初始化
new对象,但用完了没有delete对象,造成内存泄漏。
野指针:我们new了一个对象A,用完也delete了这个对象A。然而,我们没有把指向A对象的指针ptr置为null,导致B对象使用这个指针时发现指针还有指向,会认为A对象依然存活着,这就会出现严重的后果。
或者ptr1和ptr2都指向对象A,我们用完对象,调用了delete删除A,也将ptr1置为null了,然而ptr2并不知道它指向的对象已经死亡了。这也会造成野指针。
从而 就出现了只能指针的需求,来解决上面的三个缺陷。
智能指针
第一个缺陷很好解决,智能指针只需要在创建时自动置为null即可。
第二点。需要在对象不被需要的时候自动的delete。
智能指针作为一个类,内部有个属性用来指向Object。
Object有一个父类RefBase,所有Object都要继承它。
RefBase包含有一个引用计数器,记录指向它的智能指针个数。并提供两个方法incCount,decCount。
每调用一次incCount,计数器+1.
每调用一次decCount,计数器-1,并且判断,当计数器为0时,delete掉Object。
每次需要智能指针指向一个Object时,内部属性指向Object的引用地址,并且调用Object的incCount。
每当智能智能不再指向一个Object时,调用Object的decCount,并且内部属性置为null。
然而这又会出现一个问题,加入当一个父对象parent指向一个子对象child,子对象又指向父对象时,这就会出现循环引用,出现问题。从而出现类强弱指针的设计思路:
Binder驱动
Binder驱动是一个标准的Linux驱动,它将自己注册成一个misc device,并向上层提供一个/dev/binder节点。 Binder节点并不对应真实的硬件设备。Binder驱动运行于内核态,可提供open()
, ioctl()
,mmap()
等常用的文件操作。
Linux中字符设备的注册需要alloc_chrdev_region()
, cedv-init()
等许多操作才能在内核中注册自己。而misc类型驱动注册相对简单,调用misc_register()
即可。
binder为上层应用提供了6个接口: binder_poll
binder_ioctl
,binder_mmap
,binder_open
,binder_flush
,binder_release
上层进程需要使用Binder驱动时,首先需要打开/dev/binder节点, 这个操作最终会调用到
binder_open()
,最终会创建binder_proc这个对象,他是一个管理数据的记录体(每个进程都有独立的记录体)。然后对proc对象进行各种初始化操作,最后将它加入到Binder的全局管理中。
目前,Binder驱动已经为用户创建了一个他自己的binder_proc实体,之后用户对Binder设备的操作将以这个对象为基础。
binder_mmap
上层用户调用mmap()
函数之后,最终会调用到binder驱动的binder_mmap
。mmap()可以将设备的指定内存块映射到应用程序的内存空间中。
那么它有什么用呢?假设有两个进程A和B
binder_open
,mmap()
得到一个虚拟内binder_open
存的地址,这个地址经过内存转换(分段,分页转换)之后会指向一个确定的物理内存地址。binder_proc->buffer
指向一个虚拟内存地址。而这个虚拟内存地址经过转换之后会和进程A指向同一个物理内存地址。copy_from_user()
将进程B中的部分数据复制到binder_proc->buffer
指向的内存空间。这样,只通过一次复制,我们就实现了A进程和B进程之间数据的共享。binder_ioctl
binder_ioctl提供了许多命令,它承载了Binder驱动的大部分业务。
说明 | 命令 |
---|---|
可以通过此命令向binder读取或写入数据 | BINDER_WRITE_READ |
设置支持的最大线程数 | BINDER_SET_MAX_THREADS |
ServiceManager专用,将自己设置为Binder的总管。 | BINDER_SET_CONTEXT_MGR |
通知Binder线程退出,每一个线程退出时都应该通知Binder驱动 | BINDER_THREAD_EXIT |
获取Binder版本号 | BINDER_VERSION |
ServiceManager
SM有点类似于网络中的DNS服务器。SM的句柄(handle)是固定的为0;
SM必须保证它在binder驱动被使用之前就要启动。所以,它的启动是在init.rc被解析时启动的。SM本身也是一个BinderServer。
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
SM流程:
给变量svcmgr赋初值,宏定义
#define BINDER_SERVICE_MANAGER ((void*) 0)
调用binder_open打开Binder设备。进行初始化。
bs = binder_open(128*1024);
struct binder_state *binder_open(unsigned mapsize)
{
struct binder_state *bs;
bs = malloc(sizeof(*bs));
...
bs->fd = open("/dev/binder", O_RDWR);//打开binder驱动节点
...
bs->mapsize = mapsize;
//将binder驱动指定内存地址的部分空间映射到SM进程所在内存空间
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
...
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return 0;
}
将自己设置为Binder大管家。
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
可以看到,像binder驱动发送了BINDER_SET_CONTEXT_MGR
SM启动很早,可以保证自己是第一个向binder驱动发送命令注册为binder管家的。
进入主循环。
binder_loop(bs, svcmgr_handler);
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//从binder驱动中获取消息
if (res < 0) {
fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
goto fail;
}
res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);//处理读到的消息
if (res == 0) return 0;
if (res < 0) goto fail;
}
循环就是典型的消息轮询机制了
SM的主要功能就是
SM中维持着一个全局的list数据结构,保存所有Binder Server的注册信息。查询是直接从这个list中进行查询即可。
注册的话,需要先在SM中查询是否已有对应节点。如果有就不需要再注册,否则需要创建一个新的节点来记录这个Binder Server的对应信息,并保存在list中。
Binder 上层的设计思路
现在,我们如何从Binder Client中获取SM这个Binder Server呢?
整体流程也就这几步:
考虑:如果每次应用程序每次使用binder都要打开binder驱动,映射空间,那么他消耗的资源会越来越多,根本吃不消。所以我们要求每个进程只能打开一次binder,映射一次空间,其中进程中的所有线程要共享这一资源。那么就需要一个对象来管理。所以出现了一个对象ProcessState。
并且所有线程都要自由访问binder驱动(Binder通讯进行时是阻塞式的), 它们之间就需要进行同步处理,所以实际上与Binder驱动进行交互的是IPCThreadState
现在我们可以获取SM了,我们可以通过发送BINDER_WRITE_READ等Binder支持的命令来与binder驱动交互,从而一步一步获得SM提供的服务。然而这样做实在太过繁琐了,那怎么办?当然是封装,这些与binder驱动的交互封装起来 对上层透明。
我们知道SM主要功能有两个getService
addService
那么我们就设计这样一个接口,将SM提供的功能定义出来。
public interface IServiceManager {
public IBinder getService(String name) throws RemoteException;
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException;
public String[] listServices() throws RemoteException;
static final String descriptor = "android.os.IServiceManager";
...
}
我们再创建一个代理类ServiceManagerProxy来远程代理ServiceManager(注意这里的代理是指代理SM这个概念的功能)的功能。就像买火车票一样,你去火车站售票窗口可以买,但是太远了。 你家附近就有一个售票代理点。 那么这个售票代理点就要和火车站的服务内容保持一致,可以查票,买票,退票。
所以ServiceManagerProxy需要继承自IServiceManager
class ServiceManagerProxy implements IServiceManager {
private IBinder mRemote;
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
public void addService(String name, IBinder service)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
...
}
使用ServiceManagerProxy来代理ServiceManager的功能可能会让某些人迷茫,native层是ServiceManager,怎么到了Java层变成了ServiceManagerProxy? 所以我们可以在ServiceManagerProxy外面再包上一层,就取名为ServiceManager
public final class ServiceManager {
private static final String TAG = "ServiceManager";
private static IServiceManager sServiceManager;
private static HashMap sCache = new HashMap();
public static void initServiceCache(Map cache) {
if (sCache.size() != 0) {
throw new IllegalStateException("setServiceCache may only be called once");
}
sCache.putAll(cache);
}
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);//首先从缓存中查找
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service);
} catch (RemoteException e) {
Log.e(TAG, “error in addService”, e);
}
}
这时,我们就可以直接使用ServiceManager.getService(name);
来获取Binder Server。
我们来看看获得SM的调用过程
ServiceManager中全都是静态方法,所以可以直接调用getService方法。
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
getService会先充cache中查找本地有没有这个IBinder对象。没有的话就会调用ServiceManagerNative.asInterface(BinderInternal.getContextObject());
来获取。
public abstract class ServiceManagerNative extends Binder implements IServiceManager{
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);
}
public ServiceManagerNative(){
attachInterface(this, descriptor);
}
...
public IBinder asBinder(){
return this;
}
}
可以看到 asInterface这个方法先调用了queryLocalInterface查询本地是否有这个对象,有的话将这个对象转为IServiceManager类型的对象返回,没有的话 new 了一个ServiceManagerProxy对象,并且使用ServiceManagerProxy中的成员变量mRemote来记录这个IBinder对象。其中ServiceManagerProxy是继承自IServiceManager接口的,所以可以直接返回。
那么这里的关键就是这个IBinder obj
了,它是从哪来的呢? 查看调用流程会发现调用
BinderInternal.getContextObject()
获得了IBinder对象,更进去会发现这是一个native的方法。说明它是和底层Binder驱动交互的,我们先不管他。
获得了IServiceManager的实现对象ServiceManagerProxy,调用了它的getService方法。
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);//最关键的一句
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
data,reply都是Parcel对象用来装载数据。 整体流程就是,将IServiceManager的描述符以及需要获得的Binder Server的名称放入data,接着调用mRote的transact方法,线程挂起,调用native层代码。等待数据返回之后,调用reply接受数据,从reply中读取到IBinder对象。 所以整个流程最关键的一句就是mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
GET_SERVICE_TRANSATION是一个常量
int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
int FIRST_CALL_TRANSACTION = 0x00000001;
而在Service_manager.c中的业务代码定义(实际定义在binder.h文件中)
enum {
SVC_MGR_GET_SERVICE = 1,
SVC_MGR_CHECK_SERVICE,
SVC_MGR_ADD_SERVICE,
SVC_MGR_LIST_SERVICES,
};
这样,客户端功能就和服务端统一了。
再探native
上一小节,我们有两个地方调用到了native层去,分别是
BinderInternal.getContextObject()
和mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
BinderInternal是获取到IBinder对象的。而mRemote实际就是一个IBinder对象。
所以IBinder接口至少有如下方法
public interface IBinder {
public IInterface queryLocalInterface(String descriptor);
public boolean transact(int code, Parcel data, Parcel reply, int flags)throws RemoteException;
...
}
而BinderInternal至少有如下方法
public class BinderInternal {
public static final native IBinder getContextObject();
...
}
其中BinderInternal的getContextObject方法native实现代码如下
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
可以看到,它调用了ProcessState的getContextObject方法,然后将ProcessState创建的对象转换为IBinder对象返给Java层。
IBinder是一个接口,那么在Java层肯定有有类实现了它,这个类就是IBinderProxy,而在natice层继承了IBinder接口的就是BpBinder。 实际上ProcessState::self()->getContextObject(NULL);
调用返回的就是一个BpBinder对象
final class BinderProxy implements IBinder {
public native String getInterfaceDescriptor() throws RemoteException;
public native boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
...
}
transact方法是一个native方法,native层对应的实现在android_util_binder中
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
...
Parcel* data = parcelForJavaObject(env, dataObj);
...
Parcel* reply = parcelForJavaObject(env, replyObj);
...
IBinder* target = (IBinder*)
env->GetIntField(obj, gBinderProxyOffsets.mObject);
...
//调用了native层IBinder的transact方法
status_t err = target->transact(code, *data, reply, flags);
...
if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
return JNI_FALSE;
}
其中data以及reply是将Java层的Parcel转化为native层的Parcel容器对象。 然后调用了native层IBinder的transact方法。而native层的IBinder接口实现为BpBinder,BpBinder中的transact方法是
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
可以看到,最后还是调用了IPCThreadState的transact方法
所以饶了一大圈,最后实现的还是IPCThreadState和ProcessState。
ProcessState和IPCThreadState
ProcessState的主要职责在于:
保证一个进程只有一个ProcessState对象存在,并且在创建对象时做打开binder驱动以及mmap内存映射。
向上层提供服务
与IPCThreadState各司其职
第一个很好解决,采用类似Java中的单例即可。
sp ProcessState::self()
{
if (gProcess != NULL) return gProcess;
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
如果当前进程有ProcessState实例,则直接返回实例。否则创建这个实例。
ProcessState的构造函数
ProcessState::ProcessState()
: mDriverFD(open_driver()), mVMStart(MAP_FAILED)
, mManagesContexts(false), mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL), mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
#if !defined(HAVE_WIN32_IPC)
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
...
}
}
其中 ,调用open_driver()打开binder驱动。调用mmap来将binder驱动部分空间映射到当前进程的内存空间。
前面我们看到Java层调用了BinderInternal.getContextObject()
来获取IBinder对象,而这个方法又调用了native方法ProcessState::self()->getContextObject(NULL);
sp ProcessState::getContextObject(const sp& caller) {
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;//需要返回的IBinder
AutoMutex _l(mLock);
//查找一个vector表。这个表保存了这个进程中已经建立的Binder相关信息
handle_entry* e = lookupHandleLocked(handle);//如果是SM,Handle为0
//如果verctor中没有找到节点,会自动创建一个。所以e一般不会为null
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle); //BpBinder创建
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
IPCThreadState需要保证线程单实例,所以他采取了TLS (Thread Loacl Storage) 机制来保证线程单实例。
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}
if (gShutdown) return NULL;
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
if (pthread_key_create(&gTLS, threadDestructor) != 0) {
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
IPCThreadState的构造函数
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(androidGetTid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
IPCThreadState主要负责与binder驱动交互,所以他的transact方法非常重要
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags){
...
}
各个参数:
handle:目前调用的是SM,所以为0; 即在ProcessState中构建BpBinder时的mHandle
code:从Java层传递过来的,为GET_SERVICE_TRANSACTION
。
data:从Java层传递过来的,Java层对data的操作为:
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
reply:Parcel类型的变量。
flags: Java层传递过来的,目前为0;
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
各个flag的意义
flags | 意义 |
---|---|
TF_ONE_WAY | 表示当前业务是异步的。不需要返回 |
TF_ROOT_OBJECT | 所包含的内容是根对象 |
TF_STATUS_CODE | 所包含的内容是32位状态值 |
TF_ACCEPT_FDS | 允许回复中包含文件描述符 |
接下来,trasact将数据按照binder协议约定的格式进行打包.
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
进行打包的函数是writeTransactionData。这个方法只是将数据整理打包,数据被存储在mOut中。
调用了waitForResponse
if ((flags & TF_ONE_WAY) == 0) {//判断上面的flag克制,代码会走到调用waitForResponse
...
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;//做一个假的reply,调用waitForResponse
err = waitForResponse(&fakeReply);
}
...
}
调用了talkWithDriver
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {//循环等待响应数据
if ((err=talkWithDriver()) < NO_ERROR) break;//处理与binder驱动的交互
err = mIn.errorCheck();
if (err < NO_ERROR) break;//出现异常就退出循环
if (mIn.dataAvail() == 0) continue; //mIn中没有数据的话,继续循环
cmd = mIn.readInt32();//从mIn中读取响应
//接下来是一个switch,根据返回的响应来决定如何处理,暂时先不看
...
}
}
看看talkWithDriver的具体实现
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (long unsigned int)mOut.data();
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsigned int)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
#if defined(HAVE_ANDROID_OS)
//调用ioctl函数与binder驱动交互
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
IF_LOG_COMMANDS() {
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
IF_LOG_COMMANDS() {
alog << "Our err: " << (void*)err << ", write consumed: "
<< bwr.write_consumed << " (of " << mOut.dataSize()
<< "), read consumed: " << bwr.read_consumed << endl;
}
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < (ssize_t)mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
alog << "Remaining data size: " << mOut.dataSize() << endl;
alog << "Received commands from driver: " << indent;
const void* cmds = mIn.data();
const void* end = mIn.data() + mIn.dataSize();
alog << HexDump(cmds, mIn.dataSize()) << endl;
while (cmds < end) cmds = printReturnCommand(alog, cmds);
alog << dedent;
}
return NO_ERROR;
}
return err;
}
在于Binder驱动进行交互中,Binder Client端会进入睡眠等待。
Binder驱动根据命令从用户空间复制数据,并且将睡眠的ServiceManger唤醒。 ServiceManager会从Binder驱动中通过消息模型读取命令,与Binder驱动交互。
ServiceManager根据读取到的数据进行处理,并将处理结果写到binder_write_read数据结构中(其中包含了查询的BinderServer的handle),然后调用ioctl与binder驱动交互,Binder驱动把数据写到mIn中,将数据从Binder Server端复制到Binder Client端。
将mIn中的数据封装到reply中,经过一系列返回, 回到Java端的ServiceManagerProxy中得getService()方法中
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
这个方法native实现是在Parcel的native实现中中
sp Parcel::readStrongBinder() const
{
sp val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
unflatten_binder的实现
status_t unflatten_binder(const sp& proc,
const Parcel& in, sp* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
//type这个属性在Service Server封装时会判断,在同一个进程时type属性为BINDER_TYPE_BINDER,不同进程时为BINDER_TYPE_HANDLE。即同一个进程直接给了要查询的binder的引用,不同进程时给的binder的句柄
switch (flat->type) {
case BINDER_TYPE_BINDER://同一个进程type类型
*out = static_cast(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE://不同的进程type类型
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
调用了getStrongProxyForHandle
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
//先从本地记录查找有没有。
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
//当本地没有这个IBinder或者给它增加引用失败,就根据handle创建一个BpBinder
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle); //
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
至此,通过getservice方法成功获得了ServiceManager的本地代理对象。
总结:
ServiceManagerProxy
ServiceManagerProxy是SM在本地的代理端。
当一个BinderServer在启动的时候,会在SM端注册自己,SM会记录它的name和handle。当调用者需要使用一个BinderServer时,通常只知道它的name。所以SM提供了查询服务来获得某个Server的handle。而SM本身也是一个Server,它的handle是固定的为0。
获得SM的本地代理对象需要调用BinderInternal.getObjectContext()来获取SM的BpBinder。在Java层就是ServiceManagerProxy
ProcessState和IPCThreadState
ProcessState负责处理与进程有关的业务,IPCThreadState负责线程有关的业务。他们是Android系统为了方便上层使用binder所封装的两个实现类.
ProcessState主要负责打开binder驱动,mmap映射binder驱动内存空间。而具体的与binder驱动的交互就交给了IPCThreadState来处理。
上面的例子中,从Java层的IBinder.transact调用到native层的IPCThreadState的transact(),然后到waitForResponse进入循环——直到收到SM端的回复之后跳出循环,然后再一层一层返回Java端。
ServiceManager
SM在系统启动时就启动了,然后将自己注册为BinderServer的管家。并在最后一次ioctl操作中进入睡眠状态,直到有Client端发起请求,然后被binder驱动唤醒。唤醒之后SM分为两条线进行
最后将返回的IBInder通过asInterface进行包装。例如返回的SM的IBInder会通过调用ServiceManagerNative的asInterface方法包装成ServiceManagerProxy对象。