Binder 是 Android 独有的一种通信机制, ActivityServiceBroadcastContentProvider 这四大组件所涉及的多进程间的通信底层都是依赖于 Binder IPC 机制。学好底层的通信原理对掌握安卓这幢大厦有着重要的意义.

# 说明

本文所研究的安卓内核版本为 Linux version 4.9.270-g862f51bac900-ab7613625

安卓框架版本为 android12-platform-release

# Binder 简介

从进程角度来看 IPC (Inter Process Communication) 机制,每个 Android 的进程,只能运行在自己进程所拥有的虚拟地址空间。对于用户空间,不同进程之间彼此是不能共享的,而内核空间却是可共享的。Client 进程向 Server 进程通信,恰恰是利用进程间可共享的内核内存空间来完成底层通信工作的,Client 端与 Server 端进程往往采用 ioctl 等方法跟内核空间的驱动进行交互。

binder_interprocess_communication

Binder 通信采用 C/S 架构,从组件视角来说,包含 Client、Server、ServiceManager 以及 binder 驱动,其中 ServiceManager 用于管理系统中的各种服务。架构图如下所示,图中的 Client,Server,Service Manager 之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过 Binder 驱动进行交互的,从而实现 IPC 通信方式。其中 Binder 驱动位于内核空间,Client,Server,Service Manager 位于用户空间。

ServiceManager

# Binder 设备的初始化过程

在 Linux 中,万物皆文件,那么毫无疑问,Binder 其实也是一个文件,它的初始化函数是 binder_init , 主要功能是注册 binder 设备

//kernel\drivers\android\binder.c
static int __init binder_init(void)
{
	int ret;
	char *device_name, *device_names, *device_tmp;
	struct binder_device *device;
	struct hlist_node *tmp;
	// 初始化 lru 链表,该链表用于管理内存页;注册 shrinker 结构体
	ret = binder_alloc_shrinker_init();
	if (ret)
		return ret;
	// 原子操作赋值
	atomic_set(&binder_transaction_log.cur, ~0U);
	atomic_set(&binder_transaction_log_failed.cur, ~0U);
	/**debug 相关的代码,之后 debug 相关的代码将不再出现 **/
    
	// 在 debugfs 文件系统创建了 binder 文件夹
	binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
	// 如果 binder 文件夹创建成功,则在该文件夹内继续创建 binder/proc 文件夹
	if (binder_debugfs_dir_entry_root)
		binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
						 binder_debugfs_dir_entry_root);
	if (binder_debugfs_dir_entry_root) {
		// 继续在 binder 目录中创建 state,stats,transactions,transaction_log,failed_transaction_log 文件,读取 Binder 驱动程序的运行情况
		debugfs_create_file("state",
				    0444,
				    binder_debugfs_dir_entry_root,
				    NULL,
				    &binder_state_fops);
		debugfs_create_file("stats",
				    0444,
				    binder_debugfs_dir_entry_root,
				    NULL,
				    &binder_stats_fops);
		debugfs_create_file("transactions",
				    0444,
				    binder_debugfs_dir_entry_root,
				    NULL,
				    &binder_transactions_fops);
		debugfs_create_file("transaction_log",
				    0444,
				    binder_debugfs_dir_entry_root,
				    &binder_transaction_log,
				    &binder_transaction_log_fops);
		debugfs_create_file("failed_transaction_log",
				    0444,
				    binder_debugfs_dir_entry_root,
				    &binder_transaction_log_failed,
				    &binder_transaction_log_fops);
	}
	/*
	 * Copy the module_parameter string, because we don't want to
	 * tokenize it in-place.
	 */
	// 在内核空间中分配内存,GFP_KERNEL 表示正常分配内存
	device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
	if (!device_names) {
		ret = -ENOMEM;
		goto err_alloc_device_names_failed;
	}
	// 将 binder,hwbinder,vndbinder 赋值给 device_names
	strcpy(device_names, binder_devices_param);
	device_tmp = device_names;
	while ((device_name = strsep(&device_tmp, ","))) {
		// 以 "," 作为分隔符,注册 misc 设备 /dev/binder/dev/hwbinder/dev/vndbinder
		ret = init_binder_device(device_name);
		if (ret)
			goto err_init_binder_device_failed;
	}
	return ret;
err_init_binder_device_failed:
	hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
		misc_deregister(&device->miscdev);
		hlist_del(&device->hlist);
		kfree(device);
	}
	kfree(device_names);
err_alloc_device_names_failed:
	debugfs_remove_recursive(binder_debugfs_dir_entry_root);
	return ret;
}

binder_init 中,调用了 init_binder_device 通过 misc_register 来注册 binder 设备

//kernel\drivers\android\binder.c
static const struct file_operations binder_fops = {
	.owner = THIS_MODULE,
	.poll = binder_poll,
	.unlocked_ioctl = binder_ioctl,
	.compat_ioctl = binder_ioctl,//IO 控制函数
	.mmap = binder_mmap,// 内存映射函数
	.open = binder_open,//binder 文件打开函数
	.flush = binder_flush,
	.release = binder_release,
};
static int __init init_binder_device(const char *name)
{
	int ret;
	struct binder_d/evice *binder_device;
	binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
	if (!binder_device)
		return -ENOMEM;
	binder_device->miscdev.fops = &binder_fops;//// 设备的文件操作结构,这是 file_operations 结构
	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;// 次设备号 动态分配
	binder_device->miscdev.name = name;//// 设备名
	// 设置 binder_context,用于记录 servicemanager 的 binder_node 信息,
	// 由于 binder_device 是全局唯一的,这是 servicemanager 可以成为守护进
	// 程的关键。
	binder_device->context.binder_context_mgr_uid = INVALID_UID;
	binder_device->context.name = name;
	mutex_init(&binder_device->context.context_mgr_node_lock);
	// 注册 binder 设备
	ret = misc_register(&binder_device->miscdev);
	if (ret < 0) {
		kfree(binder_device);
		return ret;
	}
	hlist_add_head(&binder_device->hlist, &binder_devices);
	return ret;
}

# Binder 设备文件的打开过程

一个进程在使用 binder 进行通信之前,需要使用 open 函数来打开设备文件 /dev/binder, 在这个过程中, binder_open 函数就会被调用,这个函数的作用如下

  • 创建 binder_proc 对象
  • 把当前进程等信息保存到 binder_proc 对象
  • binder_proc 对象保存到文件指针 filp
  • binder_proc 加入到全局链表 binder_procs
