简介
Binder是基于开源的OpenBinder实现的,OpenBinder最早并不是由Google公司开发的,而是Be Inc公司开发的,接着由Palm, Inc.公司负责开发。后来OpenBinder的作者Dianne Hackborn加入了Google公司,并负责Android平台的开发工作,顺便把这项技术也带进了Android。
Binder是基于内存映射来实现的,在前面我们知道内存映射通常是用在有物理介质的文件系统上的,Binder没有物理介质,它使用内存映射是为了跨进程传递数据。
Binder 原理是掌握系统底层原理的基石。
- 直观来说,Bindr 是 Android 中的一个类,它实现了 IBinder 接口。
- 从 IPC 角度来说,是 Android 中的一种跨进程通信方式。
- 还可以理解为一种虚拟的物理设备,它的设备驱动是 /dev/binder,该通信方式在 Linux 中没有。
- 从 Android Framework 角度来说,是 ServiceManager 连接各种 Manager 和相应 ManagerService 的桥梁。
- 从 Android 应用层来说,是客户端和服务端进行通信的媒介,当 bindService 时,服务端会返回一个包含了服务端业务调用的 Binder 对象,通过这个 Binder 对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于 AIDL 的服务。
Binder通信的步骤如下所示。
1.Binder驱动在内核空间创建一个数据接收缓存区。
2.在内核空间开辟一块内核缓存区,建立内核缓存区和数据接收缓存区之间的映射关系,以及数据接收缓存区和接收进程用户空间地址的映射关系。
3.发送方进程通过copy_from_user()函数将数据拷贝 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
整个过程只使用了1次拷贝,不会因为不知道数据的大小而浪费空间或者时间,效率更高。
Binder 的工作机制:
- 客户端发起远程请求给 Binder。
- Binder(内部类 Stub)写入参数(如果有参数)到 data 中。
- 接着调用 transact 方法发起 RPC(远程过程调用)请求,同时线程被挂起。
- 然后服务端的 onTransact 方法会被调用,会从 data 中取出目标方法所需参数(如果目标方法有参数),最终向 reply 中写入结果(如果有返回值)。
- 然后返回数据,唤醒 Client。
Binder 的死亡代理:
Binder 运行在服务端进程,当服务端进程由于某种原因异常终止,这个时候我们到服务端的 Binder 连接断裂(称之为 Binder 死亡),会导致远程调用失败。
可通过 linkToDeath 和 unlinkToDeath 来实现。为 Binder 设置一个死亡代理。
为什么要使用Binder
Android是基于Linux内核的 ,Linux提供了很多IPC机制,而Android却自己设计了Binder来进行通信,主要是因为以下几点。
性能方面
性能方面主要影响的因素是拷贝次数,管道、消息队列、Socket的拷贝次书都是两次,性能不是很好,共享内存不需要拷贝,性能最好,Binder的拷贝次书为1次,性能仅次于内存拷贝。
稳定性方面
Binder是基于C/S架构的,这个架构通常采用两层结构,在技术上已经很成熟了,稳定性是没有问题的。共享内存没有分层,难以控制,并发同步访问临界资源时,可能还会产生死锁。从稳定性的角度讲,Binder是优于共享内存的。
安全方面
Android是一个开源的系统,并且拥有开放性的平台,市场上应用来源很广,因此安全性对于Android 平台而言极其重要。
传统的IPC接收方无法获得对方可靠的进程用户ID/进程ID(UID/PID),无法鉴别对方身份。Android 为每个安装好的APP分配了自己的UID,通过进程的UID来鉴别进程身份。另外,Android系统中的Server端会判断UID/PID是否满足访问权限,而对外只暴露Client端,加强了系统的安全性。
语言方面
Linux是基于C语言,C语言是面向过程的,Android应用层和Java Framework是基于Java语言,Java语言是面向对象的。Binder本身符合面向对象的思想,因此作为Android的通信机制更合适不过。
从这四方面来看,Linux提供的大部分IPC机制根本无法和Binder相比较,而共享内存只在性能方面优于Binder,其他方面都劣于Binder,这些就是为什么Android要使用Binder来进行进程间通信,当然系统中并不是所有的进程通信都是采用了Binder,而是根据场景选择最合适的,比如Zygote进程与AMS通信使用的是Socket,Kill Process采用的是信号。
为什么要学习Binder
Binder机制在Android中的地位举足轻重,我们需要掌握的很多原理都和Binder有关:
- 系统中的各个进程是如何通信的?
- Android系统启动过程
- AMS、PMS的原理
- 四大组件的原理,比如Activity是如何启动的?
- 插件化原理
- 系统服务的Client端和Server端是如何通信的?(比如MediaPlayer和MeidaPlayerService)
上面只是列了一小部分,简单来说说,比如系统在启动时,SystemServer进程启动后会创建Binder线程池,目的是通过Binder,使得在SystemServer进程中的服务可以和其他进程进行通信了。再比如我们常说的AMS、PMS都是基于Binder来实现的,拿PMS来说,PMS运行在SystemServer进程,如果它想要和DefaultContainerService通信(是用于检查和复制可移动文件的系统服务),就需要通过Binder,因为DefaultContainerService运行在com.android.defcontainer进程。
还有一个比较常见的C/S架构间通信的问题,Client端的MediaPlayer和Server端的MeidaPlayerService不是运行在一个进程中的,同样需要Binder来实现通信。
可以说Binder机制是掌握系统底层原理的基石。根据Android系统的分层,Binder机制主要分为以下几个部分,其中Java Binder和Native Binder都是应用开发需要掌握的。Java Binder是需要借助Native Binder来工作的,因此需要先了解Native Binder,Native Binder架构的原型就是基于Binder通信的C/S架构。
ServiceManager中的Binder机制
基于Binder通信的C/S架构
在Android系统中,Binder进程间的通信的使用是很普遍的,比如MediaPlayer框架基于C/S架构,并采用Binder来进行进程间通信,如下图所示。
从图中可以看出,除了常规C/S架构的Client端和Server端,还包括了ServiceManager,它用于管理系统中的服务。
首先Server进程会注册一些Service到ServiceManager中,Client要使用某个Service,则需要先到ServiceManager查询Service的相关信息,然后根据Service的相关信息与Service所在的Server进程建立通信通路,这样Client就可以使用Service了。
MediaServer的main函数
Client、Server、ServiceManager三者的交互都是基于Binder通信的,那么任意两者的交互都可以说明Binder的通信的原理,可以说Native Binder的原理的核心就是ServiceManager的原理,为了更好的了解ServiceManager,这里拿MediaPlayer框架来举例,它也是学习多媒体时必须要掌握的知识点。MediaPlayer框架的简单框架图如下所示。
可以看到,MediaPlayer和MediaPlayerService是通过Binder来进行通信的,MediaPlayer是Client端,MediaPlayerService是Server端,MediaPlayerService是系统多媒体服务的一种,系统多媒体服务是由一个叫做MediaServer的服务进程提供的,它是一个可执行程序,在Android系统启动时,MediaServer也被启动,它的入口函数如下所示。main_mediaserver.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(defaultServiceManager()); ALOGI("ServiceManager: %p", sm.get()); InitializeIcuOrDie(); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); registerExtensions(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
|
每个进程唯一的ProcessState
ProcessState用于代表进程的状态,在MediaServer的入口函数中调用了ProcessState::self(),查看ProcessState的self函数。ProcessState.cpp
1 2 3 4 5 6 7 8 9 10 11
| sp<ProcessState> ProcessState::self() { Mutex::Autolock _l(gProcessMutex); if (gProcess != NULL) { return gProcess; } gProcess = new ProcessState("/dev/binder"); return gProcess; }
|
接着来查看ProcessState的构造函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| ProcessState::ProcessState(const char *driver) : mDriverName(String8(driver)) , mDriverFD(open_driver(driver)) , mVMStart(MAP_FAILED) , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER) , mThreadCountDecrement(PTHREAD_COND_INITIALIZER) , mExecutingThreadsCount(0) , mMaxThreads(DEFAULT_MAX_BINDER_THREADS) , mStarvationStartTimeMs(0) , mManagesContexts(false) , mBinderContextCheckFunc(NULL) , mBinderContextUserData(NULL) , mThreadPoolStarted(false) , mThreadPoolSeq(1) { if (mDriverFD >= 0) { mmap函数用于对Binder设备进行内存映射,除了它还有open、ioctl函数,来看看它们做了什么。 mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str()); close(mDriverFD); mDriverFD = -1; mDriverName.clear(); } } LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating."); }
|
查看打开/dev/binder设备的open_driver函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| static int open_driver(const char *driver) { int fd = open(driver, O_RDWR | O_CLOEXEC); if (fd >= 0) { ... size_t maxThreads = DEFAULT_MAX_BINDER_THREADS; result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); if (result == -1) { ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); } } else { ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno)); } return fd; }
|
ProcessState总的来说它做了以下几个重要的事:
1.打开/dev/binder设备并设定Binder最大的支持线程数。
2.通过mmap为binder分配一块虚拟地址空间,达到内存映射的目的。
ServiceManager中的Binder机制
在MediaServer的入口函数中调用了defaultServiceManager函数。IServiceManager.cpp。
从IServiceManager所在的文件路径就可以知道,其中不仅仅使用了Binder通信,它自身也是属于Binder体系的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| sp<IServiceManager> defaultServiceManager() { if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{ AutoMutex _l(gDefaultServiceManagerLock); while (gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL)); if (gDefaultServiceManager == NULL) sleep(1); } }
return gDefaultServiceManager; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& ) { return getStrongProxyForHandle(0); }
...
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { if (handle == 0) { Parcel data; status_t status = IPCThreadState::self()->transact( 0, IBinder::PING_TRANSACTION, data, NULL, 0); if (status == DEAD_OBJECT) return NULL; } b = BpBinder::create(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result; }
|
BpBinder和BBinder
它们是Binder通信的“双子星”,都继承了IBinder。BpBinder是Client端与Server交互的代理类,而BBinder则代表了Server端。BpBinder和BBinder是一一对应的,BpBinder会通过handle来找到对应的BBinder。(在ServiceManager中创建了BpBinder,通过handle(值为0)可以找到对应的BBinder。)
回到interface_cast函数,其具体实现如下。IInterface.h
1 2 3 4 5
| template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
|
当前的场景中,INTERFACE的值为IServiceManager,那么替换后代码如下所示。
1 2 3 4
| inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj) { return IServiceManager::asInterface(obj); }
|
解密IServiceManager
BpBinder和BBinder负责Binder的通信,而 IServiceManager 用于处理 ServiceManager 的业务。IServiceManager.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class IServiceManager : public IInterface { public: DECLARE_META_INTERFACE(ServiceManager) ... virtual sp<IBinder> getService( const String16& name) const = 0; virtual sp<IBinder> checkService( const String16& name) const = 0; virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated = false, int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0; virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0; enum { GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, CHECK_SERVICE_TRANSACTION, ADD_SERVICE_TRANSACTION, LIST_SERVICES_TRANSACTION, }; };
|
查看 IInterface.h。IInterface.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #define DECLARE_META_INTERFACE(INTERFACE) \ static const ::android::String16 descriptor; \ static ::android::sp<I##INTERFACE> asInterface( \ const ::android::sp<::android::IBinder>& obj); \ virtual const ::android::String16& getInterfaceDescriptor() const; \ I##INTERFACE(); \ virtual ~I##INTERFACE(); \
#define DECLARE_META_INTERFACE(INTERFACE) static const ::android::String16 descriptor;
static ::android::sp<IServiceManager> asInterface( const ::android::sp<::android::IBinder>& obj); virtual const ::android::String16& getInterfaceDescriptor() const;
IServiceManager();
virtual ~IServiceManager();
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const ::android::String16 I##INTERFACE::descriptor(NAME); \ const ::android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const ::android::sp<::android::IBinder>& obj) \ { \ ::android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } \
|
DECLARE_META_INTERFACE 宏和 IMPLEMENT_META_INTERFACE 宏是配合使用的,很多系统服务都使用了它们,IServiceManager 使用 IMPLEMENT_META_INTERFACE 宏只有一行代码,如下所示。
1
| IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
|
IMPLEMENT_META_INTERFACE 宏的 INTERFACE 值为 ServiceManager,NAME 值为 ”android.os.IServiceManager”,进行替换后的代码如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) const ::android::String16 IServiceManager::descriptor(”android.os.IServiceManager”); const ::android::String16& IServiceManager::getInterfaceDescriptor() const { return IServiceManager::descriptor; }
::android::sp<IServiceManager> IServiceManager::asInterface( const ::android::sp<::android::IBinder>& obj) { ::android::sp<IServiceManager> intr; if (obj != NULL) { intr = static_cast<IServiceManager*>( obj->queryLocalInterface( IServiceManager::descriptor).get()); if (intr == NULL) { intr = new BpServiceManager(obj); } } return intr; } IServiceManager::IServiceManager() { } IServiceManager::~IServiceManager() { }
|
从上面代码可知,asInterface 函数就是用 BpBinder 为参数创建了 BpServiceManager,从而推断出interface_cast 函数创建了BpServiceManager,再往上推断,IServiceManager 的 defaultServiceManager 函数返回的就是 BpServiceManager。BpServiceManager有什么作用呢,先从BpServiceManager的构造函数看起。
1 2 3 4 5 6 7 8 9 10
| class BpServiceManager : public BpInterface<IServiceManager> { public: explicit BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(impl) { } ... };
|
BpInterface 继承了 BpRefBase,BpRefBase 的实现如下所示。Binder.cpp
1 2 3 4 5 6 7 8 9 10 11
| BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(NULL), mState(0) { extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) { mRemote->incStrong(this); mRefs = mRemote->createWeak(this); } }
|
IServiceManager家族
1.BpBinder和BBinder都和通信有关,它们都继承自IBinder。
2.BpServiceManager派生自IServiceManager,它们都和业务有关。
3.BpRefBase包含了mRemote,通过不断的派生,BpServiceManager也同样包含mRemote,它指向了BpBinder,通过BpBinder来实现通信。
小节
本篇文章我们学到了Binder通信的C/S架构,也知道了Native Binder的原理的核心其实就是ServiceManager的原理,为了讲解ServiceManager的原理,我们需要一个框架来举例,那就是MediaPlayer框架。在讲解MediaServer的入口函数时,我们遇到了三个问题,其中前两个问题相关的知识点ProcessState和IServiceManager都讲解到了,下一篇文章会讲解第三个问题,MediaPlayerService是如何注册的。
系统服务的注册过程
接下来从调用链角度和进程角度来讲解MediaPlayerService是如何注册的,间接的得出了系统服务是如何注册的
。这里分别对这两个角度做了简化,作为应用开发,我们不需要注重太多的过程和细节,只需要了解大概的步骤即可。
先来看MediaServer的入口函数,代码如下所示。main_mediaserver.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(defaultServiceManager()); ALOGI("ServiceManager: %p", sm.get()); InitializeIcuOrDie(); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); registerExtensions(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
|
查看 MediaPlayerService 的 注册过程。MediaPlayerService.cpp
1 2 3 4 5 6
| void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); }
|
查看 addService 方法。IServiceManager.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13
| virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated, int dumpsysPriority) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); data.writeInt32(dumpsysPriority); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }
|
查看 transact 函数。BpBinder.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13
| status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 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::self()。IPCThreadState.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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; } ... pthread_mutex_unlock(&gTLSMutex); goto restart; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { pthread_setspecific(gTLS, this); clearCaller(); mIn.setDataCapacity(256); mOut.setDataCapacity(256); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err;
flags |= TF_ACCEPT_FDS; ... err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
if (err != NO_ERROR) { if (reply) reply->setError(err); return (mLastError = err); }
if ((flags & TF_ONE_WAY) == 0) { ... if (reply) { err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } ... } else { err = waitForResponse(NULL, NULL); } return err; }
|
writeTransactionData函数分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) { binder_transaction_data tr; tr.target.ptr = 0; tr.target.handle = handle; tr.code = code; tr.flags = binderFlags; tr.cookie = 0; tr.sender_pid = 0; tr.sender_euid = 0;
const status_t err = data.errorCheck(); if (err == NO_ERROR) { tr.data_size = data.ipcDataSize(); tr.data.ptr.buffer = data.ipcData(); tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); tr.data.ptr.offsets = data.ipcObjects(); } else if (statusBuffer) { tr.flags |= TF_STATUS_CODE; *statusBuffer = err; tr.data_size = sizeof(status_t); tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer); tr.offsets_size = 0; tr.data.ptr.offsets = 0; } else { return (mLastError = err); }
mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr));
return NO_ERROR; }
|
waitForResponse函数分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { uint32_t cmd; int32_t err; while (1) { if ((err=talkWithDriver()) < NO_ERROR) break; err = mIn.errorCheck(); if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
IF_LOG_COMMANDS() { alog << "Processing waitForResponse Command: " << getReturnString(cmd) << endl; }
switch (cmd) { case BR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish; break;
case BR_DEAD_REPLY: err = DEAD_OBJECT; goto finish; ... default: err = executeCommand(cmd); if (err != NO_ERROR) goto finish; break; } } finish: ... return err; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
status_t IPCThreadState::talkWithDriver(bool doReceive) { if (mProcess->mDriverFD <= 0) { return -EBADF; }
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 = (uintptr_t)mOut.data(); if (doReceive && needRead) { bwr.read_size = mIn.dataCapacity(); bwr.read_buffer = (uintptr_t)mIn.data(); } else { bwr.read_size = 0; bwr.read_buffer = 0; } ... if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0; bwr.read_consumed = 0; status_t err; do { IF_LOG_COMMANDS() { alog << "About to read/write, write size = " << mOut.dataSize() << endl; } #if defined(__ANDROID__)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; #else err = INVALID_OPERATION; #endif ... } while (err == -EINTR); ... return err; }
|
小节
从调用链的角度来看,MediaPlayerService是如何注册的貌似并不复杂,因为这里只是简单的介绍了一个调用链分支,可以简单的总结为以下几个步骤:
- addService函数将数据打包发送给BpBinder来进行处理。
- BpBinder新建一个IPCThreadState对象,并将通信的任务交给IPCThreadState。
- IPCThreadState的writeTransactionData函数用于将命令协议和数据写入到mOut中。
- IPCThreadState的waitForResponse函数主要做了两件事,一件事是通过ioctl函数操作mOut和mIn来与Binder驱动进行数据交互,另一件事是处理各种命令协议。
实际上MediaPlayerService的注册还涉及到了进程。
从图中看出是以C/S架构为基础,addService是在MediaPlayerService进行的,它是Client端,用于请求添加系统服务。而Server端则是指的是ServiceManager,用于完成系统服务的添加。
Client端和Server端分别运行在两个进程中,通过向Binder来进行通信。更详细点描述,就是两端通过向Binder驱动发送命令协议来完成系统服务的添加。这其中命令协议非常多,过程也比较复杂,这里对命令协议进行了简化,只涉及到了四个命令协议,其中
BC_TRANSACTION和BR_TRANSACTION过程是一个完整的事务,BC_REPLY和BRREPLY是一个完整的事务。
Client端和Server端向Binder驱动发送命令协议以BC开头,而Binder驱动向Client端和Server端返回的命令协议以BR开头。
步骤如下所示:
1.Client端向Binder驱动发送BC_TRANSACTION命令。
2.Binder驱动接收到请求后生成BR_TRANSACTION命令,唤醒Server端的线程后将BR_TRANSACTION命令发送给ServiceManager。
3.Server端中的服务注册完成后,生成BC_REPLY命令发送给Binder驱动。
4.Binder驱动生成BR_REPLY命令,唤醒Client端的线程后将BR_REPLY命令发送个Client端。
通过这些协议命令来驱动并完成系统服务的注册。
ServiceManager的启动过程
ServiceManager的启动过程实际上就是分析ServiceManager的入口函数,在入口函数中主要做了三件事。
ServiceManager的入口函数
ServiceManager是init进程负责启动的,具体是在解析init.rc配置文件时启动的,init进程是在系统启动时启动的,因此ServiceManager亦是如此。
rc文件内部由Android初始化语言编写(Android Init Language)编写的脚本,它主要包含五种类型语句:Action、Commands、Services、Options和Import。
在Android 7.0中对init.rc文件进行了拆分,每个服务一个rc文件。ServiceManager的启动脚本在servicemanager.rc中。servicemanager.rc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| service servicemanager /system/bin/servicemanager class core user system group system readproc critical onrestart restart healthd onrestart restart zygote onrestart restart audioserver onrestart restart media onrestart restart surfaceflinger onrestart restart inputflinger onrestart restart drm onrestart restart cameraserver writepid /dev/cpuset/system-background/tasks
|
servicemanager的入口函数在service_manager.c中。service_manager.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| int main(int argc, char** argv) {
struct binder_state *bs; union selinux_callback cb; char *driver;
if (argc > 1) { driver = argv[1]; } else { driver = "/dev/binder"; }
bs = binder_open(driver, 128*1024); ...
if (binder_become_context_manager(bs)) { ALOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } ... if (getcon(&service_manager_context) != 0) { ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); abort(); } binder_loop(bs, svcmgr_handler); return 0; }
|
打开binder设备
binder_open函数用于打开binder设备文件,并且将它映射到进程的地址空间,如下所示。binder.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| struct binder_state *binder_open(const char* driver, size_t mapsize) { struct binder_state *bs; struct binder_version vers;
bs = malloc(sizeof(*bs)); if (!bs) { errno = ENOMEM; return NULL; }
bs->fd = open(driver, O_RDWR | O_CLOEXEC); if (bs->fd < 0) { fprintf(stderr,"binder: cannot open %s (%s)\n", driver, strerror(errno)); goto fail_open; }
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { fprintf(stderr, "binder: kernel driver version (%d) differs from user space version (%d)\n", vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); goto fail_open; }
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); if (bs->mapped == MAP_FAILED) { fprintf(stderr,"binder: cannot map device (%s)\n", strerror(errno)); goto fail_map; }
return bs;
fail_map: close(bs->fd); fail_open: free(bs); return NULL; }
|
用户态和内核态
临时插入一个知识点:用户态和内核态
Intel的X86架构的CPU提供了0到3四个特权级,数字越小,权限越高,Linux操作系统中主要采用了0和3两个特权级,分别对应的就是内核态与用户态。用户态的特权级别低,因此进程在用户态下不经过系统调用是无法主动访问到内核空间中的数据的,这样用户无法随意的进入所有进程共享的内核空间,起到了保护的作用。下面来介绍下什么是用户态和内核态。
当一个进程在执行用户自己的代码时处于用户态,比如open函数,它运行在用户空间,当前的进程处于用户态。
当一个进程因为系统调用进入内核代码中执行时就处于内核态,比如open函数通过系统调用(__open()函数),查找到了open函数在Kernel Binder对应的函数为binder_open,这时binder_open运行在内核空间,当前的进程由用户态切换到内核态。
kernel/goldfish/drivers/staging/android/binder.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc; binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", current->group_leader->pid, current->pid); proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (proc == NULL) return -ENOMEM; get_task_struct(current); proc->tsk = current; INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); binder_lock(__func__);
binder_stats_created(BINDER_STAT_PROC); hlist_add_head(&proc->proc_node, &binder_procs); proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); filp->private_data = proc; binder_unlock(__func__); ... return 0; }
|
注册成为Binder机制的上下文管理者
binder_become_context_manager函数用于将servicemanager注册成为Binder机制的上下文管理者,这个管理者在整个系统只有一个,代码如下所示。binder.c
1 2 3 4 5
| int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }
|
binder_ioctl函数代码比较多,这里截取BINDER_SET_CONTEXT_MGR的处理部分,代码如下所示。
kernel/goldfish/drivers/staging/android/binder.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; struct binder_proc *proc = filp->private_data; struct binder_thread *thread; unsigned int size = _IOC_SIZE(cmd); void __user *ubuf = (void __user *)arg; trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret) goto err_unlocked;
binder_lock(__func__); thread = binder_get_thread(proc); if (thread == NULL) { ret = -ENOMEM; goto err; }
switch (cmd) { ... case BINDER_SET_CONTEXT_MGR: if (binder_context_mgr_node != NULL) { printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n"); ret = -EBUSY; goto err; } ret = security_binder_set_context_mgr(proc->tsk); if (ret < 0) goto err; if (binder_context_mgr_uid != -1) { if (binder_context_mgr_uid != current->cred->euid) { printk(KERN_ERR "binder: BINDER_SET_" "CONTEXT_MGR bad uid %d != %d\n", current->cred->euid, binder_context_mgr_uid); ret = -EPERM; goto err; } } else binder_context_mgr_uid = current->cred->euid; binder_context_mgr_node = binder_new_node(proc, NULL, NULL); if (binder_context_mgr_node == NULL) { ret = -ENOMEM; goto err; } binder_context_mgr_node->local_weak_refs++; binder_context_mgr_node->local_strong_refs++; binder_context_mgr_node->has_strong_ref = 1; binder_context_mgr_node->has_weak_ref = 1; break; ... err_unlocked: trace_binder_ioctl_done(ret); return ret; }
|
循环等待和处理client端发来的请求
servicemanager成功注册成为Binder机制的上下文管理者后,servicemanager就是Binder机制的“总管”了,它需要在系统运行期间处理client端的请求,由于client端的请求不确定何时发送,因此需要通过无限循环来实现,实现这一需求的函数就是binder_loop。binder.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void binder_loop(struct binder_state *bs, binder_handler func) { int res; struct binder_write_read bwr; uint32_t readbuf[32];
bwr.write_size = 0; bwr.write_consumed = 0; bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER; binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) { ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; }
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); if (res == 0) { ALOGE("binder_loop: unexpected reply?!\n"); break; } if (res < 0) { ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); break; } } }
|
由于binder_write函数的调用链中涉及到了内核空间和用户空间的交互,因此这里着重讲解下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int binder_write(struct binder_state *bs, void *data, size_t len) { struct binder_write_read bwr; int res;
bwr.write_size = len; bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data; bwr.read_size = 0; bwr.read_consumed = 0; bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); if (res < 0) { fprintf(stderr,"binder_write: ioctl failed (%s)\n", strerror(errno)); } return res; }
|
ioctl函数在Kernel Binder中对应的函数为binder_ioctl,此前分析过这个函数,这里截取BINDER_WRITE_READ命令处理部分。
kernel/goldfish/drivers/staging/android/binder.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { ... void __user *ubuf = (void __user *)arg; ... switch (cmd) { case BINDER_WRITE_READ: { struct binder_write_read bwr; if (size != sizeof(struct binder_write_read)) { ret = -EINVAL; goto err; } if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { ret = -EFAULT; goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer);
if (bwr.write_size > 0) { ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); trace_binder_write_done(ret); if (ret < 0) { bwr.read_consumed = 0; if (copy_to_user(ubuf, &bwr, sizeof(bwr))) ret = -EFAULT; goto err; } } ... binder_debug(BINDER_DEBUG_READ_WRITE, "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n", proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { ret = -EFAULT; goto err; } break; } ... return ret; }
|
系统服务的获取过程
此前以MediaPlayerService为例,讲解了系统服务是如何注册的(addService),既然有注册那肯定也要有获取,仍旧以MediaPlayerService为例,来讲解系统服务的获取过程(getService)。会分为两个部分进行讲解,分别是客户端MediaPlayerService请求获取服务和服务端ServiceManager处理请求。
要想获取MediaPlayerService,需要先调用getMediaPlayerService函数,如下所示。IMediaDeathNotifier.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| IMediaDeathNotifier::getMediaPlayerService() { ALOGV("getMediaPlayerService"); Mutex::Autolock _l(sServiceLock); if (sMediaPlayerService == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.player")); if (binder != 0) { break; } ALOGW("Media player service not published, waiting..."); usleep(500000); } while (true);
if (sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } binder->linkToDeath(sDeathNotifier); sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); } ALOGE_IF(sMediaPlayerService == 0, "no media player service!?"); return sMediaPlayerService; }
|
获取服务是重点,BpServiceManager的getService函数如下所示。IServiceManager.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class BpServiceManager : public BpInterface<IServiceManager> { ... virtual sp<IBinder> getService(const String16& name) const { ... int n = 0; while (uptimeMillis() < timeout) { n++; if (isVendorService) { ALOGI("Waiting for vendor service %s...", String8(name).string()); CallStack stack(LOG_TAG); } else if (n%10 == 0) { ALOGI("Waiting for service %s...", String8(name).string()); } usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name); if (svc != NULL) return svc; } ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); return NULL; } ... };
|
getService函数中主要做的事就是循环的查询服务是否存在,如果不存在就继续查询,查询服务用到了checkService函数,代码如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class BpServiceManager : public BpInterface<IServiceManager> { ... virtual sp<IBinder> checkService( const String16& name) const { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); return reply.readStrongBinder(); } ... };
|
BpBinder的transact函数如下所示。BpBinder.cpp
1 2 3 4 5 6 7 8 9 10 11 12
| status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { if (mAlive) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; }
return DEAD_OBJECT; }
|
BpBinder 将逻辑处理交给 IPCThreadState,后面的调用链在此前的系统服务的注册过程中有讲,最后会调用到talkWithDriver函数,其内部通过ioctl与Binder驱动进行通信。
当前分析的是客户端进程的流程,当MediaPlayerService向Binder驱动发送BC_TRANSACTION命令后,Binder驱动会向ServiceManager发送BR_TRANSACTION命令,接下来查看服务端ServiceManager是如何处理获取服务这一请求的。
服务端ServiceManager处理请求
说到服务端ServiceManager处理请求,不得不说到ServiceManager的启动过程,在 servicemanager 的入口 man 函数中主要做了三件事,其中最后一件事就是调用binder_loop函数,这里需要注意,它的第二个参数为svcmgr_handler。
binder_loop函数在无限循环中不断的调用ioctl函数,它不断的使用BINDER_WRITE_READ指令查询Binder驱动中是否有新的请求,如果有就交给binder_parse函数处理。如果没有,当前线程就会在Binder驱动中睡眠,等待新的进程间通信请求。binder_parse函数如下所示。binder.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| int binder_parse(struct binder_state *bs, struct binder_io *bio, uintptr_t ptr, size_t size, binder_handler func) { int r = 1; uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end) { uint32_t cmd = *(uint32_t *) ptr; ptr += sizeof(uint32_t); #if TRACE fprintf(stderr,"%s:\n", cmd_name(cmd)); #endif switch(cmd) { ... case BR_TRANSACTION: { struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; if ((end - ptr) < sizeof(*txn)) { ALOGE("parse: txn too small!\n"); return -1; } binder_dump_txn(txn); if (func) { unsigned rdata[256/4]; struct binder_io msg; struct binder_io reply; int res;
bio_init(&reply, rdata, sizeof(rdata), 4); bio_init_from_txn(&msg, txn); res = func(bs, txn, &msg, &reply); if (txn->flags & TF_ONE_WAY) { binder_free_buffer(bs, txn->data.ptr.buffer); } else { binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); } } ptr += sizeof(*txn); break; } ... } return r; }
|
查看 svcmgr_handler 。 service_manager.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| int svcmgr_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) { ... switch(txn->code) { case SVC_MGR_GET_SERVICE: case SVC_MGR_CHECK_SERVICE: s = bio_get_string16(msg, &len); if (s == NULL) { return -1; } handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid); if (!handle) break; bio_put_ref(reply, handle); return 0;
... default: ALOGE("unknown code %d\n", txn->code); return -1; }
bio_put_uint32(reply, 0); return 0; }
|
当要获取服务时,会调用do_find_service函数,代码如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid) { struct svcinfo *si = find_svc(s, len);
if (!si || !si->handle) { return 0; }
if (!si->allow_isolated) { uid_t appid = uid % AID_USER; if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { return 0; } } if (!svc_can_find(s, len, spid, uid)) { return 0; }
return si->handle; }
|
接着看find_svc函数。
1 2 3 4 5 6 7 8 9 10 11 12
| struct svcinfo *find_svc(const uint16_t *s16, size_t len) { struct svcinfo *si;
for (si = svclist; si; si = si->next) { if ((len == si->len) && !memcmp(s16, si->name, len * sizeof(uint16_t))) { return si; } } return NULL; }
|
系统服务的注册流程中,在Kernel Binder中会调用do_add_service函数,其内部会将包含服务名和handle值的svcinfo保存到svclist列表中。同样的,在获取服务的流程中,find_svc函数中会遍历svclist列表,根据服务名查找对应服务是否已经注册,如果已经注册就会返回对应的svcinfo,如果没有注册就返回NULL。
Java Binder的初始化
此前都在介绍Native Binder和Kernel Binder的内容,它们的架构简单总结为下图。
在ServiceManager中的Binder机制中,知道BpBinder是Client端与Server交互的代理类,而BBinder则代表了Server端,那么上图就可以改为:
从上图可以看到,Native Binder实际是基于C/S架构,Bpinder是Client端,BBinder是Server端,在ServiceManager的启动过程中,得知Native Binder通过ioctl函数和Binder驱动进行数据交互。
Java Binder是需要借助Native Binder来进行工作的,因此Java Binder在设计上也是一个C/S架构,可以说Java Binder是Native Binder的一个镜像,接下来看 Java Binder 是如何初始化的,即Java Binder的JNI注册。
Java Binder的JNI注册
Java Binder要想和Native Binder进行通信,需要通过JNI,JNI的注册是在Zygote进程启动过程中注册的,代码如下所示。AndroidRuntime.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env); if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } ... }
|
startReg函数如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int AndroidRuntime::startReg(JNIEnv* env) { ATRACE_NAME("RegisterAndroidNatives"); androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n"); env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); return 0; }
|
register_jni_procs函数的作用就是循环调用gRegJNI数组的成员所对应的方法,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12
| static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { for (size_t i = 0; i < count; i++) { if (array[i].mProc(env) < 0) { #ifndef NDEBUG ALOGD("----------!!! %s failed to load\n", array[i].mName); #endif return -1; } } return 0; }
|
gRegJNI数组中有100多个成员变量:
1 2 3 4 5 6 7 8 9
| static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), ... REG_JNI(register_android_os_Binder), ... };
|
其中REG_JNI是一个宏定义,实际上就是调用参数名所对应的函数。
1 2 3 4
| #define REG_JNI(name) { name } struct RegJNIRec { int (*mProc)(JNIEnv*); };
|
查看 register_android_os_Binder 函数,它做了如下三件事。android_util_Binder.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int register_android_os_Binder(JNIEnv* env) { if (int_register_android_os_Binder(env) < 0) return -1; if (int_register_android_os_BinderInternal(env) < 0) return -1; if (int_register_android_os_BinderProxy(env) < 0) return -1; ... return 0; }
|
它们是Java Binder关联类的一小部分,它们的关系如下。
- IBinder接口中定义了很多整型的变量,其中定义一个叫做
FLAG_ONEWAY
的整形变量。客户端发起调用时,客户端一般会阻塞,直到服务端返回结果。设置FLAG_ONEWAY
后,客户端只需要把请求发送到服务端就可以立即返回,而不需要等待服务端的结果,这是一种非阻塞方式。
- Binder和BinderProxy实现了IBinder接口,Binder是服务端的代表,而BinderProxy是客户端的代表。
- BinderInternal只是在Binder框架中被使用,其内部类GcWatcher用于处理和Binder的垃圾回收。
- Parcel是一个数据包装器,它可以在进程间进行传递,Parcel既可以传递基本数据类型也可以传递Binder对象,Binder通信就是通过Parcel来进行客户端与服务端数据交互。Parcel的实现既有Java部分,也有Native部分,具体实现在Native部分中。
下面分别对Binder、BinderInternal这两个类的注册进行分析。
Binder类的注册
调用int_register_android_os_Binder函数来完成Binder类的注册,代码如下所示。android_util_Binder.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| static const JNINativeMethod gBinderMethods[] = { { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, { "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder }, { "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer }, { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable } };
const char* const kBinderPathName = "android/os/Binder"; static int int_register_android_os_Binder(JNIEnv* env) { jclass clazz = FindClassOrDie(env, kBinderPathName);
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z"); gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie( env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods)); }
|
gBinderMethods的定义如下所示。
1 2 3 4 5 6 7
| static struct bindernative_offsets_t { jclass mClass; jmethodID mExecTransact; jfieldID mObject;
} gBinderOffsets;
|
使用gBinderMethods来保存变量和方法有两个原因:
1.为了效率考虑,如果每次调用相关的方法时都需要查询方法和变量,显然效率比较低。
2.这些成员变量和方法都是本地引用,在int int_register_android_os_Binder函数返回时,这些本地引用会被自动释放,因此用gBinderOffsets来保存,以便于后续使用。
BinderInternal类的注册
调用int_register_android_os_BinderInternal函数来完成BinderInternal类的注册,代码如下所示。android_util_Binder.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal"; static int int_register_android_os_BinderInternal(JNIEnv* env) { jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V"); gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");
jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray"); gSparseIntArrayOffsets.classObject = MakeGlobalRefOrDie(env, SparseIntArrayClass); gSparseIntArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "<init>", "()V"); gSparseIntArrayOffsets.put = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "put", "(II)V");
BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);
return RegisterMethodsOrDie( env, kBinderInternalPathName, gBinderInternalMethods, NELEM(gBinderInternalMethods)); }
|
和int_register_android_os_Binder函数的实现类似,主要做了三件事:
1.获取BinderInternal在JNI层的代表clazz。
2.将BinderInternal类中有用的成员变量和方法存储到gBinderInternalOffsets中。
3.注册BinderInternal类的Native方法对应的JNI函数。
BinderProxy类的注册
它和Binder、BinderInternal的注册过程差不多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| static int int_register_android_os_BinderProxy(JNIEnv* env) { jclass clazz = FindClassOrDie(env, "java/lang/Error"); gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
clazz = FindClassOrDie(env, kBinderProxyPathName); gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance", "(JJ)Landroid/os/BinderProxy;"); gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); gBinderProxyOffsets.mDumpProxyDebugInfo = GetStaticMethodIDOrDie(env, clazz, "dumpProxyDebugInfo", "()V"); gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
clazz = FindClassOrDie(env, "java/lang/Class"); gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
return RegisterMethodsOrDie( env, kBinderProxyPathName, gBinderProxyMethods, NELEM(gBinderProxyMethods)); }
|
Java Binder中系统服务的注册过程
在系统服务的注册过程中,介绍的是Native Binder中的系统服务的注册过程,这一过程的核心是ServiceManager,而在Java Binder中,也有一个ServiceManager,只不过这个ServiceManager是Java文件。
既然要将系统服务注册到ServiceManager,那么需要选择一个系统服务为例,这里以常见的AMS为例。
将AMS注册到ServiceManager
在AMS的setSystemProcess方法中,会调用ServiceManager的addService方法,如下所示。ActivityManagerService.java
1 2 3 4 5 6 7 8 9 10 11 12
| public void setSystemProcess() { try { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); .... } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( "Unable to find android system package", e); } ... }
|
接着看ServiceManager的addService方法。ServiceManager.java
1 2 3 4 5 6 7 8
| public static void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) { try { getIServiceManager().addService(name, service, allowIsolated, dumpPriority); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } }
|
主要分析getIServiceManager方法返回的是什么,代码如下所示。
1 2 3 4 5 6 7 8
| private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } sServiceManager = ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; }
|
讲到这里,已经积累了几个点需要分析,分别是:
- BinderInternal.getContextObject()
- ServiceManagerNative.asInterface()
- getIServiceManager().addService()
BinderInternal.getContextObject()
Binder.allowBlocking的作用是将BinderProxy的sWarnOnBlocking值置为false。主要来分析BinderInternal.getContextObject()做了什么,这个方法是一个Native方法,找到它对应的函数:android_util_Binder.cpp
1 2 3 4
| static const JNINativeMethod gBinderInternalMethods[] = { { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, ... };
|
对应的函数为android_os_BinderInternal_getContextObject:
1 2 3 4 5 6
| static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) { sp<IBinder> b = ProcessState::self()->getContextObject(NULL); return javaObjectForIBinder(env, b); }
|
ProcessState::self()的作用是创建ProcessState。
BpBinder是Native Binder中的Client端,这说明Java层的ServiceManager需要Native层的BpBinder,但是这个BpBinder在Java层是无法直接使用,那么就需要传入javaObjectForIBinder函数来做处理,其内部会创建一个BinderProxy对象(BinderProxy是Java Binder的客户端的代表),这样我们得知 BinderInternal.getContextObject()最终得到的是BinderProxy。
需要注意的一点是,这个传入的BpBinder会保存到BinderProxy的成员变量mObject中。
ServiceManagerNative.asInterface()
说到asInterface方法,在Native Binder中也有一个asInterface函数,IServiceManager的asInterface函数,它的作用是用BpBinder做为参数创建BpServiceManager。那么在Java Binder中的asInterface方法的作用又是什么?ServiceManagerNative.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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); }
|
BinderProxy和BpBinder分别在Jave Binder和Native Binder作为客户端的代表,BpServiceManager通过BpBinder来实现通信,同样的,ServiceManagerProxy也会将业务的请求交给BinderProxy来处理。
分析到这里,那么:
1 2
| sServiceManager = ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
|
可以理解为:
1 2
| sServiceManager = new ServiceManagerProxy(BinderProxy); }
|
getIServiceManager().addService()
getIServiceManager()返回的是ServiceManagerProxy,ServiceManagerProxy是ServiceManagerNative的内部类,它实现了IServiceManager接口。来查看ServiceManagerProxy的addService方法。ServiceManagerNative.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); data.writeStrongBinder(service); data.writeInt(allowIsolated ? 1 : 0); data.writeInt(dumpPriority); mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); }
|
BinderProxy.transact是native函数,实现的函数如下所示。android_util_Binder.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) { if (dataObj == NULL) { jniThrowNullPointerException(env, NULL); return JNI_FALSE; } Parcel* data = parcelForJavaObject(env, dataObj); if (data == NULL) { return JNI_FALSE; } Parcel* reply = parcelForJavaObject(env, replyObj); if (reply == NULL && replyObj != NULL) { return JNI_FALSE; } IBinder* target = getBPNativeData(env, obj)->mObject.get(); if (target == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); return JNI_FALSE; } ...
status_t err = target->transact(code, *data, reply, flags); return JNI_FALSE; }
|
引出JavaBBinder
接着回过头来分析data.writeStrongBinder(service),代码如下所示。Parcel.java
1 2 3
| public final void writeStrongBinder(IBinder ll) { nativeWriteStrongBinder(mNativePtr, val); }
|
nativeWriteStrongBinder是Native方法,实现的函数为android_os_Parcel_writeStrongBinder:android_os_Parcel.cpp
1 2 3 4 5 6 7 8 9 10
| static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } } }
|
接着查看 ibinderForJavaObject 函数:android_util_Binder.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) { if (obj == NULL) return NULL; if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); return jbh->get(env, obj); } if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { return getBPNativeData(env, obj)->mObject; }
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj); return NULL; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class JavaBBinderHolder { public: sp<JavaBBinder> get(JNIEnv* env, jobject obj) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, obj); mBinder = b; ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n", b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); } return b; } sp<JavaBBinder> getExisting() { AutoMutex _l(mLock); return mBinder.promote(); } private: Mutex mLock; wp<JavaBBinder> mBinder; };
|
data.writeStrongBinder(service)在本文中等价于:
1
| data.writeStrongBinder(new JavaBBinder(env,Binder))。
|
讲到这里可以得知ServiceManager.addService()传入的并不是AMS本身,而是JavaBBinder。
解析JavaBBinder
接着来分析JavaBBinder,查看它的构造函数:android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder
1 2 3 4 5 6 7 8 9 10 11
| class JavaBBinder : public BBinder { public: JavaBBinder(JNIEnv* env, jobject c) : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) { ALOGV("Creating JavaBBinder %p\n", this); gNumLocalRefsCreated.fetch_add(1, std::memory_order_relaxed); gcIfManyNewRefs(env); } ...
|
可以发现JavaBBinder继承了BBinder,那么JavaBBinder的作用是什么呢?当Binder驱动得到客户端的请求,紧接着会将响应发送给JavaBBinder,这时会调用JavaBBinder的onTransact函数,代码如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { JNIEnv* env = javavm_to_jnienv(mVM); ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); IPCThreadState* thread_state = IPCThreadState::self(); const int32_t strict_policy_before = thread_state->getStrictModePolicy(); jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
... return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; }
|
查看 execTransact 函数。Binder.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private boolean execTransact(int code, long dataObj, long replyObj, int flags) { ... try { if (tracingEnabled) { Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code); }
res = onTransact(code, data, reply, flags); } catch (RemoteException|RuntimeException e) { ... } ... return res; }
|
Java Binder架构
Native Binder的部分在此前的文章已经讲过,这里主要来说说Java Binder部分,从图中可以看到:
1.Binder是服务端的代表,JavaBBinder继承BBinder,JavaBBinder通过mObject变量指向Binder。
2.BinderProxy是客户端的代表,ServiceManager的addService等方法会交由ServiceManagerProxy处理。
3.ServiceManagerProxy的成员变量mRemote指向BinderProxy对象,所以ServiceManagerProxy的addService等方法会交由BinderProxy来处理。
4.BinderProxy的成员变量mObject指向BpBinder对象,因此BinderProxy可以通过BpBinder和Binder驱动发送数据。
备注
注:源码基于 Android 9.0 版本
参考资料:
Android 开发艺术探索
http://liuwangshu.cn/tags/Binder%E5%8E%9F%E7%90%86/
http://gityuan.com/tags/#binder
https://xiaozhuanlan.com/topic/9405168327
https://www.jianshu.com/p/adaa1a39a274