Skip to content

Commit

Permalink
ServiceManager addService
Browse files Browse the repository at this point in the history
  • Loading branch information
aiyongbiao committed Sep 26, 2017
1 parent 320be3c commit 3ee5807
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 0 deletions.
53 changes: 53 additions & 0 deletions frameworks/base/cmds/servicemanager/binder.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,19 @@ const char *cmd_name(uint32_t cmd)
#define binder_dump_txn(txn) do{} while (0)
#endif

// 表示结构体binder_io内部的数据缓冲区是一块在内核空间分配的内核缓冲区
// 可以通过用户空间地址来共享访问
// 当使用完成这个数据缓冲区之后,它就可以使用BC_FREE_BUFFER命令协议来通知Binder驱动释放相应的内核缓冲区
#define BIO_F_SHARED 0x01 /* needs to be buffer freed */
// 表示两个错误码
//
// 表示数据溢出,上次读出的数据大小超出了其内部的数据缓冲区大小
#define BIO_F_OVERFLOW 0x02 /* ran out of space */
// 上次从结构体binder_io读数据时发生了IO错误
#define BIO_F_IOERROR 0x04
// binder_io内部的数据缓冲区是通过malloc来分配的
// 它指的是一块在用户空间分配的缓冲区
// 当进程完成这个数据缓冲区后,可以直接调用函数free释放
#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */

// Service Manager打开了设备文件/dev/binder之后,就会得到文件描述符
Expand Down Expand Up @@ -171,18 +181,24 @@ int binder_write(struct binder_state *bs, void *data, unsigned len)
return res;
}

// reply: binder_io结构体,内部包含了进程间通信结果数据
// buffer_to_free:用户空间地址,指向了一块用来传输进程间通信数据的内核缓冲区
// status: 用来描述servicemanager是否成功处理了一个进程间通信请求,即是否成功注册了service组件
void binder_send_reply(struct binder_state *bs,
struct binder_io *reply,
void *buffer_to_free,
int status)
{
// 匿名结构体
// 用来描述一个BC_FREE_BUFFER和一个BC_REPLY命令协议
struct {
uint32_t cmd_free;
void *buffer;
uint32_t cmd_reply;
struct binder_txn txn;
} __attribute__((packed)) data;

// 设置匿名结构体data中的BC_FREE_BUFFER命令协议内容
data.cmd_free = BC_FREE_BUFFER;
data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY;
Expand All @@ -202,16 +218,19 @@ void binder_send_reply(struct binder_state *bs,
data.txn.data = reply->data0;
data.txn.offs = reply->offs0;
}
// 将BC_FREE_BUFFER和BC_REPLY命令协议发送给Binder驱动程序
binder_write(bs, &data, sizeof(data));
}

// 处理从驱动接收到的返回协议
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uint32_t *ptr, uint32_t size, binder_handler func)
{
int r = 1;
uint32_t *end = ptr + (size / 4);

while (ptr < end) {
// 读出返回协议码
uint32_t cmd = *ptr++;
#if TRACE
fprintf(stderr,"%s:\n", cmd_name(cmd));
Expand All @@ -231,6 +250,7 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio,
ptr += 2;
break;
case BR_TRANSACTION: {
// 获取通信的数据
struct binder_txn *txn = (void *) ptr;
if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
LOGE("parse: txn too small!\n");
Expand All @@ -239,13 +259,23 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio,
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
// 定义两个binder_io结构体
//
// 用来解析从Binder驱动程序读取回来的进程间通信数据
struct binder_io msg;
// 用来将进程间通信结果数据保存到缓冲区rdata中,以便后面可以将它返回给Binder驱动程序
struct binder_io reply;
int res;

// 分别使用函数bio_init, bio_init_from_txn来初始化
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
// 调用func来处理保存在binder_io结构体msg中的BR_TRANSACTION返回协议
// 将处理结果保存在binder_io结构体reply中
//
// func函数指针指向的是service manager进程中的函数svcmgr_handler
res = func(bs, txn, &msg, &reply);
// 将进程间的通信结果返回给Binder驱动
binder_send_reply(bs, &reply, txn->data, res);
}
ptr += sizeof(*txn) / sizeof(uint32_t);
Expand Down Expand Up @@ -414,29 +444,42 @@ void binder_loop(struct binder_state *bs, binder_handler func)
}
}

// io: 要初始化的binder_io结构体
// txn: 包含了binder_io结构体要解析的数据缓冲区和偏移数组
void bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn)
{
bio->data = bio->data0 = txn->data;
bio->offs = bio->offs0 = txn->offs;
bio->data_avail = txn->data_size;
bio->offs_avail = txn->offs_size / 4;
// 设置flag, 表示内部的数据缓冲区和偏移数组是在内核空间分配的
bio->flags = BIO_F_SHARED;
}