//kernel\drivers\android\binder.c
static int binder_open(struct inode *nodp, struct file *filp)
{
	struct binder_proc *proc;
	struct binder_device *binder_dev;
	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
		     current->group_leader->pid, current->pid);
	// 创建 binder_proc 结构体遍历 proc,并为 proc 实现初始化
	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
	if (proc == NULL)
		return -ENOMEM;
	spin_lock_init(&proc->inner_lock);
	spin_lock_init(&proc->outer_lock);
	atomic_set(&proc->tmp_ref, 0);
	get_task_struct(current->group_leader);
	/*
	任何一个进程,如果只有主线程,那 pid 是自己,tgid 是自己,group_leader 指向的还是自己。
	但是,如果一个进程创建了其他线程,那就会有所变化了。线程有自己的 pid,tgid 就是进程的
	主线程的 pid,group_leader 指向的就是进程的主线程。
	有了 tgid 之后,我们就可以判断一个 task 是线程还是进程了。
	pid : 每个 task 都有一个 pid,是唯一的,不管是进程还是线程。
	tgid: 指向主线程的 pid
	*/
	//group_leader: 指向进程的主线程
	proc->tsk = current->group_leader;
	mutex_init(&proc->files_lock);
	// 初始化 todo 队列
	INIT_LIST_HEAD(&proc->todo);
	// 初始化进程优先级
	if (binder_supported_policy(current->policy)) {
		proc->default_priority.sched_policy = current->policy;
		proc->default_priority.prio = current->normal_prio;
	} else {
		proc->default_priority.sched_policy = SCHED_NORMAL;
		proc->default_priority.prio = NICE_TO_PRIO(0);
	}
	// 初始化 binder_dev,proc->context,proc->alloc
	binder_dev = container_of(filp->private_data, struct binder_device,
				  miscdev);
	proc->context = &binder_dev->context;
	binder_alloc_init(&proc->alloc);
	//binder_alloc 初始化
	binder_stats_created(BINDER_STAT_PROC);
	proc->pid = current->group_leader->pid;
	INIT_LIST_HEAD(&proc->delivered_death);
	INIT_LIST_HEAD(&proc->waiting_threads);
	// 将初始化完成的 binder_proc 结构体 proc 保存到 filp->private_data 中
	//filp 指向一个打开的文件结构体,它和进程调用 open 函数打开设备文件
	///dev/binder 之后内核返回给进程的文件描述符是相互关联的
	filp->private_data = proc;
	mutex_lock(&binder_procs_lock);
	// 将 binder_proc 结构体 proc 加入到一个全局哈希队列 binder_procs 中
	//binder 通过遍历这个哈希队列就可以知道有多少进程在使用 binder
	hlist_add_head(&proc->proc_node, &binder_procs);
	mutex_unlock(&binder_procs_lock);
	return 0;
}

# Binder 设备文件的内存映射过程

在打开了设备文件 /dev/binder 之后,还需要调用 mmap 函数来把这个设备文件映射到进程的地址空间,此时 binder 驱动程序中的 binder_mmap 函数就会被调用,主要功能:在内核虚拟地址空间,申请一块与用户虚拟内存相同大小的内存;然后再申请 1 个 page 大小的物理内存,再将同一块物理内存分别映射到内核虚拟地址空间和用户虚拟内存空间,从而实现了用户空间的 Buffer 和内核空间的 Buffer 同步操作的功能。

//kernel\drivers\android\binder.c
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
{
	int ret;
	struct binder_proc *proc = filp->private_data;
	const char *failure_string;
	// 保证请求分配内存的线程为主线程
	if (proc->tsk != current->group_leader)
		return -EINVAL;
	// 保证映射内存 <= 4MB, 说明 Binder 最多能为进程分配 4MB 的内核缓冲区来传输数据
	if ((vma->vm_end - vma->vm_start) > SZ_4M)
		vma->vm_end = vma->vm_start + SZ_4M;
	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
		     "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
		     __func__, proc->pid, vma->vm_start, vma->vm_end,
		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
		     (unsigned long)pgprot_val(vma->vm_page_prot));
	//#define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
	// 检查进程要映射的地址空间是否可写
	if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
		ret = -EPERM;
		failure_string = "bad vm_flags";
		goto err_bad_arg;
	}
	//VM_DONTCOPY	/* Do not copy this vma on fork */
	//VM_MIXEDMAP	/* Can contain "struct page" and pure PFN pages */
	// 禁止拷贝
	vma->vm_flags |= VM_DONTCOPY | VM_MIXEDMAP;
	// 为该内存赋予 r-x 权限
	vma->vm_flags &= ~VM_MAYWRITE;
	vma->vm_ops = &binder_vm_ops;
	vma->vm_private_data = proc;
	// 为进程分配内核缓冲区,并将这块物理内存分别映射到内核虚拟地址空间和用户虚拟内存空间
	ret = binder_alloc_mmap_handler(&proc->alloc, vma);
	if (ret)
		return ret;
	mutex_lock(&proc->files_lock);
	proc->files = get_files_struct(current);
	mutex_unlock(&proc->files_lock);
	return 0;
err_bad_arg:
	pr_err("%s: %d %lx-%lx %s failed %d\n", __func__,
	       proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
	return ret;
}

Binder 驱动程序为进程分配的内核缓冲区即为一系列物理页面,他们分别被映射到进程的用户地址空间和内核地址空间。当 Binder 驱动程序需要将一块数据传输给一个进程时,它可以先把这块数据保存在为该进程分配所分配的一块内核缓冲区中,然后再把这块内核缓冲区的用户空间地址告诉进程,最后进程就可以访问到里面的数据了。这样做的好处是不需要将内核空间拷贝到用户空间,从而提高了数据传输的效率.

binder_physical_memory

# binder 设备文件的 ioctl

binder_ioctl 函数负责在两个进程间收发 IPC 数据和 IPC reply 数据。

ioctl (input/output control) 是一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码。

ioctl 命令 数据类型 操作 使用场景
BINDER_WRITE_READ struct binder_write_read 收发 Binder IPC 数据 Binder 读写交互场景,IPC.talkWithDriver
BINDER_SET_IDLE_TIMEOUT __s64
BINDER_SET_MAX_THREADS __u32 设置 Binder 线程最大个数 初始化 ProcessState 对象,open_driver () ; 主动调整参数,ProcessState.setThreadPoolMaxThreadCount ()
BINDER_SET_IDLE_PRIORITY __s32
BINDER_SET_CONTEXT_MGR __s32 设置 Service Manager 节点 servicemanager 进程成为上下文管理者,binder_become_context_manager ()
BINDER_THREAD_EXIT __s32 释放 Binder 线程
BINDER_VERSION struct binder_version 获取 Binder 版本信息 初始化 ProcessState 对象,open_driver ()
BINDER_GET_NODE_DEBUG_INFO struct binder_node_debug_info
BINDER_GET_NODE_INFO_FOR_REF struct binder_node_info_for_ref
BINDER_SET_CONTEXT_MGR_EXT struct flat_binder_object
//kernel\drivers\android\binder.c
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;
	/*pr_info("binder_ioctl: %d:%d %x %lx\n",
			proc->pid, current->pid, cmd, arg);*/
	binder_selftest_alloc(&proc->alloc);
	trace_binder_ioctl(cmd, arg);
	ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
	if (ret)
		goto err_unlocked;
	thread = binder_get_thread(proc);
	if (thread == NULL) {
		ret = -ENOMEM;
		goto err;
	}
	switch (cmd) {
	// 进行 binder 的读写操作,这个命令使用的最为频繁
	case BINDER_WRITE_READ:
		ret = binder_ioctl_write_read(filp, cmd, arg, thread);
		if (ret)
			goto err;
		break;
	// 设置 binder 最大支持的线程数
	case BINDER_SET_MAX_THREADS: {
		int max_threads;
		if (copy_from_user(&max_threads, ubuf,
				   sizeof(max_threads))) {
			ret = -EINVAL;
			goto err;
		}
		binder_inner_proc_lock(proc);
		proc->max_threads = max_threads;
		binder_inner_proc_unlock(proc);
		break;
	}
	case BINDER_SET_CONTEXT_MGR_EXT: {
		struct flat_binder_object fbo;
		if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
			ret = -EINVAL;
			goto err;
		}
		ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
		if (ret)
			goto err;
		break;
	}
    // 成为 binder 的上下文管理者,也就是 ServiceManager 成为守护进程
	case BINDER_SET_CONTEXT_MGR:
		ret = binder_ioctl_set_ctx_mgr(filp, NULL);
		if (ret)
			goto err;
		break;
	// 当 binder 线程退出,释放 binder 线程
	case BINDER_THREAD_EXIT:
		binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
			     proc->pid, thread->pid);
		binder_thread_release(proc, thread);
		thread = NULL;
		break;
	// 获取 binder 的版本号
	case BINDER_VERSION: {
		struct binder_version __user *ver = ubuf;
		if (size != sizeof(struct binder_version)) {
			ret = -EINVAL;
			goto err;
		}
		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,
			     &ver->protocol_version)) {
			ret = -EINVAL;
			goto err;
		}
		break;
	}
	case BINDER_GET_NODE_INFO_FOR_REF: {
		struct binder_node_info_for_ref info;
		if (copy_from_user(&info, ubuf, sizeof(info))) {
			ret = -EFAULT;
			goto err;
		}
		ret = binder_ioctl_get_node_info_for_ref(proc, &info);
		if (ret < 0)
			goto err;
		if (copy_to_user(ubuf, &info, sizeof(info))) {
			ret = -EFAULT;
			goto err;
		}
		break;
	}
	case BINDER_GET_NODE_DEBUG_INFO: {
		struct binder_node_debug_info info;
		if (copy_from_user(&info, ubuf, sizeof(info))) {
			ret = -EFAULT;
			goto err;
		}
		ret = binder_ioctl_get_node_debug_info(proc, &info);
		if (ret < 0)
			goto err;
		if (copy_to_user(ubuf, &info, sizeof(info))) {
			ret = -EFAULT;
			goto err;
		}
		break;
	}
	default:
		ret = -EINVAL;
		goto err;
	}
	ret = 0;
