本文参考《Android系统源代码情景分析》,作者罗升阳
一、测试代码:
~/Android/external/binder/server
----FregServer.cpp
~/Android/external/binder/common
----IFregService.cpp
----IFregService.h
~/Android/external/binder/client
----FregClient.cpp
Binder库(libbinder)代码:
~/Android/frameworks/base/libs/binder
----BpBinder.cpp
----Parcel.cpp
----ProcessState.cpp
----Binder.cpp
----IInterface.cpp
----IPCThreadState.cpp
----IServiceManager.cpp
----Static.cpp
~/Android/frameworks/base/include/binder
----Binder.h
----BpBinder.h
----IInterface.h
----IPCThreadState.h
----IServiceManager.h
----IBinder.h
----Parcel.h
----ProcessState.h
驱动层代码:
~/Android//kernel/goldfish/drivers/staging/android
----binder.c
----binder.h
Service Manager代码:
二、源码分析
1、FregClient进程,获取ServiceManager代理对象
参考FregServer进程,获取ServiceManager代理对象http://blog.csdn.net/jltxgcy/article/details/25953361。
~/Android/external/binder/client
----FregClient.cpp
int main()
{
sp<IBinder> binder = defaultServiceManager()->getService(String16(FREG_SERVICE));
if(binder == NULL) {
LOGE("Failed to get freg service: %s.\n", FREG_SERVICE);
return -1;
}
sp<IFregService> service = IFregService::asInterface(binder);
if(service == NULL) {
LOGE("Failed to get freg service interface.\n");
return -2;
}
............
}
首先调用Binder库提供的函数defaultServiceManager在FregClient进程中获得一个Service Manager代理对象,接着再调用它的成员函数getService来获得一个名称为FREG_SERVICE的Service组件的代理对象,类型为BpBinder。然后再需要通过IFregService类的静态成员函数asInterface将它封装成一个BpFregService类型的代理对象。
2、FregClient进程,封装进程间通信数据
参考FregServer进程,封装进程间通信数据http://blog.csdn.net/jltxgcy/article/details/26059215。
我们首先分析下Service Manager代理对象的成员函数getService实现如下:
~/Android/external/binder/client
---IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
.........
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
LOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
...........
};
这个函数最多会尝试5次来获得一个名称为name的Service组件的代理对象。如果上一次获得失败,那么就调用sleep使得当前线程睡眠1毫秒,然后再重新去获取,否则就直接将获得的Service组件的代理对象返回给调用者。
调用checkService来获得一个名称为name的Service组件的代理对象。实现如下:
~/Android/external/binder/client
----IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
........
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//android.os.IServiceManager
data.writeString16(name);//shy.luo.FregService
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);//remote为BpBinder对象
return reply.readStrongBinder();
}
.........
};
3、 FregClient进程,发送BC_TRANSACTION,唤醒ServiceManager进程,返回BR_TRANSACTION_COMPLETE,睡眠等待主线程thread->wait
参考FregServer进程,发送BC_TRANSACTION,唤醒ServiceManager进程,返回BR_TRANSACTION_COMPLETE,睡眠等待主线程thread->wait ,http://blog.csdn.net/jltxgcy/article/details/26076149。
一个是ADD_SERVICE_TRANSACTION,一个是CHECK_SERVICE_TRANSACTION。只是放在binder_transaction结构t->code不同。
不同之处是往缓冲区写的数据,FregClient没有写入对象,只有android.os.IServiceManager,shy.luo.FregService。注意此时写入的内核缓冲区是Service Manger的内核缓冲区。
4、Service Manager进程从睡眠中被唤醒,返回BR_TRANSACTION,执行真正意义的checkService
参考Service Manager进程从睡眠中被唤醒,返回BR_TRANSACTION,执行真正意义的checkService,http://blog.csdn.net/jltxgcy/article/details/26151113。注意此时读入的内核缓冲区是Service Manger的内核缓冲区。
随着执行的深入,svcmgr_handler方法,出现了不同的执行过程。实现如下:int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
..........
if (txn->target != svcmgr_handle)
return -1;
.........
strict_policy = bio_get_uint32(msg);//strict_policy为STRICT_MODE_PENALTY_GATHER
s = bio_get_string16(msg, &len);//s为android.os.IServiceManager
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {//比较是否一致,如果不一致,直接返回出错
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}
switch(txn->code) {//CHECK_SERVICE_TRANSACTION,即SVC_MGR_CHECK_SERVICE
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);//s为shy.luo.FregService,len为它的长度
ptr = do_find_service(bs, s, len);//Service Manager进程的引用对象(引用了FregServer进程的实体对象)的句柄值
if (!ptr)
break;
bio_put_ref(reply, ptr);//将前面获得的一个句柄值封装成一个binder_object结构体,并且写入到binder_io结构体reply中
return 0;
.........
}
.........
}
调用do_find_service在已注册Service组件列表svclist中查找与它对应的一个svcinfo结构体,实现如下:
void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)
{
struct svcinfo *si;
si = find_svc(s, len);//s为shy.luo.FregService,len为它的长度
// LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
if (si && si->ptr) {
return si->ptr;//返回一个引用了注册到Service Manager中Service组件的Binder引用对象的句柄值
} else {
return 0;
}
}
首先调用find_svc来查找与字符串s对应的一个svcinfo结构体si。我们已经分析过函数find_svc的实现了,它通过遍历已注册Service组件列表svclist来查找与字符串s对应的一个svcinfo结构体。如果找到了与字符串对应的svcinfo结构体si,并且它的成员变量ptr的值不为0,那么就将它的成员变量ptr的值返回给调用者。
结构体svcinfo的成员变量ptr保存的一个引用了注册到Service Manager中Service组件的Binder引用对象的句柄值。当Service Manager将这个句柄值返回给Binder驱动程序时,Binder驱动程序就可以根据它找到相应的Binder引用对象,接着找到该Binder引用对象所引用Binder实体对象。
返回svcmgr_handler,继续执行bio_put_ref函数,将前面获得的一个句柄值封装成一个binder_object结构体,并且写入到binder_io结构体reply中,实现如下:
~/Android/frameworks/base/cmd/servicemanager
----binder.c
void bio_put_ref(struct binder_io *bio, void *ptr)//bio为reply,ptr为句柄值
{
struct binder_object *obj;
if (ptr)//不为NULL
obj = bio_alloc_obj(bio);//分配了binder_object结构体,而不是binder_io,binder_io以前已经分配过了
else
obj = bio_alloc(bio, sizeof(*obj));
if (!obj)
return;
obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
obj->type = BINDER_TYPE_HANDLE;
obj->pointer = ptr;
obj->cookie = 0;
}
由于传进来的参数ptr的值不等于0,因此调用bio_alloc_obj在binder_io结构体bio的数据缓冲区中分配一个binder_object结构体obj。实现如下:
~/Android/frameworks/base/cmd/servicemanager
----binder.c
static struct binder_object *bio_alloc_obj(struct binder_io *bio)//bio为reply
{
struct binder_object *obj;
obj = bio_alloc(bio, sizeof(*obj));//在binder_io结构体bio的数据缓冲区中分配一个binder_object结构体obj
if (obj && bio->offs_avail) {
bio->offs_avail--;//偏移数组大小减1
*bio->offs++ = ((char*) obj) - ((char*) bio->data0);//偏移数组内容指向刚才的binder_object结构体obj
return obj;
}
bio->flags |= BIO_F_OVERFLOW;
return 0;
}
~/Android/frameworks/base/cmd/servicemanager
----binder.c
static void *bio_alloc(struct binder_io *bio, uint32_t size)
{
size = (size + 3) & (~3);
if (size > bio->data_avail) {
bio->flags |= BIO_F_OVERFLOW;
return 0;
} else {
void *ptr = bio->data;//开始位置
bio->data += size;//分配完binder_object后的位置
bio->data_avail -= size;//可用数据要减少size
return ptr;
}
}
5、Service Manager进程,发送BC_REPLY,唤醒FregClient进程,返回BR_TRANSACTION_COMPLETE,睡眠等待在proc->wait
参考Service Manager进程,发送BC_REPLY,唤醒FregServer进程,返回BR_TRANSACTION_COMPLETE,睡眠等待在proc->wait,http://blog.csdn.net/jltxgcy/article/details/26216521。
回到svcmgr_handler中,现在要返回给Binder驱动程序的进程间通信结果数据保存在binder_io结构体reply中了。接着又返回函数binder_parse中,最后调用函数binder_send_reply将binder_io结构体reply的内容返回给Binder驱动程序。
注意,此时写入的内核缓冲区是FregClient进程的内核缓冲区。
随着执行的深入,binder_transaction方法,出现了不同的执行过程。不同之处在于reply中含有Binder对象。实现如下:
~/Android//kernel/goldfish/drivers/staging/android
----binder.c
static void
binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
struct binder_transaction *t;
struct binder_work *tcomplete;
......
struct binder_proc *target_proc;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
struct list_head *target_list;
wait_queue_head_t *target_wait;
struct binder_transaction *in_reply_to = NULL;
........
uint32_t return_error;
........
if (reply) {
in_reply_to = thread->transaction_stack;//首先从线程thread的事务堆栈中将该binder_transaction结构体取出来,并且保存在变量in_reply_to中
if (in_reply_to == NULL) {
......
return_error = BR_FAILED_REPLY;
goto err_empty_call_stack;
}
binder_set_nice(in_reply_to->saved_priority);
if (in_reply_to->to_thread != thread) {
........
return_error = BR_FAILED_REPLY;
in_reply_to = NULL;
goto err_bad_call_stack;
}
thread->transaction_stack = in_reply_to->to_parent;//Server Manager进程的主线程transaction_stack为NULL
target_thread = in_reply_to->from;//目标线程
if (target_thread == NULL) {
return_error = BR_DEAD_REPLY;
goto err_dead_binder;
}
if (target_thread->transaction_stack != in_reply_to) {
.........
return_error = BR_FAILED_REPLY;
in_reply_to = NULL;
target_thread = NULL;
goto err_dead_binder;
}
target_proc = target_thread->proc;//找到了目标进程
} else {
........
}
if (target_thread) {
.........
target_list = &target_thread->todo;//分别将它的todo队列和wait等待队列作为目标todo队列target_list和目标wait等待队列target_wait
target_wait = &target_thread->wait;//分别将它的todo队列和wait等待队列作为目标todo队列target_list和目标wait等待队列target_wait
} else {
.........
}
.........
/* TODO: reuse incoming transaction for reply */
t = kzalloc(sizeof(*t), GFP_KERNEL);//分配了binder_transaction结构体
........
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);//分配了binder_work结构体
if (tcomplete == NULL) {
return_error = BR_FAILED_REPLY;
goto err_alloc_tcomplete_failed;
}
.......
if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;//service_manager的主线程
else
t->from = NULL;
t->sender_euid = proc->tsk->cred->euid;//service_manager进程号
t->to_proc = target_proc;//目标进程
t->to_thread = target_thread;//目标线程
t->code = tr->code;//0
t->flags = tr->flags;//0
t->priority = task_nice(current);
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));//分配了binder_buffer结构体
if (t->buffer == NULL) {
return_error = BR_FAILED_REPLY;
goto err_binder_alloc_buf_failed;
}
t->buffer->allow_user_free = 0;//不允许释放
.......
t->buffer->transaction = t;
t->buffer->target_node = target_node;//NULL
if (target_node)
binder_inc_node(target_node, 1, 0, NULL);//增加目标Binder实体对象的强引用计数
offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));//偏移数组在data中起始位置,位于数据缓冲区之后
if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {//数据缓冲区拷贝到data中
binder_user_error("binder: %d:%d got transaction with invalid "
"data ptr\n", proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
goto err_copy_data_failed;
}
if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {//偏移数组拷贝到data中,偏移数组位于数据缓冲区之后
binder_user_error("binder: %d:%d got transaction with invalid "
"offsets ptr\n", proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
goto err_copy_data_failed;
}
...........
off_end = (void *)offp + tr->offsets_size;
for (; offp < off_end; offp++) {//偏移数组里面有内容
struct flat_binder_object *fp;
.......
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
switch (fp->type) {
......
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
struct binder_ref *ref = binder_get_ref(proc, fp->handle);//Service Manager进程的引用对象(引用了FregServer进程的实体对象)
.......
if (ref->node->proc == target_proc) {//FregService进程和FregClient进程不相等
.......
} else {
struct binder_ref *new_ref;
new_ref = binder_get_ref_for_node(target_proc, ref->node);//FregClient进程的引用对象(引用了FregServer进程的实体对象)
.........
fp->handle = new_ref->desc;//FregClient进程的引用对象句柄赋值给handle
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
........
}
} break;
.......
}
if (reply) {
BUG_ON(t->buffer->async_transaction != 0);
binder_pop_transaction(target_thread, in_reply_to);//FregClient进程的主线程thread->transaction_stack为NULL
} else if (!(t->flags & TF_ONE_WAY)) {
.........
} else {
.........
}
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);//加入到目标线程的todo
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);//加入到本线程的todo
if (target_wait)
wake_up_interruptible(target_wait);//唤醒目标线程
return;
}
要传递的t->buffer->data中flat_binder_object对象的各个成员如下:
flags为0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS,type为BINDER_TYPE_HANDLE,handle为FregClient进程的引用对象(引用了FregServer进程的实体对象)句柄值,cookie为0。
6、FregClient进程,返回BR_REPLY
参考FregServer进程,返回BR_REPLY,http://blog.csdn.net/jltxgcy/article/details/26339313。
7、FregClient进程,返回到checkService中,创建FregClient进程的代理对象,最后创建一个BpFregService类型的代理对象。参考Android Binder进程间通信---FregServer进程,启动Binder线程池http://blog.csdn.net/jltxgcy/article/details/26354311。
注意,此时读入的内核缓冲区是FregClient进程的内核缓冲区。
实现如下:
~/Android/external/binder/client
----IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
........
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//android.os.IServiceManager
data.writeString16(name);//shy.luo.FregService
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);//remote为BpBinder对象
return reply.readStrongBinder();//FregClient进程的代理对象
}
.........
};
返回后调用Parcel对象reply的成员函数readStrongBinder来获得一个Binder代理对象。实现如下:
~/Android/frameworks/base/libs/binder
----Parcel.cpp
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);//来获得这个flat_binder_object结构体
return val;
}
调用unflatten_binder函数,实现如下:
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);//in就是reply
if (flat) {
switch (flat->type) {
.........
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
......
}
}
return BAD_TYPE;
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);//检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {//如果进程尚未为句柄值handle创建过Binder代理对象,或者创建了Binder代理对象但已经销毁了
b = new BpBinder(handle); //Binder代理对象,handle为1
e->binder = b;//保存再e的成员变量binder中
if (b) e->refs = b->getWeakRefs();//将弱引用计数对象保存在e的成员变量refs中
result = b;//返回结果
} else {//如果进程已经创建了Binder代理对象,并且没有销毁,那么直接返回
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);//设置返回结果result
e->refs->decWeak(this);//减少弱引用计数,因为attemptIncWeak增加了弱引用计数
}
}
return result;
}
创建FregClient进程的代理对象。
执行完checkSevice,返回main函数。实现如下:
~/Android/external/binder/client
----FregClient.cpp
int main()
{
sp<IBinder> binder = defaultServiceManager()->getService(String16(FREG_SERVICE));
if(binder == NULL) {
LOGE("Failed to get freg service: %s.\n", FREG_SERVICE);
return -1;
}
sp<IFregService> service = IFregService::asInterface(binder);
if(service == NULL) {
LOGE("Failed to get freg service interface.\n");
return -2;
}
............
}
IFregService类的静态成员函数asInterface是通过宏IMPLEMENT_META_INTERFACE来定义的,它的实现如下:
android::sp<IFregService> IFregService::asInterface(const android::sp<android::IBinder>& obj)
{
android::sp<IFregService> intr;
if (obj != NULL) {
intr = static_cast<IFregService*>(
obj->queryLocalInterface(IFregService::descriptor).get());//返回NULL
if (intr == NULL) {
intr = new BpFregService(obj); //创建了BpFregService类型的代理对象
}
}
return intr;
}
参数obj指向的是前面获得的一个Binder代理对象,即一个BpBinder对象。然后将这个Binder代理对象封装成一个BpFregService类型的代理对象,并且将它的IFregService接口返回给调用者。
Service Manager进程的实体对象;
FregServer进程的引用对象(引用了Service Manager进程的实体对象);
FregServer进程的代理对象。
FregServer进程的本地对象;
FregServer进程的实体对象;
Service Manager进程的引用对象(引用了FregServer进程的实体对象);
FregClient进程的引用对象(引用了FregServer进程的实体对象);
FregClient进程的代理对象;
BpFregService类型的代理对象(成员函数remote()可以获取FregClient进程的代理对象);