// bio: 要初始化的binder_io结构体
// data: bio内部所用的缓冲区
// maxdata: 用来描述缓冲区data的大小
// maxoffs: 描述bio内部的偏移数组大小
void bio_init(struct binder_io *bio, void *data,
uint32_t maxdata, uint32_t maxoffs)
{
uint32_t n = maxoffs * sizeof(uint32_t);

// 判断是否大于缓冲区data的大小
if (n > maxdata) {
bio->flags = BIO_F_OVERFLOW;
bio->data_avail = 0;
bio->offs_avail = 0;
return;
}

// 将data分成了两部分
//
// 一部分用于binder_io结构体bio的数据缓冲区
// 另一部分用户binder_io结构体的bio偏移数组
bio->data = bio->data0 = data + n;
bio->offs = bio->offs0 = data;
// 设置可用的数据缓冲区和偏移数组的大小
bio->data_avail = maxdata - n;
bio->offs_avail = maxoffs;
bio->flags = 0;
Expand Down Expand Up @@ -579,15 +622,21 @@ void bio_put_string16_x(struct binder_io *bio, const char *_str)

static void *bio_get(struct binder_io *bio, uint32_t size)
{
// 将它对齐到4个字节边界
size = (size + 3) & (~3);

// 剩余的为解析字节数data_avail是否小于要求读取的字节数size
if (bio->data_avail < size){
bio->data_avail = 0;
// 如果是,那么就是溢出了
bio->flags |= BIO_F_OVERFLOW;
return 0;
} else {
// 如果否,将data当前的位置保存在ptr中
void *ptr = bio->data;
// 往前推进size个字节
bio->data += size;
// 未读取的字节数减少size个字节
bio->data_avail -= size;
return ptr;
}
Expand All @@ -614,6 +663,7 @@ static struct binder_object *_bio_get_obj(struct binder_io *bio)
unsigned off = bio->data - bio->data0;

/* TODO: be smarter about this? */
// 循环检查binder_io结构体的数据缓冲区当前位置是否保存了一个binder_object结构体
for (n = 0; n < bio->offs_avail; n++) {
if (bio->offs[n] == off)
return bio_get(bio, sizeof(struct binder_object));
Expand All @@ -626,13 +676,16 @@ static struct binder_object *_bio_get_obj(struct binder_io *bio)

void *bio_get_ref(struct binder_io *bio)
{
// 从binder_io结构体取出一个binder_object结构体
struct binder_object *obj;

obj = _bio_get_obj(bio);
if (!obj)
return 0;

if (obj->type == BINDER_TYPE_HANDLE)
// 将成员变量pointer返回,pointer保存的是一个由Binder驱动程序创建的引用对象的句柄值
// 这个引用对象引用了即将要注册的Service组件
return obj->pointer;

return 0;
Expand Down
14 changes: 14 additions & 0 deletions frameworks/base/cmds/servicemanager/binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

struct binder_state;

// 描述一个Binder对象
// 等同于结构体flat_binder_object
struct binder_object
{
uint32_t type;
Expand All @@ -17,6 +19,8 @@ struct binder_object
void *cookie;
};

// 用来描述进程间通信数据
// 等同于binder_transaction_data
struct binder_txn
{
void *target;
Expand All @@ -33,16 +37,26 @@ struct binder_txn
void *offs;
};

// 用来解析进程间通信数据
// 作用类似于Binder库中的Parcel类
struct binder_io
{
// 数据缓冲区
char *data; /* pointer to read/write from */
// 偏移数组
uint32_t *offs; /* array of offsets */
// 描述数据缓冲区data0,offs0还有多少内容还没有被解析
uint32_t data_avail; /* bytes available in data buffer */
uint32_t offs_avail; /* entries available in offsets array */

// 在解析进程间通信数据的过程中
// binder_io的成员变量data0, offs0是中指向数据缓冲区和偏移数组的起始地址
// 成员变量data和offs指向当前正在解析的数据缓冲区和偏移数组的状态
char *data0; /* start of data buffer */
uint32_t *offs0; /* start of offsets buffer */
// 描述数据缓冲区的属性
uint32_t flags;
// 保留给以后使用
uint32_t unused;
};

Expand Down
32 changes: 32 additions & 0 deletions frameworks/base/cmds/servicemanager/service_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static struct {
const char *name;
} allowed[] = {
#ifdef LVMX
// 用户名为uid的进程才能注册名为xxx的service组件
{ AID_MEDIA, "com.lifevibes.mx.ipc" },
#endif
{ AID_MEDIA, "media.audio_flinger" },
Expand Down Expand Up @@ -75,13 +76,16 @@ int str16eq(uint16_t *a, const char *b)
return 1;
}

// 注册service是一种特权,不是所有进程都可以将service组件注册到service manager中
int svc_can_register(unsigned uid, uint16_t *name)
{
unsigned n;

// 如果发现用户id是系统进程或是AID_SYSTEM进程,将不受限制
if ((uid == 0) || (uid == AID_SYSTEM))
return 1;

// allowed是一个全局的数组,定义了可以注册什么名称的service组件
for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
return 1;
Expand All @@ -91,21 +95,30 @@ int svc_can_register(unsigned uid, uint16_t *name)

struct svcinfo
{
// 描述下一个svcinfo结构体
struct svcinfo *next;
// 句柄值,描述注册了的service组件
void *ptr;
// 死亡通知
struct binder_death death;
// 长度
unsigned len;
// 已经注册了的service组件名称
uint16_t name[0];
};

// 每一个被注册了的service组件都使用了svcinfo结构体来描述
// 保存在一个全局队列svclist中
struct svcinfo *svclist = 0;

struct svcinfo *find_svc(uint16_t *s16, unsigned len)
{
struct svcinfo *si;

// 循环检查全局队列svclist中已注册service组件列表
for (si = svclist; si; si = si->next) {
if ((len == si->len) &&
// 发现已经存在的话会将s16对应的svcinfo结构体返回给调用者
!memcmp(s16, si->name, len * sizeof(uint16_t))) {
return si;
}
Expand Down Expand Up @@ -152,21 +165,29 @@ int do_add_service(struct binder_state *bs,
if (!ptr || (len == 0) || (len > 127))
return -1;

// s: 要注册的service组件名称
// uid: 注册service组件的进程的用户id
//
// 检查权限
if (!svc_can_register(uid, s)) {
LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
str8(s), ptr, uid);
return -1;
}

// 检查是否已经注册过
si = find_svc(s, len);
if (si) {
if (si->ptr) {
// 已经被使用过
LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
str8(s), ptr, uid);
return -1;
}
// 修改ptr参数
si->ptr = ptr;
} else {
// 如果没有被引用,就会创建一个svcinfo结构体来描述要注册的service组件
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
Expand All @@ -180,10 +201,13 @@ int do_add_service(struct binder_state *bs,
si->death.func = svcinfo_death;
si->death.ptr = si;
si->next = svclist;
// 添加到全局的svclist中
svclist = si;
}

// 因为引用了新注册的service组件,因此需要调用binder_acquire来增加相应的binder引用对象的引用计数值
binder_acquire(bs, ptr);
// 注册一个Binder本地对象的死亡接收通知,以便service manager在该service组件死亡时采取相应的处理措施
binder_link_to_death(bs, ptr, &si->death);
return 0;
}
Expand All @@ -202,17 +226,21 @@ int svcmgr_handler(struct binder_state *bs,
// LOGI("target=%p code=%d pid=%d uid=%d\n",
// txn->target, txn->code, txn->sender_pid, txn->sender_euid);

// 检查从驱动传进来的目标Binder本地对象是否指向在service manager中定义的虚拟Binder本地对象svcmgr_handle
if (txn->target != svcmgr_handle)
return -1;

// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
// 检查Binder进程间通信请求头是否合法
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
// 验证传递过来的服务接口描述符是否等于svcmgr_id
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
// 如果不相等,说明这是一个非法的进程间通信请求
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}
Expand All @@ -229,6 +257,8 @@ int svcmgr_handler(struct binder_state *bs,

case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
// 从binder_io结构体中的数据缓冲区获取一个Binder引用对象的句柄值
// 它引用了要注册的Service组件
ptr = bio_get_ref(msg);
if (do_add_service(bs, s, len, ptr, txn->sender_euid))
return -1;
Expand All @@ -251,6 +281,8 @@ int svcmgr_handler(struct binder_state *bs,
return -1;
}

// 将注册成功的代码0写入到reply中
// 返回给请求注册service组件的进程
bio_put_uint32(reply, 0);
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions frameworks/base/core/jni/android_util_Binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,14 @@ static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie)

static Mutex mProxyLock;

// 要么指向binder代理对象,要么指向本地对象
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;

if (val->checkSubclass(&gBinderOffsets)) {
// One of our own!
// 如果是本地对象,将java层的Binder对象返回
jobject object = static_cast<JavaBBinder*>(val.get())->object();
//printf("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
Expand Down
Loading

0 comments on commit 3ee5807

Please sign in to comment.