err:
	if (thread)
		thread->looper_need_return = false;
	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
	if (ret && ret != -ERESTARTSYS)
		pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
	trace_binder_ioctl_done(ret);
	return ret;
}

# Binder 内部通信协议

Client 进程通过 RPC (Remote Procedure Call Protocol) 与 Server 通信,可以简单地划分为三层,应用层、IPC 层、内核驱动层。 demo() 是 Client 端和 Server 共同协商好的统一方法;handle、RPC 数据、代码、协议这 4 项组成了 IPC 层的数据,通过 IPC 层进行数据传输;而真正在 Client 和 Server 两端建立通信的基础设施便是 Binder Driver。

binder_ipc

# 通信模型

一次完整的 Binder 通信过程如下

binder_protocol

Binder 协议包含在 IPC 数据中,分为两类:

  • BINDER_COMMAND_PROTOCOL :binder 请求码,以”BC_“开头,简称 BC 码,用于从 IPC 层传递到 Binder Driver 层;

  • BINDER_RETURN_PROTOCOL :binder 响应码,以”BR_“开头,简称 BR 码,用于从 Binder Driver 层传递到 IPC 层;

Binder IPC 通信至少是两个进程的交互:

  • client 进程执行 binder_thread_write,根据 BC_XXX 命令,生成相应的 binder_work;
  • server 进程执行 binder_thread_read,根据 binder_work.type 类型,生成 BR_XXX,发送到用户空间处理。

# 通信过程

一次 Client 向 Server 通信的过程如图所示

binder_protocol

# BC_PROTOCOL

binder 请求码,是用 enum binder_driver_command_protocol 来定义的,是用于应用程序向 binder 驱动设备发送请求消息

请求码 参数类型 作用
BC_TRANSACTION binder_transaction_data Client 向 Binder 驱动发送请求数据
BC_REPLY binder_transaction_data Server 向 Binder 驱动发送请求数据
BC_FREE_BUFFER binder_uintptr_t (指针) 释放内存
BC_INCREFS __u32(descriptor) binder_ref 弱引用加 1 操作
BC_DECREFS __u32(descriptor) binder_ref 弱引用减 1 操作
BC_ACQUIRE __u32(descriptor) binder_ref 强引用加 1 操作
BC_RELEASE __u32(descriptor) binder_ref 强引用减 1 操作
BC_ACQUIRE_DONE binder_ptr_cookie binder_node 强引用减 1 操作
BC_INCREFS_DONE binder_ptr_cookie binder_node 弱引用减 1 操作
BC_REGISTER_LOOPER 无参数 创建新的 looper 线程
BC_ENTER_LOOPER 无参数 应用线程进入 looper
BC_EXIT_LOOPER 无参数 应用线程退出 looper
BC_REQUEST_DEATH_NOTIFICATION binder_handle_cookie 注册死亡通知
BC_CLEAR_DEATH_NOTIFICATION binder_handle_cookie 取消注册的死亡通知
BC_DEAD_BINDER_DONE binder_uintptr_t (指针) 已完成 binder 的死亡通知
BC_ACQUIRE_RESULT - -
BC_ATTEMPT_ACQUIRE - -
  • 当一个进程请求另外一个进程执行一个操作时,源进程就使用 BC_TRANSACTION 来请求 Binder 驱动进程将通信数据传递到目标进程
  • 当目标进程处理完成源进程所请求的操作之后,它就使用 BC_REPLY 来请求 Binder 驱动进程将结果数据传递给源进程
  • BC_FREE_BUFFER 后面跟的通信数据是一个整数,它指向了在 Binder 驱动进程内部所分配的一块内核缓冲区.Binder 驱动程序就是通过这个内核缓冲区将源进程的通信数据传递到目标进程的。当目标进程处理完成源进程的通信请求之后,它会使用 BC_FREE_BUFFER 来通知 Binder 驱动程序释放这个内核缓冲区
  • 当一个线程将自己注册到 Binder 驱动程序之后,它会使用 BC_ENTER_LOOPER 来通知 Binder 驱动程序,它已经准备就绪处理进程间通信请求了
  • 当 Binder 驱动程序主动请求进程注册一个新的线程到它的 Binder 线程池中来处理进程间通信请求之后,新创建的线程就会使用 BC_REGISTER_LOOPER 来通知 Binder 驱动程序,它准备就绪了
  • 当一个线程要退出时,它使用 BC_EXIT_LOOPER 从 Binder 驱动程序中注销,这样他就不会再接收到进程间通信请求了
  • 如果一个进程希望获得它所引用的 Service 组件的死亡接收通知,那么它需要使用 BC_REQUEST_DEATH_NOTIFICATION 来向 Binder 驱动程序注册一个死亡接收通知
  • 如果一个进程希望注销之前所注册的一个死亡接收通知,那么它需要使用 BC_CLEAR_DEATH_NOTIFICATION 来向 Binder 驱动程序发出请求
  • 当一个进程获得一个 Service 组件的死亡通知时,它会使用 BC_DEAD_BINDER_DONE 来通知 Binder 驱动程序,它已经处理完成该 Service 组件的死亡通知了

# binder_work

结构体 binder_work 用来描述待处理的工作项, binder_work.entry 用来将结构体嵌入到一个宿主结构中,通过 binder_work.type 的取值,Binder 就可以判断出一个 binder_work 结构体嵌入到什么类型的宿主结构中

struct binder_work {
	struct list_head entry;
	enum binder_work_type {
		BINDER_WORK_TRANSACTION = 1,// 最常见
		BINDER_WORK_TRANSACTION_COMPLETE,
		BINDER_WORK_RETURN_ERROR,
		BINDER_WORK_NODE,
		BINDER_WORK_DEAD_BINDER,
		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
	} type;
};
binder_work 类型 触发时机
BINDER_WORK_TRANSACTION binder_transaction() ; binder_release_work() 被调用
BINDER_WORK_TRANSACTION_COMPLETE binder_transaction() ; binder_release_work() 被调用
BINDER_WORK_NODE binder_new_node() 被调用
BINDER_WORK_DEAD_BINDER binder_thread_write() 收到 BC_REQUEST_DEATH_NOTIFICATION
BINDER_WORK_DEAD_BINDER_AND_CLEAR binder_thread_write() 收到 BC_CLEAR_DEATH_NOTIFICATION
BINDER_WORK_CLEAR_DEATH_NOTIFICATION binder_thread_write() 收到 BC_CLEAR_DEATH_NOTIFICATIONBC_DEAD_BINDER_DONE

# BR_PROTOCOL

binder 响应码,是用 enum binder_driver_return_protocol 来定义的,是 binder 设备向应用程序回复的消息

响应码 参数类型 作用 触发时机
BR_ERROR __s32 操作发生错误
BR_OK 无参数 操作完成
BR_NOOP 无参数 不做任何事
BR_SPAWN_LOOPER 无参数 创建新的 Looper 线程
BR_TRANSACTION binder_transaction_data Binder 驱动向 Server 端发送请求数据 收到 BINDER_WORK_TRANSACTION
BR_REPLY binder_transaction_data Binder 驱动向 Client 端发送回复数据 收到 BINDER_WORK_TRANSACTION
BR_TRANSACTION_COMPLETE 无参数 对请求发送的成功反馈 收到 BINDER_WORK_TRANSACTION_COMPLETE
BR_DEAD_REPLY 无参数 回复失败,往往是线程或节点为空
BR_FAILED_REPLY 无参数 回复失败,往往是 transaction 出错导致
BR_INCREFS binder_ptr_cookie binder_ref 弱引用加 1 操作(Server 端)
BR_DECREFS binder_ptr_cookie binder_ref 弱引用减 1 操作(Server 端)
BR_ACQUIRE binder_ptr_cookie binder_ref 强引用加 1 操作(Server 端)
BR_RELEASE binder_ptr_cookie binder_ref 强引用减 1 操作(Server 端)
BR_DEAD_BINDER binder_uintptr_t (指针) Binder 驱动向 client 端发送死亡通知 收到 BINDER_WORK_DEAD_BINDER 或 BINDER_WORK_DEAD_BINDER_AND_CLEAR
BR_CLEAR_DEATH_NOTIFICATION_DONE binder_uintptr_t (指针) BC_CLEAR_DEATH_NOTIFICATION 命令对应的响应码 收到 BINDER_WORK_CLEAR_DEATH_NOTIFICATION
BR_ACQUIRE_RESULT - -
BR_ATTEMPT_ACQUIRE - -
BR_FINISHED - -

# 协议转换图

BINDER_WORK_xxx –> BW_xxx

图解:(以 BC_TRANSACTION 为例)

  • 发起端进程:binder_transaction () 过程将 BC_TRANSACTION 转换为 BW_TRANSACTION;
  • 接收端进程:binder_thread_read () 过程,将 BW_TRANSACTION 转换为 BR_TRANSACTION;
  • 接收端进程:IPC.execute () 过程,处理 BR_TRANSACTION 命令。

protocol_transaction.jpg

protocol_binder_dead.jpg

# ServiceManager 介绍

我们知道在 Android 系统中,各个进程之间都是隔离的,假如 Clinet 想和 Server 通信,那么该如何找到 Server 呢?这就需要依靠 ServiceManager 了

ServiceManager 是 Android 进程间通信机制 Binder 的守护进程,它扮演着 Binder 进程间通信机制上下文管理者 (context Manager) 的角色,同时负责管理系统中的 Service 组件,向 Client 组件提供获取 Service 代理对象的服务

ServiceManager

我们可以将 binder 跨进程通信和 socket 网络通信类比,在网络通信中,客户端并不知道服务器的 IP 地址,但是知道服务器的域名,现在客户端想要和服务器建立 socket 连接,那么通信的第一步就是通过 DNS 服务器将域名解析为 IP 地址然后层层路由,这样客户端就可以和服务器建立网络连接了。binder 跨进程通信也不例外,ServiceManager 就相当于是 socket 网络通信中的 DNS 服务器,倘若 Server 希望有人能够和它通信,那么 Server 就先前往 Service Manager 那里 “备案” 一下(1. 注册服务),过了不久,Client 想要和 Server 去通信了,它就去询问 Service Manager:“Server 在什么地方呀,我要怎么和它通信呀”(2. 获取服务),然后 Service Manager 就告诉 Client 通信的方法,这样 Clinet 和 Server 就可以愉快的通信了~(3. 使用服务

# ServiceManager 的启动过程

ServiceManager 是由 init 进程通过解析 init.rc 文件创建的

# platform\system\core\rootdir\init.rc
on init
	...
	# Start essential services.
    start servicemanager

具体的服务声明在 platform\frameworks\native\cmds\servicemanager\servicemanager.rc

# platform\frameworks\native\cmds\servicemanager\servicemanager.rc
service servicemanager /system/bin/servicemanager
    class core animation# 指定了服务的类别为core和animation
    user system# 指定了服务用户为system,表示该服务将以系统用户的权限来运行
    group system readproc# 指定了服务的用户组为system,并具有 readproc 权限
    critical# 标志该服务为关键服务,这表示它是系统启动的一部分,必须优先启动

    # 要求在servicemanager重新启动时重启
    # apexd服务, audioserver服务, gatekeeperd服务
    # main类别的服务, hal类别的服务, early_hal类别的服务
    onrestart restart apexd
    onrestart restart audioserver
    onrestart restart gatekeeperd
    onrestart class_restart main
    onrestart class_restart hal
    onrestart class_restart early_hal

    # 将 servicemanager 的进程 ID 写入
    # /dev/cpuset/system-background/tasks文件,这可用于CPU集合管理
    writepid /dev/cpuset/system-background/tasks

    # 声明该服务为关键服务,在系统关闭时,这个服务将被优先关闭
    shutdown critical

Service Manager 的入口函数是 main.cpp 中的 main() , 它的启动过程由以下四个步骤组成

  1. 调用 ProcessState::initWithDriver 打开并映射 binder 驱动设备
  2. 将自身作为服务 (服务名称: manager ) 注册到 ServiceManager 中
  3. 调用 ps->becomeContextManager(); 成为 binder 进程间通信机制的上下文管理者
  4. 使用 looper 无限循环阻塞处理事件
//platform\frameworks\native\cmds\servicemanager\main.cpp
int main(int argc, char** argv) {
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }
	// 指定 driver 的名称,如果无参数,则使用默认驱动 /dev/binder
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
	/*
	每一个进程只能有一个 ProcessState 对象,service manager 通过 initWithDriver 方法
	实例化了一个 ProcessState 对象,并打开 binder 设备和进行 mmap 内存映射,这个过程中
	将会同时调用 binder 设备内部的函数 binder_open 和 binder_mmap
	*/
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
	// 设置可以同时存在的线程池的最大数量为 0, 即此时只能有 ServiceManager 这一个线程存在
    ps->setThreadPoolMaxThreadCount(0);
	// 在阻塞调用时中止进程
	//FATAL_IF_NOT_ONEWAY: ServiceManager 发起的 Binder 调用必须是单向,否则打印堆栈日志提示
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
	// 实例化 ServiceManager, 初始化参数为 Access 对象的智能指针
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
	//self register servicemanager,"manager" 将作为 servicemanager 的第一个服务被注册
	if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }
	// 将 "manager" 服务作为服务端 Bbinder 对象
    IPCThreadState::self()->setTheContextObject(manager);
	// 向 binder 驱动发送 ioctl BINDER_SET_CONTEXT_MGR_EXT 信号,将 servicemanager
	// 在 ProcessState::initWithDriver 中打开驱动设备 /dev/driver 所返回的文件描述符句柄
	// 作为整个 binder IPC 通信中的上下文管理者
    ps->becomeContextManager();
	// 准备 looper
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
	// 监听 BC_ENTER_LOOPER 信号,收到该信号后回调处理 binder 调用
    BinderCallback::setupTo(looper);
	// 监听客户端回调
    ClientCallbackCallback::setupTo(looper, manager);
	// 阻塞等待和处理事件
    while(true) {
        looper->pollAll(-1);
    }
    // should not be reached
    return EXIT_FAILURE;
}

# ProcessState::init

//platform\frameworks\native\libs\binder\ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
    return init(kDefaultDriver, false /*requireDefault*/);
}
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
    return init(driver, true /*requireDefault*/);
}
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
    [[clang::no_destroy]] static sp<ProcessState> gProcess;
    [[clang::no_destroy]] static std::mutex gProcessMutex;
    if (driver == nullptr) {
        std::lock_guard<std::mutex> l(gProcessMutex);
        return gProcess;
    }
	/*
	这里使用了单例模式的设计思想,通过 std::once_flag 和 std::call_once
	来保证只有一个线程可以进入初始化代码块,
	这保证了在一个线程中只能有一个 ProcessState 实例
	
	它的工作方式如下
	[-] 第一次调用 std::call_once 时,它会检查与 std::once_flag 关联的标记是否已被设置。
	如果标记尚未设置,它将执行传递给 std::call_once 的可调用对象,
	并设置标记,以标记初始化已完成。
	
	[-] 如果其他线程尝试再次调用 std::call_once 与相同的 std::once_flag,
	它会发现标记已经设置,因此不会再次执行可调用对象。
	*/
    [[clang::no_destroy]] static std::once_flag gProcessOnce;
    std::call_once(gProcessOnce, [&](){
		// 判断 binder 驱动是否存在
        if (access(driver, R_OK) == -1) {
            ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
            driver = "/dev/binder";
        }
        std::lock_guard<std::mutex> l(gProcessMutex);
		// 将 driver 作为参数实例化 ProcessState, 并赋值给 gProcess
        gProcess = sp<ProcessState>::make(driver);
    });
    if (requireDefault) {
        // Detect if we are trying to initialize with a different driver, and
        // consider that an error. ProcessState will only be initialized once above.
        LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
                            "ProcessState was already initialized with %s,"
                            " can't initialize with %s.",
                            gProcess->getDriverName().c_str(), driver);
    }
    return gProcess;
}

# ProcessState 构造函数

在代码的第 26 行,通过 driver 参数实例化了 ProcessState, 它通过 open_driver() 打开了 binder 驱动设备,并使用 mmap 来进行内存映射

//platform\frameworks\native\libs\binder\ProcessState.cpp
ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))// 通过系统调用陷入内核,打开 /dev/binder 设备
    , mVMStart(MAP_FAILED)// 映射内存的起始地址
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mWaitingForThreads(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        // 调用内存映射函数 mmap, 此时 binder 驱动会在内核空间执行 binder_mmap, 来将一块物理内存同时映射到
        // 用户空间和内核空间,来帮助进行跨进程通信
        // #define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2) = 1016KB
        // PAGE_SIZE 被定义为 4096
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }
#ifdef __ANDROID__
    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
#endif
}

# open_driver

//platform\frameworks\native\libs\binder\ProcessState.cpp
static int open_driver(const char *driver)
{
	// 以读写方式打开,并为该文件描述符添加 close-on-exec (执行时可关闭) 的标志,
	// 来防止该文件描述符被意外泄漏给了 fork 创建出来的子进程
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
          ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
                vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
            close(fd);
            fd = -1;
        }
		// 设置这个打开的 binder 对象的最大线程数为 15
        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));
        }
        uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
        result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
        if (result == -1) {
            ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
        }
    } else {
        ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
    }
    return fd;
}

# 总结

img

# Binder 中各个类的含义

在进行后续的学习前,我们先来了解一下 Binder 中各个类的含义

类名 说明
BpRefBase RefBase 的子类,提供 remote () 方法获取远程 Binder
IInterface Binder 服务接口的基类,Binder 服务通常需要同时提供本地接口和远程接口
BpInterface 远程接口的基类,远程接口是供客户端调用的接口集
BnInterface 本地接口的基类,本地接口是需要服务中真正实现的接口集
IBinder Binder 对象的基类,BBinder 和 BpBinder 都是这个类的子类
BpBinder 远程 Binder,这个类提供 transact 方法来发送请求,BpXXX 实现中会用到
BBinder 本地 Binder,服务实现方的基类,提供了 onTransact 接口来接收请求
ProcessState 代表了使用 Binder 的进程
IPCThreadState 代表了使用 Binder 的线程,这个类中封装了与 Binder 驱动通信的逻辑
Parcel 在 Binder 上传递的数据的包装器

Binder 服务的实现类通常都会遵守下面的命名规则

  • 服务的接口使用 I 字母作为前缀
  • 远程接口使用 Bp 作为前缀
  • 本地接口使用 Bn 作为前缀
  • p 即 proxy 的意思,是客户端用来与 Server 交互的类

IBinder 家族

image

BpBinder 和 BBinder 都是 Android 中与 Binder 通信相关的代表,它们都从 IBinder 类中派生而来

  • BpBinder 是客户端用来与 Server 交互的代理类,p 即 proxy 的意思
  • BBinder 则是 proxy 相对的一端,它是 proxy 交互的目的端。如果说 BpBinder 代表客户端,那么 BBinder 则代表服务端。这里的 BpBinder 和 BBinder 是一一对应的,即某个 BpBinder 只能和对应的 BBinder 交互
  • 在注册服务和获取服务的过程中,ServiceManager 均为服务端
  • BpBinder 通过 handle 来标识它所对应的 BBinder 端,与其相关的函数为 sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) ,handle 值为 0 表示 ServiceManager 所对应的 BBinder

IServiceManager 家族

image

  • IServiceManager、BpServiceManager 和 BnServiceManager 都与业务逻辑相关。

  • BnServiceManager 同时从 BBinder 派生,表示它可以直接参与 Binder 通信。

  • BpServiceManager 虽然从 BpInterface 中派生,但是这条分支似乎与 BpBinder 没有关系。

  • BnServiceManager 是一个虚类,它的业务函数最终需要子类来实现。

# ServiceManager 的获取过程

当一个 Server 想要注册服务,那必须要知道 "ServiceManager 在哪里才可以", 所以需要有一个方法来让 Server 找到 ServiceManager, 这是通过函数 defaultServiceManager 实现的

// 获取 BpServiceManager 对象
sp<IServiceManager> sm(defaultServiceManager());

defaultServiceManager 的主要作用是获取 BpServiceManager 对象,它通过 getContextObject 获取到了 ServiceManager 的 BBinder 所对应的 BpBinder 对象,随后利用 interface_castBpBinder 对象转换成了 BpServiceManager 对象

//platform\frameworks\native\libs\binder\IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
    std::call_once(gSmOnce, []() {
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
			// 获取 ServiceManager 的 BBinder 所对应的 BpBinder 对象,
			// 并将该对象通过 interface_cast 转换为 AidlServiceManager
            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
                ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
                sleep(1);
            }
        }
		// 实例化 ServiceManagerShim
        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });
    return gDefaultServiceManager;
}

AidlServiceManager

AidlServiceManager 其实是 android::os::IServiceManager 的别名

using AidlServiceManager = android::os::IServiceManager;

ServiceManagerShim

之前是没有 ServiceManagerShim 的,而是直接操作 BpServiceManager,这个辅助类封装了 AIDL 自动生成的 BpServiceManager,所以现在的客户端代码流就变成如下三步:

1.      用户代码 
2. libbinder代码  binder/IServiceManager.cpp#ServiceManagerShim
3.     AIDL 代码  android/os/IServiceManager.cpp#BpServiceManager 接口

libbinder 中的 ServiceManagerShim 起到了一个中转的作用,把请求转给 out 下 AIDL 自动生成的 BpServiceManager, 原来是在 libbinder#IServiceManager.cpp 中手写实现,现在是 AIDL 帮你实现。

//platform\frameworks\native\libs\binder\IServiceManager.cpp
// From the old libbinder IServiceManager interface to IServiceManager.
class ServiceManagerShim : public IServiceManager
{
public:
    explicit ServiceManagerShim (const sp<AidlServiceManager>& impl);
    sp<IBinder> getService(const String16& name) const override;
    sp<IBinder> checkService(const String16& name) const override;
    status_t addService(const String16& name, const sp<IBinder>& service,
                        bool allowIsolated, int dumpsysPriority) override;
    Vector<String16> listServices(int dumpsysPriority) override;
    sp<IBinder> waitForService(const String16& name16) override;
    bool isDeclared(const String16& name) override;
    Vector<String16> getDeclaredInstances(const String16& interface) override;
    std::optional<String16> updatableViaApex(const String16& name) override;
    // for legacy ABI
    const String16& getInterfaceDescriptor() const override {
        return mTheRealServiceManager->getInterfaceDescriptor();
    }
    IBinder* onAsBinder() override {
        return IInterface::asBinder(mTheRealServiceManager).get();
    }
private:
    sp<AidlServiceManager> mTheRealServiceManager;
};

# getContextObject

这个函数最主要的功能就是获取 ServiceManager 的 BBinder 所对应的 BpBinder 对象,它通过调用 getStrongProxyForHandle(0) 来进行获取

这里传入的 handle 的值为 0, 它表示 ServiceManager 所对应的 BBinder

//platform\frameworks\native\libs\binder\ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
	// 创建一个 BpBinder 对象,getStrongProxyForHandle 传入的参数 handle 的值为 0
	//,0 代表的就是 ServiceManager 所对应的 BBinder。
    sp<IBinder> context = getStrongProxyForHandle(0);
    if (context) {
        // The root object is special since we get it directly from the driver, it is never
        // written by Parcell::writeStrongBinder.
        internal::Stability::markCompilationUnit(context.get());
    } else {
        ALOGW("Not able to get context object on %s.", mDriverName.c_str());
    }
    return context;
}

getStrongProxyForHandle(0)

//platform\frameworks\native\libs\binder\ProcessState.cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
	// 根据索引查找对应资源。
    handle_entry* e = lookupHandleLocked(handle);
	// 如果 lookupHandleLocked 发现没有对应的资源项,则会创建一个新的项并返回。
    if (e != nullptr) {
        // 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.  The
        // attemptIncWeak() is safe because we know the BpBinder destructor will always
        // call expungeHandle(), which acquires the same lock we are holding now.
        // We need to do this because there is a race condition between someone
        // releasing a reference on this BpBinder, and a new reference on its handle
        // arriving from the driver.
        IBinder* b = e->binder;
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                // Special case for context manager...
                // The context manager is the only object for which we create
                // a BpBinder proxy without already holding a reference.
                // Perform a dummy transaction to ensure the context manager
                // is registered before we create the first local reference
                // to it (which will occur when creating the BpBinder).
                // If a local reference is created for the BpBinder when the
                // context manager is not present, the driver will fail to
                // provide a reference to the context manager, but the
                // driver API does not return status.
                //
                // Note that this is not race-free if the context manager
                // dies while this code runs.
                //
                // TODO: add a driver API to wait for context manager, or
                // stop special casing handle 0 for context manager and add
                // a driver API to get a handle to the context manager with
                // proper reference counting.
                IPCThreadState* ipc = IPCThreadState::self();
                CallRestriction originalCallRestriction = ipc->getCallRestriction();
                ipc->setCallRestriction(CallRestriction::NONE);
                Parcel data;
                status_t status = ipc->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                ipc->setCallRestriction(originalCallRestriction);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }
			// 创建一个 BpBinder
            sp<BpBinder> b = BpBinder::create(handle);
            e->binder = b.get();
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // 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);
            e->refs->decWeak(this);
        }
    }
    return result;
}

# interface_cast

//platform\frameworks\native\libs\binder\include\binder\IInterface.h
/**
 * If this is a local object and the descriptor matches, this will return the
 * actual local object which is implementing the interface. Otherwise, this will
 * return a proxy to the interface without checking the interface descriptor.
 * This means that subsequent calls may fail with BAD_TYPE.
 */
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

这是一个模板函数,其中的 asInterface 是在 DECLARE_META_INTERFACE 宏中定义的

asInterface

//platform\frameworks\native\include\binder\IInterface.h
//## 的作用是将前后两个标识符或符号连接在一起,以形成一个单独的标识符或符号。
// 如 #define CONCATENATE (x, y) x##y
// 如果调用 CONCATENATE (a, b),它将被展开为 ab
#define DECLARE_META_INTERFACE(INTERFACE)                               \
public:                                                                 \
    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();                                            \
    static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl);     \
    static const std::unique_ptr<I##INTERFACE>& getDefaultImpl();       \
private:                                                                \
    static std::unique_ptr<I##INTERFACE> default_impl;                  \
public:                                                                 \
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)    \
    
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\
    const ::android::StaticString16                                     \
        I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
    const ::android::String16 I##INTERFACE::descriptor(                 \
        I##INTERFACE##_descriptor_static_str16);                        \
    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 != nullptr) {                                           \
            intr = ::android::sp<I##INTERFACE>::cast(                   \
                obj->queryLocalInterface(I##INTERFACE::descriptor));    \
            if (intr == nullptr) {                                      \
                intr = ::android::sp<Bp##INTERFACE>::make(obj);         \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl;           \
    bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\
    {                                                                   \
        /* Only one user of this interface can use this function     */ \
        /* at a time. This is a heuristic to detect if two different */ \
        /* users in the same process use this function.              */ \
        assert(!I##INTERFACE::default_impl);                            \
        if (impl) {                                                     \
            I##INTERFACE::default_impl = std::move(impl);               \
            return true;                                                \
        }                                                               \
        return false;                                                   \
    }                                                                   \
    const std::unique_ptr<I##INTERFACE>& I##INTERFACE::getDefaultImpl() \
    {                                                                   \
        return I##INTERFACE::default_impl;                              \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

我们将 interface_cast<AidlServiceManager>(new BpBinder(0)) 通过宏定义替换一下看的会更加清楚,在这里 asInterfaceBpBinder 转换成了 BpServiceManager , BpServiceManager 继承了 IServiceManager

public:
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();
static bool setDefaultImpl(std::unique_ptr<IServiceManager> impl);
static const std::unique_ptr<IServiceManager>& getDefaultImpl();
private:
static std::unique_ptr<IServiceManager> default_impl;
public:
const ::android::StaticString16
    IServiceManager_descriptor_static_str16(__IINTF_CONCAT(u, android.os.IServiceManager));
const ::android::String16 IServiceManager::descriptor(
    IServiceManager_descriptor_static_str16);
const ::android::String16&
    IServiceManager::getInterfaceDescriptor() const {
    return IServiceManager::descriptor;
}
// 在这里终于出现了 asInterface 函数的定义,我们也找到了 BpServiceManager 这个类
::android::sp<IServiceManager> IServiceManager::asInterface(
    const ::android::sp<::android::IBinder>& obj)
{
    ::android::sp<IServiceManager> intr;
    if (obj != nullptr) {
        intr = ::android::sp<IServiceManager>::cast(
            obj->queryLocalInterface(IServiceManager::descriptor));
        if (intr == nullptr) {
            intr = ::android::sp<BpServiceManager>::make(obj);
        }
    }
    return intr;
}
std::unique_ptr<IServiceManager> IServiceManager::default_impl;
bool IServiceManager::setDefaultImpl(std::unique_ptr<IServiceManager> impl)
{
    /* Only one user of this interface can use this function     */
    /* at a time. This is a heuristic to detect if two different */
    /* users in the same process use this function.              */
    assert(!IServiceManager::default_impl);
    if (impl) {
        IServiceManager::default_impl = std::move(impl);
        return true;
    }
    return false;
}
const std::unique_ptr<IServiceManager>& IServiceManager::getDefaultImpl()
{
    return IServiceManager::default_impl;
}
IServiceManager::IServiceManager() { }
IServiceManager::~IServiceManager() { }

# 总结

img

# Server 向 ServiceManager 注册服务

这里以 MediaServer 为例来分析 Server 向 ServiceManager 注册服务的过程

//platform\frameworks\av\media\mediaserver\main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
	// 创建一个 ProcessState 实例,打开默认驱动 /dev/binder 并进行 mmap 内存映射
	// 此方法的详细分析请参见右侧目录 ServiceManager 的启动过程 ->ProcessState::init
    sp<ProcessState> proc(ProcessState::self());
	// 客户端获取 ServiceManagerShim 对象
	// 此方法的详细分析请参见右侧目录 ServiceManager 的获取过程
    sp<IServiceManager> sm(defaultServiceManager());
    ALOGI("ServiceManager: %p", sm.get());
	// 注册 media.player 服务
    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
    registerExtensions();
    ::android::hardware::configureRpcThreadpool(16, false);
	// 启动线程池
    ProcessState::self()->startThreadPool();
	// 将线程加入线程池
    IPCThreadState::self()->joinThreadPool();
    ::android::hardware::joinRpcThreadpool();
}

MediaPlayerService::instantiate

这个函数的作用就是调用 defaultServiceManager 的 addService 方法来添加向 ServiceManager 注册服务

//platform\frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
        String16("media.player"), new MediaPlayerService());
}

# defaultServiceManager()->addService

//platform\frameworks\native\libs\binder\IServiceManager.cpp
status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
                                        bool allowIsolated, int dumpsysPriority)
{
    Status status = mTheRealServiceManager->addService(
        String8(name).c_str(), service, allowIsolated, dumpsysPriority);
    return status.exceptionCode();
}

这里使用了 mTheRealServiceManager 中的 addService 方法,那么 mTheRealServiceManager 是从哪里来的呢?

# mTheRealServiceManager

//platform\frameworks\native\libs\binder\IServiceManager.cpp
using AidlServiceManager = android::os::IServiceManager;
// From the old libbinder IServiceManager interface to IServiceManager.
class ServiceManagerShim : public IServiceManager
{
public:
    ...
private:
    sp<AidlServiceManager> mTheRealServiceManager;
};
ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl)
 : mTheRealServiceManager(impl)
{}

从这段 ServiceManagerShim 类的声明中,我们可以清楚的看到 mTheRealServiceManager 是 android::os::IServiceManager 类型的实例,并且在 ServiceManagerShim 实例化时赋值

而在 ServiceManager 的获取过程 中,我们知道 ServiceManagerShim 是在 defaultServiceManager() 中实例化的

//platform\frameworks\native\libs\binder\IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
    std::call_once(gSmOnce, []() {
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
			//获取ServiceManager的BBinder所对应的BpBinder对象,
			//并将该对象通过interface_cast转换为AidlServiceManager
            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
                ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
                sleep(1);
            }
        }
		//实例化ServiceManagerShim
        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });

    return gDefaultServiceManager;
}

所以说 mTheRealServiceManager 其实是 BpServiceManager(new BpBinder(0)) , 注册服务的顺序为 BpServiceManager-->BpBinder-->IPCThreadState-->ioctl

BpServiceManager 现在是由 AIDL 自动生成在框架编译完成之后的 out 目录中的

BpServiceManager::addService

//platform/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/IServiceManager.cpp
namespace android {
namespace os {

BpServiceManager::BpServiceManager(const ::android::sp<::android::IBinder>& _aidl_impl)
    : BpInterface<IServiceManager>(_aidl_impl){//_aidl_impl 就是 BpBinder(0) 实例
}
--------------------------------------------------
    ::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) {
  ::android::Parcel _aidl_data;
  _aidl_data.markForBinder(remoteStrong());//0、和 Rpc Binder有关
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  //1、写 interface
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  //2、写 name
  _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  //3、写 binder 对象
  _aidl_ret_status = _aidl_data.writeStrongBinder(service);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  //4、写 allowIsolated
  _aidl_ret_status = _aidl_data.writeBool(allowIsolated);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  //5、写 dumpPriority
  _aidl_ret_status = _aidl_data.writeInt32(dumpPriority);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  //6、借助 BpBinder(0)#transact 来发起 Binder 通信
  _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0);
  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IServiceManager::getDefaultImpl())) {
     return IServiceManager::getDefaultImpl()->addService(name, service, allowIsolated, dumpPriority);
  }
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  //7、如果有返回值就从这个 parcel 包里读
  _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  if (!_aidl_status.isOk()) {
    return _aidl_status;
  }
  _aidl_error:
  _aidl_status.setFromStatusT(_aidl_ret_status);
  return _aidl_status;
}

这个过程主要是借助 BpBinder (0)#transact 来发起 Binder 通信,Binder 驱动根据 handle == 0 找到我们的 ServiceManager 进程,唤醒他开始处理请求。

还记得在 ServiceManager 的启动过程 中的那个 while 循环函数吗?BinderCallback 就是用来处理 Binder 驱动发送的 BR_TRANSACTION 信号的

//platform\frameworks\native\cmds\servicemanager\main.cpp
int main(int argc, char** argv) {
    ...
	//准备looper
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

	//监听BC_ENTER_LOOPER信号,收到该信号后回调处理binder调用
    BinderCallback::setupTo(looper);

	//监听客户端回调
    ClientCallbackCallback::setupTo(looper, manager);

	//阻塞等待和处理事件
    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

# BinderCallback

BinderCallback::handleEvent 调用了 IPCThreadState::self()->handlePolledCommands() 来处理命令

//platform\frameworks\native\cmds\servicemanager\main.cpp
class BinderCallback : public LooperCallback {
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = sp<BinderCallback>::make();

        int binder_fd = -1;
		//监听BC_ENTER_LOOPER信号
        IPCThreadState::self()->setupPolling(&binder_fd);
        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);

        int ret = looper->addFd(binder_fd,
                                Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT,
                                cb,
                                nullptr /*data*/);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }

    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

# IPCThreadState::handlePolledCommands

//platform\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::handlePolledCommands()
{
    status_t result;

    do {
        //获取并执行命令
        result = getAndExecuteCommand();
    } while (mIn.dataPosition() < mIn.dataSize());

    processPendingDerefs();
    flushCommands();
    return result;
}

# IPCThreadState::getAndExecuteCommand

//platform\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;

	//和binder驱动交流,获取或传输数据
    result = talkWithDriver();
    if (result >= NO_ERROR) {
        size_t IN = mIn.dataAvail();
        if (IN < sizeof(int32_t)) return result;
		//读取命令
        cmd = mIn.readInt32();
        IF_LOG_COMMANDS() {
            alog << "Processing top-level Command: "
                 << getReturnString(cmd) << endl;
        }

        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount++;
        if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs == 0) {
            mProcess->mStarvationStartTimeMs = uptimeMillis();
        }
        pthread_mutex_unlock(&mProcess->mThreadCountLock);

		//解析并执行命令
        result = executeCommand(cmd);

        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount--;
        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs != 0) {
            int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
            if (starvationTimeMs > 100) {
                ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
                      mProcess->mMaxThreads, starvationTimeMs);
            }
            mProcess->mStarvationStartTimeMs = 0;
        }

        // Cond broadcast can be expensive, so don't send it every time a binder
        // call is processed. b/168806193
        if (mProcess->mWaitingForThreads > 0) {
            pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
        }
        pthread_mutex_unlock(&mProcess->mThreadCountLock);
    }

    return result;
}

# IPCThreadState::executeCommand

//platform\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd)
{
	switch ((uint32_t)cmd) {
		case BR_TRANSACTION:
        {	//因为目的端 SM 所以 tr.target.ptr 为 0
        	if (tr.target.ptr) {
        	...
        	}else {//开始业务分发
        	    error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
        	}

ServiceManager 的启动过程 这节的内容中,我们让 ServiceManager 成为了整个 binder IPC 通信中的上下文管理者,并将其存储在全局变量 the_context_object

//platform\frameworks\native\cmds\servicemanager\main.cpp
sp<BBinder> the_context_object;

void IPCThreadState::setTheContextObject(const sp<BBinder>& obj)
{
    the_context_object = obj;
}

int main(int argc, char** argv) {
    ...
	//将"manager"服务作为服务端Bbinder对象
    IPCThreadState::self()->setTheContextObject(manager);
	//向binder驱动发送ioctl BINDER_SET_CONTEXT_MGR_EXT信号,将servicemanager
	//在ProcessState::initWithDriver中打开驱动设备/dev/driver所返回的文件描述符句柄
	//作为整个binder IPC通信中的上下文管理者
    ps->becomeContextManager();
	...
}

所以 the_context_object->transact() 调用就走到 BBinder 的 transact

//platform\frameworks\native\libs\binder\Binder.cpp

// NOLINTNEXTLINE(google-default-arguments)
status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    if (reply != nullptr && (flags & FLAG_CLEAR_BUF)) {
        reply->markSensitive();
    }

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            err = pingBinder();
            break;
        case EXTENSION_TRANSACTION:
            err = reply->writeStrongBinder(getExtension());
            break;
        case DEBUG_PID_TRANSACTION:
            err = reply->writeInt32(getDebugPid());
            break;
        default:
            err = onTransact(code, data, reply, flags);
            break;
    }

    // In case this is being transacted on in the same process.
    if (reply != nullptr) {
        reply->setDataPosition(0);
    }

    return err;
}

然后回到了这个 AIDL 自动生成的 IServiceManager.cpp 中 BnServiceManager 的 onTransact () 方法里

//platform/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/IServiceManager.cpp

::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
  ::android::status_t _aidl_ret_status = ::android::OK;
  switch (_aidl_code) {
  case BnServiceManager::TRANSACTION_addService:
  {
    ::std::string in_name;
    ::android::sp<::android::IBinder> in_service;
    bool in_allowIsolated;
    int32_t in_dumpPriority;
    //检查 interface
    if (!(_aidl_data.checkInterface(this))) {
      _aidl_ret_status = ::android::BAD_TYPE;
      break;
    }
    //读 name
    _aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    //读 binder
    _aidl_ret_status = _aidl_data.readStrongBinder(&in_service);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    //读 in_allowIsolated
    _aidl_ret_status = _aidl_data.readBool(&in_allowIsolated);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    //读 in_dumpPriority
    _aidl_ret_status = _aidl_data.readInt32(&in_dumpPriority);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    //调用真正的 ServiceManager.cpp 中的实现
    ::android::binder::Status _aidl_status(addService(in_name, in_service, in_allowIsolated, in_dumpPriority));
    //如果有返回写返回到 _aidl_reply
    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    if (!_aidl_status.isOk()) {
      break;
    }
  }

这里是和 Bp 端是对称的操作,下一步走到 ServiceManager.cpp::addService 方法

//platform\frameworks\native\cmds\servicemanager\ServiceManager.cpp

Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    auto ctx = mAccess->getCallingContext();

    // apps cannot add services
    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    if (!mAccess->canAdd(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    if (binder == nullptr) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

	//检验Service名称的合法性,名称长度要求大于0并小于等于127
	//字符仅包括[a-z][A-Z][0-9]_-./
    if (!isValidServiceName(name)) {
        LOG(ERROR) << "Invalid service name: " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

#ifndef VENDORSERVICEMANAGER
    if (!meetsDeclarationRequirements(binder, name)) {
        // already logged
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }
#endif  // !VENDORSERVICEMANAGER

    // implicitly unlinked when the binder is removed
    // 为binder对象设置死亡代理
    /*
	在和service进行交互时,service返回一个Binder对象。
	Binder是工作在service端,如果,由于某种原因,服务端出现故障而死亡,
	那么该返回的Binder对象也将消失,这时,如果我们在客户端在使用Binder对象
	进行某些函数调用将会出现错误。为了避免该情况的发生,我们可以为
	Binder对象设置死亡代理(linkToDeath)。当出现和服务端连接发生故障时,
	系统将自动调用死亡代理函数binderDied()。
	*/
    if (binder->remoteBinder() != nullptr &&
        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
        LOG(ERROR) << "Could not linkToDeath when adding " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
    }

    // Overwrite the old service if it exists
    //添加服务,以name作为索引值,使用binder作为参数实例化Service对象
    mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };


	/*检查服务注册的合法性,包括
	1.服务是否存在
	2.该服务是否是服务端注册的
	3.是否有同名服务存在
	4.为该服务注册的死亡代理是否成功
	*/
    auto it = mNameToRegistrationCallback.find(name);
    if (it != mNameToRegistrationCallback.end()) {
        for (const sp<IServiceCallback>& cb : it->second) {
            mNameToService[name].guaranteeClient = true;
            // permission checked in registerForNotifications
            cb->onRegistration(name, binder);
        }
    }

    return Status::ok();
}

# 总结

Server 想要向 ServiceManager 注册服务,首先通过 defaultServiceManager 获取到一个 Service Manager 的代理对象,然后再调用它的成员函数 addService 将该 Service 组件注册到 Service Manager 中,该代理对象通过向 Binder 驱动设备发送 BC_TRANSACTION 信号和 Service Manager 通信,在 Service Manager 启动之后会进入一个阻塞的无限循环, Service Manager 通过 BinderCallback 回调函数处理 Binder 驱动设备返回的 BR_TRANSACTION , 调用 BBinder 的 transact 方法,这个方法将会把我们引到 BnServiceManager 的 onTransact () 方法,终于这个方法将我们带到了真正添加服务的方法 ServiceManager.cpp::addService

img

# Client 向 ServiceManager 获取服务

# 参考资料

  • gityuan 大佬的 Binder 系列
  • 第 6 章 深入理解 Binder
  • Android 12 系统源码分析 | Native Binder 代码变迁
  • Android 深入浅出之 Binder 机制
  • 理解 Android Binder 机制 (2/3):C++ 层
更新于 阅读次数