【android10】【binder】【3.向servicemanager注册服务】

系列文章目录

 可跳转到下面链接查看下表所有内容https://blog.youkuaiyun.com/handsomethefirst/article/details/138226266?spm=1001.2014.3001.5501文章浏览阅读2次。系列文章大全https://blog.youkuaiyun.com/handsomethefirst/article/details/138226266?spm=1001.2014.3001.5501


目录

系列文章目录

1.简介

1.1 时序图

1.1流程介绍

2 meidaservice的启动——源码分析

2.1 获取ProcessState对象

2.1.1 ProcessState::ProcessState

 2.1.2 ProcessState::init

2.1.3 open_driver

2.1.4 binder_open

2.1.5 获取版本号binder_ioctl

2.1.6 设置binder最大线程数binder_ioctl

2.1.7 binder_mmap

2.1.8 binder_update_page_range

 2.2 获取bpServiceManager对象

2.2.1 defaultServiceManager

2.2.2 ProcessState::getContextObject

2.2.3 ProcessState::getStrongProxyForHandle

2.2.4 ProcessState::lookupHandleLocked

2.2.5 BpBinder::create

2.2.6 BpBinder::BpBinder

2.2.7 IPCThreadState::self

2.2.8 IPCThreadState::IPCThreadState

2.2.9 IPCThreadState::incWeakHandle

2.2.10 interface_cast

2.2.11 asInterface

2.2.12 queryLocalInterface

2.2.13 BpServiceManager::BpServiceManager

2.2.14 BpInterface::BpInterface

2.2.15 BpRefBase::BpRefBase

2.3 注册多媒体服务到servicemanager

2.3.1 MediaPlayerService::instantiate

2.3.2 IServiceManager::addService

 2.3.3 writeStrongBinder

2.3.4  flatten_binder

2.3.5 BpBinder::transact

2.3.6 IPCThreadState::transact

2.3.7 IPCThreadState::writeTransactionData

2.3.8 IPCThreadState::waitForResponse向驱动发送请求add服务的消息

2.3.9 IPCThreadState::talkWithDriver

2.3.10 binder_ioctl

2.3.11 binder_thread_write(增加SM对应的句柄0的引用计数)

 2.3.12 binder_thread_write(处理media服务请求add的消息)

2.3.13 binder_transaction

2.4 mediapalyservice服务陷入休眠

2.4.1 binder_ioctl

2.4.2 binder_thread_read

2.4.3 IPCThreadState::talkWithDriver

2.4.4 IPCThreadState::waitForResponse

2.4.5 talkWithDriver第三次循环(同步消息才会有):

2.4.6 binder_ioctl

2.4.7 binder_thread_read

2.5 ServiceManager被唤醒

2.5.1 binder_thread_read

2.5.2 binder_ioctl

2.5.3 binder_loop

2.5.4 binder_parse

2.5.5 bio_init

2.5.6 bio_init_from_txn

2.5.7 svcmgr_handler

2.5.8 bio_get_ref

2.5.9 do_add_service

2.5.10 find_svc

2.5.11 binder_acquire

2.5.12 binder_write

2.5.13 binder_ioctl

2.5.14 binder_thread_write

2.5.16 binder_write

2.5.17 binder_ioctl

2.5.18 binder_thread_write

2.6 Servicemanager服务发送reply消息给meidaservice

2.6.1 bio_put_uint32

2.6.2 bio_alloc

2.6.3 binder_send_reply

2.6.4 binder_write

2.6.5 binder_ioctl

2.6.6 binder_thread_write

2.6.7 binder_transaction

2.7 servicemanager处理未完成事务,并再次陷休眠

2.7.1 binder_loop

2.7.2 binder_ioctl

2.7.3 binder_thread_read

2.7.4 binder_parse

2.7.5 sm主线程再次休眠,等待来自驱动的消息

2.8 唤醒meidaservice服务,meida服务处理reply消息

2.8.1 binder_thread_read

2.8.2 binder_ioctl

2.8.3 talkWithDriver

2.8.4 waitForResponse

2.8.5 Parcel::ipcSetDataReference

2.9 ProcessState::startThreadPool

2.9.1 ProcessState::spawnPooledThread

2.9.2 threadLoop

2.9.3 IPCThreadState::joinThreadPool

2.9.4 IPCThreadState::getAndExecuteCommand

2.9.5 IPCThreadState::talkWithDriver

2.9.6 binder_ioctl

2.9.7 binder_thread_write

2.9.8 死循环用于获取来自驱动的消息

 2.9.9 getAndExecuteCommand

2.9.10 talkWithDriver

2.9.11 binder_ioctl

2.9.12 binder_thread_read

2.10 joinThreadPool

2.10.1 IPCThreadState::joinThreadPool

2.10.2 IPCThreadState::getAndExecuteCommand

2.10.3 IPCThreadState::talkWithDriver

2.10.4 binder_ioctl

2.10.5 binder_thread_write

2.10.6 死循环用于获取来自驱动的消息

 2.10.7 getAndExecuteCommand

2.10.8 talkWithDriver

2.10.9 binder_ioctl

2.10.10 binder_thread_read


1.简介

此篇我们便从源码的角度来看注册服务的过程,此篇以MediaPlayerService注册进入到servicemanager中为例子。

1.1 时序图

 (为了保证流程的完整性,较为模糊,可保存到本地,放大仔细观看)

1.1流程介绍

此处举例为MediaPlayerService注册进入到servicemanager中。

第一步:首先mediaservice会获取ProcessState实例对象,此ProcessState对象会打开binder驱动,驱动中会创建meidaservice服务对应的porc进程信息对象。同时meidaservice作为服务,会申请一块内存,通过mmap的进行内存映射,将meidaservice服务的用户空间映射到驱动中,从而会减少数据的拷贝。

第二步:获取BpServiceManager对象,即通过handle0获取ServiceManager的binder代理对象,用于和servicemanager对象通信。

第三步:初始化MediaPlayerService服务,内部首先会创建MediaPlayerService对象,此对象是一个BnMediaPlayerService(binder实体对象),然后调用BpServiceManager代理对象的addservice将此服务注册到中。

第四步:在BpServiceManager代理对象的addservice函数中,会构建Parcel对象,并将meidapalyservice服务的binder实体对象,服务名称,等信息写入Parcel对象中。然后调用bpbinder的通信接口transact函数。

第五步:然后transact函数会将数据再次进行封装,然后调用ioctl函数向驱动发送请求add服务的消息,此时进入内核态。

第六步:ioctl函数对应驱动的binder_ioctl函数,驱动会先将mediapalyservice服务的用户空间的数据拷贝到内核空间,并取出add的标志,处理add服务的消息。然后会走到binder_transaction中。

第七步:binder_transaction函数中首先会找到目标的进程的proc对象和目标进程的线程,然后取出meidapalyservice服务塞入Parcel对象中binder实体对象,并在驱动中创建meidapalyservice服务对应的bbbinder实体,并将此bbbinder实体添加到meidiaplayservice服务的比红黑树中,然后在目标进程(SM进程)的binder_proc中创建对应的binder_ref红黑树节点,将mediaservice的引用添加到SM进程的引用的红黑树中。然后在sm之前映射的进程中分配一块内核buffer空间,将add添加服务的消息数据放入sm进程的缓冲区中。然后将此add服务的消息添加到sm进程的todo队列中。然后唤醒目标进程(SM进程的队列)队列。同时也会生成一个完成的事务消息放入到meidaplayservice的进程队列中。

第八步:meidaplayservice服务作为客户端,会陷入休眠,等待服务端返回reply消息。

第九步:我们知道SM启动后,在向驱动成为binder的管理者后,就会循环从驱动中读取数据,由于驱动无数据,所以会陷入休眠状态等待在todo队列上。在第七步我们已经唤醒了sm进程。此时sm进程会从队列中读取到消息。然后处理add服务的消息。


第十步:sm将meidaplayservice服务的hanle和服务名称保存到svclist,完成注册。然后sm向驱动发送回复消息。同样也是通过binder_transaction函数去找到meidaplayservice服务的porc对象,并向meida服务的todo队列中插入回复消息,并唤醒mediaservice服务。并且往自己的队列中插入未完成事务。然后sm处理完后,再次陷入等待,等待来自驱动的消息。

第十一步:meidaplayservice服务处理reply消息。

第十二步:mediaplayservice服务创建一个新的线程加入binder线程池中,并向驱动发送要进入线程循环的指令,
然后此新线程进入死循环,用于读取来自驱动的消息,如果没有消息,则会休眠阻塞。

第十三步:mediaplayservice服务主线程也加入binder线程池中,也会进入死循环,用于读取来自驱动的消息,如果没有消息,则会休眠阻塞。用于不让主服务退出。


2 meidaservice的启动——源码分析

此例子以meidaservice注册到servcicemanager为例。

//此函数的作用是:驱动多媒体服务,并注册到serivcemanager中
int main(int argc __unused, char **argv __unused)
{
	signal(SIGPIPE, SIG_IGN);
 
    sp<ProcessState> proc(ProcessState::self());     //获得ProcessState实例对象
    sp<IServiceManager> sm(defaultServiceManager()); //获取BpServiceManager对象
    ALOGI("ServiceManager: %p", sm.get());
    AIcu_initializeIcuOrDie();
    MediaPlayerService::instantiate();   //注册多媒体服务
    ResourceManagerService::instantiate();
    registerExtensions();
    ProcessState::self()->startThreadPool();    //启动Binder线程池
    IPCThreadState::self()->joinThreadPool();   //当前线程加入到线程池

}

 注意:startThreadPool,本质上是创建了一个新的线程,并向binder驱动注册为主线程。然后一直循环。joinThreadPool是将当前线程加入到binder主线程。此时有两个binder主线程。

2.1 获取ProcessState对象

2.1.1 ProcessState::ProcessState

1.此处是单例模式。在一个进程中,只会创建一次。ProcessState作为进程状态的记录器,主要用来打开Binder驱动获取句柄,mmap申请一块(1M-8K)的内存空间,设置Binder线程最大个数。

sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        return gProcess;
    }
    gProcess = new ProcessState(kDefaultDriver);//sp<ProcessState> gProcess;
	//根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder"kDefaultDriver此时值是= "/dev/binder";
    return gProcess;
}

 2.1.2 ProcessState::init

1.创建了ProcessState对象。此对象用于打开binder驱动,并完成内存的映射,将用户空间的一块内存映射到内核空间,映射关系建立后,用户对这块内存区域的修改可直接反映到内核空间,反之内核空间对其修改也能反映到用户空间。

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))//driver是/dev/binder
    , mDriverFD(open_driver(driver))//打开binder驱动返回的fd文件描述符
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)//保护线程数量的锁,pthread_mutex_t mThreadCountLock;
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)//条件变量。pthread_cond_t mThreadCountDecrement;
    , mExecutingThreadsCount(0)//当前执行命令的binder线程数
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)//最大线程数15
    , mStarvationStartTimeMs(0)//线程池被清空的时间
    , mManagesContexts(false)
    , mBinderContextCheckFunc(nullptr)
    , mBinderContextUserData(nullptr)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)//无呼叫限制
{
    if (mDriverFD >= 0) {
		//mmap binder,内存映射。128k的内存地址,申请128k的内存地址用来接收事务,对应binder驱动的binder_mmap函数。
		//启动分析中有,故不再分析
        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();
        }
		*/
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

2.1.3 open_driver

主要作用为:

1.open打开binder驱动,通过系统调用_open,最后会调用到binder_open,陷入内核态。获取fd。

2.通过ioctl,获取binder驱动版本号,用vers保存。然后对比版本号是否一致。

3.通过ioctl设置binder驱动最大线程数。

static int open_driver(const char *driver)
{
    int fd = open(driver, O_RDWR | O_CLOEXEC);//driver值是/dev/binder,打开binder驱动,陷入内核,此
	//open对应_open,然后对应binder驱动层的binder_open,binder_open中主要是为/dev/binder这个驱动设备节点,创建
	//对应的proc对象,然后通过fd返回。这样就可以和驱动进行通信。
    if (fd >= 0) {//大于0代表打开成功
        int vers = 0;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);//获取binder驱动的版本信息,用vers保存
		/**正常不执行
        if (result == -1) {//如果获取信息失败,则关闭binder驱动
            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
		*/
		
		/**
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {//如果获取的版本信息不匹配,则关闭binder驱动
          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;
        }
		*/
		
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;//设置最大线程数15
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//设置binder驱动最大线程数
		
		/**
        if (result == -1) {
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
		*/
        uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;//DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION值是1,表示默认启用更新垃圾检测
        result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);//设置到binder驱动中
		/**
        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;
}

2.1.4 binder_open

1.为当前sm服务进程分配保存binder_proc的对象。binder_proc结构体保存的是sm服务的进程的信息。

2.对sm服务的binder_proc的对象进行初始化,如初始化todo队列,设置进程优先级等。

3.将sm服务的binder_proc添加到binder_procs队列中,驱动有一个全局的binder_procss的列表,用于存储所有进程的binder_proc对象。

//主要作用:binder驱动为用户进程创建了用户进程自己的binder——proc实体
static int binder_open(struct inode *nodp, struct file *filp)
{
	struct binder_proc *proc;//proc表示驱动中binder进程


	proc = kzalloc(sizeof(*proc), GFP_KERNEL);//为binder_proc结构体在分配kernel内存空间
	if (proc == NULL)
		return -ENOMEM;
	//下面是对binder_proc进行初始化,binder_proc用于管理数据的记录体
	get_task_struct(current);
	proc->tsk = current;//current代表当前线程。当前线程此时是servicemanager的主线程,当前线程的task保存在binder进程的tsk
	INIT_LIST_HEAD(&proc->todo);//初始化to列表
	init_waitqueue_head(&proc->wait);//初始化wait列表
	proc->default_priority = task_nice(current);//当前进程的nice值转化为进程优先级

	binder_lock(__func__);

	binder_stats_created(BINDER_STAT_PROC);//BINDER_PROC对象创建+1
	hlist_add_head(&proc->proc_node, &binder_procs);//将proc_node节点添加到binder_procs为表头的队列
	proc->pid = current->group_leader->pid;
	INIT_LIST_HEAD(&proc->delivered_death);
	filp->private_data = proc;//将 proc 保存到filp中,这样下次可以通过filp找到此proc

	binder_unlock(__func__);

	if (binder_debugfs_dir_entry_proc) {
		char strbuf[11];
		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
		proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
			binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
	}

	return 0;
}
//进程相关的参数
struct binder_proc {
	struct hlist_node proc_node;//hlist_node表示哈希表中的一个节点。哈希表中的一个节点,用于标记该进程
	struct rb_root threads;// rb_root表示红黑树。Binder线程池每一个Binder进程都有一个线程池,
	//由Binder驱动来维护,Binder线程池中所有线程由一个红黑树来组织,RB树以线程ID为关键字  */
        //上述红黑树的根节点
	struct rb_root nodes;// 一系列Binder实体对象(binder_node)和Binder引用对象(binder_ref) */
    //在用户空间:运行在Server端称为Binder本地对象,运行在Client端称为Binder代理对象*/
    //在内核空间:Binder实体对象用来描述Binder本地对象,Binder引用对象来描述Binder代理对象 */
    //Binder实体对象列表(RB树),关键字 ptr
	struct rb_root refs_by_desc;//记录binder引用, 便于快速查找,binder_ref红黑树的根节点(以handle为key),它是Client在Binder驱动中的体现。
	//Binder引用对象,关键字  desc
	struct rb_root refs_by_node;//记录binder引用, 便于快速查找,binder_ref红黑树的根节点(以ptr为key),它是Client在Binder驱动中的体现,
	//Binder引用对象,关键字  node
	struct list_head waiting_threads; 
	int pid;//进程组pid
	struct task_struct *tsk;//任务控制模块
	const struct cred *cred;
	struct hlist_node deferred_work_node;
	int deferred_work;
	bool is_dead;

	struct list_head todo;//待处理队列,进程每接收到一个通信请求,Binder将其封装成一个工作项,保存在待处理队列to_do中  */

	struct binder_stats stats;
	struct list_head delivered_death;
	int max_threads;// Binder驱动程序最多可以请求进程注册线程的最大数量,
	//进程可以调用ioctl注册线程到Binder驱动程序中,当线程池中没有足够空闲线程来处理事务时,Binder驱动可以主动要求进程注册更多的线程到Binder线程池中 */
    // Binder驱动程序最多可以请求进程注册线程的最大数量
	int requested_threads;
	int requested_threads_started;
	int tmp_ref;
	long default_priority;
	struct dentry *debugfs_entry;
	struct binder_alloc alloc;
	struct binder_context *context;//存储binder_node和binder_context_mgr_uid以及name
	spinlock_t inner_lock;
	spinlock_t outer_lock;
	struct dentry *binderfs_entry;
};

2.1.5 获取版本号binder_ioctl

主要作用为:

1.此时用于获取版本号。

//获取binder版本号分析
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;//binder线程
	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);//binder_stop_on_user_error值是0,
	//binder_stop_on_user_error < 2为假时,休眠,故此处不休眠
	if (ret)
		goto err_unlocked;

	binder_lock(__func__);
	thread = binder_get_thread(proc);//获取当前sm的proc实体对象的binder_thread
	if (thread == NULL) {
		ret = -ENOMEM;
		goto err;
	}

	switch (cmd) {
	case BINDER_VERSION://获取版本号
		if (size != sizeof(struct binder_version)) {
			ret = -EINVAL;
			goto err;
		}
		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
			//将驱动程序的BINDER_CURRENT_PROTOCOL_VERSION变量地址,拷贝sizeof(*ptr)的ubuf用户空间地址。
			//分析,此处是有一次拷贝的。
			ret = -EINVAL;
			goto err;
		}
		break;
	default:
		ret = -EINVAL;
		goto err;
	}
	ret = 0;
err:
	if (thread)
		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	binder_unlock(__func__);
	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);//不休眠
	if (ret && ret != -ERESTARTSYS)
		printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
	trace_binder_ioctl_done(ret);
	return ret;
}

2.1.6 设置binder最大线程数binder_ioctl

//设置binder最大线程数分析
//ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);maxThreads值为15
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;//binder线程
	unsigned int size = _IOC_SIZE(cmd);
	void __user *ubuf = (void __user *)arg;//ubuf是15的地址

	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);//获取当前sm的proc实体的binder_thread
	if (thread == NULL) {
		ret = -ENOMEM;
		goto err;
	}

	switch (cmd) {
	case BINDER_SET_MAX_THREADS://设置binder最大线程数量
		if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {//拷贝用户空间的地址到内核空间
			ret = -EINVAL;
			goto err;
		}
		break;
	ret = 0;
err:
	if (thread)
		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	binder_unlock(__func__);
	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
	if (ret && ret != -ERESTARTSYS)
		printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
	trace_binder_ioctl_done(ret);
	return ret;
}

2.1.7 binder_mmap

主要作用为:

1.get_vm_area分配一个连续的内核虚拟空间,与用户进程虚拟空间大小一致。

2.binder_update_page_range,分配物理页面,同时映射到内核空间和用户进程空间。

即,此时servermanager服务在其内部分配了一块地址映射进入了内核空间。减少了拷贝。

//filp对应fp,vma代表用户地址空间
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)//vma描述了应用程序使用的用户虚拟空间
{
	int ret;
	struct vm_struct *area;//内核虚拟空间
	struct binder_proc *proc = filp->private_data;//取出sm进程对应的binder_proc对象
	const char *failure_string;
	struct binder_buffer *buffer;//用于binder传输数据的缓冲区

	if ((vma->vm_end - vma->vm_start) > SZ_4M)//保证映射内存大小不超过4M
		vma->vm_end = vma->vm_start + SZ_4M;



	if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {//判断是否禁止mmap
		ret = -EPERM;
		failure_string = "bad vm_flags";
		goto err_bad_arg;
	}
	vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;

	mutex_lock(&binder_mmap_lock);
	if (proc->buffer) {//如果buffer不为空,则代表已经mmap过了
		ret = -EBUSY;
		failure_string = "already mapped";
		goto err_already_mapped;
	}

	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);//分配一个连续的内核虚拟空间,与用户进程虚拟空间大小一致
	if (area == NULL) {
		ret = -ENOMEM;
		failure_string = "get_vm_area";
		goto err_get_vm_area_failed;
	}
	proc->buffer = area->addr;//binder_proc对象的buffer指向内核虚拟空间的地址
	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;//计算偏移量,地址偏移量=用户空间地址-内核空间地址
	mutex_unlock(&binder_mmap_lock);

	proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);//分配
	//分配物理页的指针数组,大小等于用户虚拟内存/4K,此数组用于指示binder申请的物理页的状态
	if (proc->pages == NULL) {
		ret = -ENOMEM;
		failure_string = "alloc page array";
		goto err_alloc_pages_failed;
	}
	proc->buffer_size = vma->vm_end - vma->vm_start;//计算大小

	vma->vm_ops = &binder_vm_ops;
	vma->vm_private_data = proc;

	if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {//分配物理页面,同时映射到内核空间和进程空间,
	//目前只分配1个page的物理页
		ret = -ENOMEM;
		failure_string = "alloc small buf";
		goto err_alloc_small_buf_failed;
	}
	buffer = proc->buffer;//binder_buffer对象,指向proc的buffer地址,proc的buffer地址又指向内核虚拟空间的地址
	INIT_LIST_HEAD(&proc->buffers);
	list_add(&buffer->entry, &proc->buffers);//将内核虚拟空间的地址加入到所属进程的buffer队列
	buffer->free = 1;
	binder_insert_free_buffer(proc, buffer);//将空闲的buffer放入proc->free_buffer中
	proc->free_async_space = proc->buffer_size / 2;
	barrier();
	proc->files = get_files_struct(proc->tsk);
	proc->vma = vma;//binder_proc对象保存了用户空间的地址
	proc->vma_vm_mm = vma->vm_mm;

	/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
		 proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
	return 0;
////错误跳转
err_alloc_small_buf_failed:
	kfree(proc->pages);
	proc->pages = NULL;
err_alloc_pages_failed:
	mutex_lock(&binder_mmap_lock);
	vfree(proc->buffer);
	proc->buffer = NULL;
err_get_vm_area_failed:
err_already_mapped:
	mutex_unlock(&binder_mmap_lock);
err_bad_arg:
	printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
	       proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
	return ret;
}

2.1.8 binder_update_page_range

主要作用为:

1.分配物理内存空间。

2.将物理空间映射到内核空间。

3.将物理空间映射到用户进程空间。

当然binder_update_page_range 既可以分配物理页面,也可以释放物理页面。

//binder_update_page_range 主要完成工作:分配物理内存空间,将物理空间映射到内核空间,将物理空间映射到进程空间。
//当然binder_update_page_range 既可以分配物理页面,也可以释放物理页面
static int binder_update_page_range(struct binder_proc *proc, int allocate,
				    void *start, void *end,
				    struct vm_area_struct *vma)
					//参数说明:
					//proc对应的进程的proc对象
					//allocate表示是申请还是释放
					//start,表示内核虚拟空间起始地址
					//end,内核虚拟空间末尾地址
					//用户空间地址
{
	void *page_addr;
	unsigned long user_page_addr;
	struct vm_struct tmp_area;
	struct page **page;
	struct mm_struct *mm;


	if (end <= start)
		return 0;

	trace_binder_update_page_range(proc, allocate, start, end);

	if (vma)
		mm = NULL;
	else
		mm = get_task_mm(proc->tsk);

	if (mm) {
		down_write(&mm->mmap_sem);
		vma = proc->vma;
		if (vma && mm != proc->vma_vm_mm) {
			pr_err("binder: %d: vma mm and task mm mismatch\n",
				proc->pid);
			vma = NULL;
		}
	}

	if (allocate == 0)
		goto free_range;

	if (vma == NULL) {
		printk(KERN_ERR "binder: %d: binder_alloc_buf failed to "
		       "map pages in userspace, no vma\n", proc->pid);
		goto err_no_vma;
	}
	//前面都在判断参数是否合法
	//
	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
		int ret;
		struct page **page_array_ptr;
		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];

		BUG_ON(*page);
		//分配物理内存
		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
		if (*page == NULL) {
			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
			       "for page at %p\n", proc->pid, page_addr);
			goto err_alloc_page_failed;
		}
		tmp_area.addr = page_addr;//tmp_area是内核地址,此时指向物理地址
		tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
		page_array_ptr = page;
		ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);//映射物理页地址到内核地址tmp_area
		if (ret) {
			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
			       "to map page at %p in kernel\n",
			       proc->pid, page_addr);
			goto err_map_kernel_failed;
		}
		user_page_addr =
			(uintptr_t)page_addr + proc->user_buffer_offset;
		ret = vm_insert_page(vma, user_page_addr, page[0]);//映射物理页地址到虚拟用户地址空间vma
		if (ret) {
			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
			       "to map page at %lx in userspace\n",
			       proc->pid, user_page_addr);
			goto err_vm_insert_page_failed;
		}
		/* vm_insert_page does not seem to increment the refcount */
	}
	if (mm) {
		up_write(&mm->mmap_sem);
		mmput(mm);
	}
	return 0;

free_range:
	for (page_addr = end - PAGE_SIZE; page_addr >= start;
	     page_addr -= PAGE_SIZE) {
		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
		if (vma)
			zap_page_range(vma, (uintptr_t)page_addr +
				proc->user_buffer_offset, PAGE_SIZE, NULL);
err_vm_insert_page_failed:
		unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
err_map_kernel_failed:
		__free_page(*page);
		*page = NULL;
err_alloc_page_failed:
		;
	}
err_no_vma:
	if (mm) {
		up_write(&mm->mmap_sem);
		mmput(mm);
	}
	return -ENOMEM;
}

 2.2 获取bpServiceManager对象

2.2.1 defaultServiceManager

1.此处最重要的是gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(nullptr));

因此我们需要查看getContextObject和interface_cast的作用。

可以提前说一下,最终sm是bpServiceManager对象。我们看一下是如何分析的。

sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;

    {
        AutoMutex _l(gDefaultServiceManagerLock);
		
        while (gDefaultServiceManager == nullptr) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(nullptr));
            if (gDefaultServiceManager == nullptr)
                sleep(1);//当ServiceManager还未准备好,等待1秒后重新获取ServiceManager对象
        }
    }

    return gDefaultServiceManager;//gDefaultServiceManager是一个bpServiceManager
}

2.2.2 ProcessState::getContextObject

1.最终获取了servicemanager的句柄对应的BpBinder对象。

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);//0就是servicemanager的句柄
}

2.2.3 ProcessState::getStrongProxyForHandle

1.创建了一个handle为0的BpBinder,即SM的bpbinder

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)//传入的是0,代表serviceManager的句柄
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);//查找SM的handle对应的资源项。

    if (e != nullptr) {
        IBinder* b = e->binder;//此时b为空
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
				//执行一个伪事务以确保上下文管理器已注册。通过ping操作测试binder是否准备就绪
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }

            b = BpBinder::create(handle);//创建了一个handle为0的BpBinder,即SM的bpbinder
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;//返回一个handle为0的BpBinder
}

2.2.4 ProcessState::lookupHandleLocked

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)//此时值是0,0代表sm的binder代理对象的句柄
{
    const size_t N=mHandleToObject.size();//第一次N=0
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = nullptr;
        e.refs = nullptr;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);//mHandleToObject是保存handle_entry的容器
        if (err < NO_ERROR) return nullptr;
    }
    return &mHandleToObject.editItemAt(handle);//返回了一个空的handle_entry
}

2.2.5 BpBinder::create

1.创建了SM对应的BpBinder对象。

BpBinder* BpBinder::create(int32_t handle) {
    int32_t trackedUid = -1;
	//sCountByUidEnabled默认是false
	/**
    if (sCountByUidEnabled) {
        trackedUid = IPCThreadState::self()->getCallingUid();
        AutoMutex _l(sTrackingLock);
        uint32_t trackedValue = sTrackingMap[trackedUid];
        if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {
            if (sBinderProxyThrottleCreate) {
                return nullptr;
            }
        } else {
            if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
                ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
                      getuid(), trackedUid, trackedValue);
                sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
                if (sLimitCallback) sLimitCallback(trackedUid);
                if (sBinderProxyThrottleCreate) {
                    ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"
                          " count drops below %d",
                          trackedUid, getuid(), sBinderProxyCountLowWatermark);
                    return nullptr;
                }
            }
        }
        sTrackingMap[trackedUid]++;
    }
	*/
    return new BpBinder(handle, trackedUid);//创建了BpBinder对象
}

2.2.6 BpBinder::BpBinder

BpBinder::BpBinder(int32_t handle, int32_t trackedUid)//此时handle=0,trackedUid是-1
    : mHandle(handle)//是0,代表SM的Bpbinder的句柄
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(nullptr)
    , mTrackedUid(trackedUid)
{
    ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);

    extendObjectLifetime(OBJECT_LIFETIME_WEAK);//扩展生命周期为弱引用管理
    IPCThreadState::self()->incWeakHandle(handle, this);//增加BPbinder的弱引用计数
}

2.2.7 IPCThreadState::self

IPCThreadState* IPCThreadState::self()
{
	/**不执行
    if (gHaveTLS.load(std::memory_order_acquire)) {//定义时是false。static std::atomic<bool> gHaveTLS(false);
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }


	
    // Racey, heuristic test for simultaneous shutdown.
    if (gShutdown.load(std::memory_order_relaxed)) {//定义是false。static std::atomic<bool> gShutdown = false;
        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
        return nullptr;
    }
	*/

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS.load(std::memory_order_relaxed)) {
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);//分配用于表示进程中线程特定数据的键,键对进程中的所有线程来说是全局的.
		//pthread_key_create第一个参数为指向一个键值的指针,第二个参数指明了一个destructor函数,
		//如果这个参数不为空,那么当每个线程结束时,系统将调用这个函数来释放绑定在这个键上的内存块。
		//key_create_value成功返回0,其他是失败
		/**
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                    strerror(key_create_value));
            return nullptr;
        }
		*/
        gHaveTLS.store(true, std::memory_order_release);//将gHaveTLS值设置为true。static std::atomic<bool> gHaveTLS(false);
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

2.2.8 IPCThreadState::IPCThreadState

IPCThreadState::IPCThreadState()
      : mProcess(ProcessState::self()),//保存当前的ProcessState对象
        mServingStackPointer(nullptr),
        mWorkSource(kUnsetWorkSource),
        mPropagateWorkSource(false),
        mIsLooper(false),
        mIsFlushing(false),
        mStrictModePolicy(0),
        mLastTransactionBinderFlags(0),
        mCallRestriction(mProcess->mCallRestriction) {
    pthread_setspecific(gTLS, this);//将自己即IPCThreadState对象存储到gTLS中。
    clearCaller();
    mIn.setDataCapacity(256);//设置输入缓存区大小
    mOut.setDataCapacity(256);//设置输出缓存区大小
}

2.2.9 IPCThreadState::incWeakHandle

void IPCThreadState::incWeakHandle(int32_t handle, BpBinder *proxy)
{
    LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
    mOut.writeInt32(BC_INCREFS);//向驱动请求增加binder的引用计数
    mOut.writeInt32(handle);//此时是0,代表SM的句柄
	if (!flushIfNeeded()) {//flushIfNeeded返回值是false,因为当前线程还没有进入循环,故无法贺binder驱动通信。
    // Create a temp reference until the driver has handled this command.
    proxy->getWeakRefs()->incWeak(mProcess.get());
    mPostWriteWeakDerefs.push(proxy->getWeakRefs());
	}
}

所以gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(nullptr));

就变成了
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0,trackedUid));

我们接下来继续查看interface_cast的作用。

2.2.10 interface_cast

这个是一个模板类。

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

 此时INTERFACE的值是IServiceManager,转换后为:

inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
    return IServiceManager::asInterface(obj);//此时obj是BpBinder(0,trackedUid)
	//真正返回的是BpServiceManager(BpBinder(0,trackedUid)) 对象
}

继续查看asInterface的作用。

2.2.11 asInterface

#define DO_NOT_DIRECTLY_USE_ME_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 != nullptr) {                                           \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == nullptr) {                                      \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }

替换后为:

#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")                       
    const ::android::String16 IServiceManager::descriptor("android.os.IServiceManager");    
	
    ::android::sp<IServiceManager> IServiceManager::asInterface(              
            const ::android::sp<::android::IBinder>& obj)               
    {                                                                   
        ::android::sp<IServiceManager> intr;                               
        if (obj != nullptr) {//此时obj是BpBinder(0,trackedUid)                                    
            intr = static_cast<IServiceManager*>(                          
                obj->queryLocalInterface(IServiceManager::descriptor).get());//查询"android.os.IServiceManager"对应的本地服务      
            if (intr == nullptr) {                                      
                intr = new BpServiceManager(obj);                          
            }                                                           
        }                                                               
        return intr; //返回的是BpServiceManager(BpBinder(0,trackedUid))     		
    }

2.2.12 queryLocalInterface

//此时obj是BpBinder对象,查看其queryLocalInterface方法。
sp<IInterface>  IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
    return nullptr;//返回为空
}

所以此时

gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(nullptr));

就变成了
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0,trackedUid));

等价于
gDefaultServiceManager =new BpServiceManager(new BpBinder(0,trackedUid));

2.2.13 BpServiceManager::BpServiceManager

explicit BpServiceManager(const sp<IBinder>& impl)//此时impl是BpBinder(0,trackedUid)
        : BpInterface<IServiceManager>(impl)
{
}

2.2.14 BpInterface::BpInterface

class BpInterface : public INTERFACE, public BpRefBase
inline BpInterface<IServiceManager>::BpInterface(const sp<IBinder>& remote)//remote是BpBinder(0,trackedUid)
    : BpRefBase(remote)
{
}



替换后,等价于
class BpInterface : public IServiceManager, public BpRefBase
inline BpInterface<IServiceManager>::BpInterface(const sp<IBinder>& remote)//remote是BpBinder(0,trackedUid)
    : BpRefBase(remote)
{
}

2.2.15 BpRefBase::BpRefBase

BpRefBase::BpRefBase(const sp<IBinder>& o)//o是BpBinder(0,trackedUid)
    : mRemote(o.get()), mRefs(nullptr), mState(0)//mRemote就是BpBinder(0,trackedUid)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);//扩展对象生命周期为弱周期管理

    if (mRemote) {
        mRemote->incStrong(this);           //增加对象引用计数
        mRefs = mRemote->createWeak(this);  //持有一个mRemote的弱引用对象
    }
}

2.3 注册多媒体服务到servicemanager

2.3.1 MediaPlayerService::instantiate

主要作用为:

1.MediaPlayerService调用Bpservicemanager对象的addService接口。

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());//BpServiceManager的addService方法
}

2.3.2 IServiceManager::addService

1.生成发送到驱动的数据data和请求恢复的reply。

2.将MediaPlayerService这个binder实体对象,对应的string名称,写入data。

3.通过bpbinder的transact接口将消息发送出去,并等待回复的消息。

[/frameworks/native/libs/binder/IServiceManager.cpp]
virtual status_t addService(const String16& name, const sp<IBinder>& service,
                                bool allowIsolated, int dumpsysPriority) {
		//参数:name是"media.player",service是new MediaPlayerService,也是一个BBbinder实体
		//allowIsolated是fasle,dumpsysPriority是8,默认优先级
        Parcel data, reply;//发送到驱动的data,和请求回复的reply
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//写入RPC头信息"android.os.IServiceManager"
        data.writeString16(name);//写入"media.player"
        data.writeStrongBinder(service);//把一个binder实体“打扁”并写入parcel, 服务的实体对象:new MediaPlayerService
        data.writeInt32(allowIsolated ? 1 : 0);//写入0
        data.writeInt32(dumpsysPriority);//写入8
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);//remote() 函数{ return mRemote; }
		//故mRemote是SM对应的BpBinder(0,-1)的transact方法。ADD_SERVICE_TRANSACTION是3
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }
status_t Parcel::writeInterfaceToken(const String16& interface)
{
    const IPCThreadState* threadState = IPCThreadState::self();//获取IPCThreadState对象
    writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
    updateWorkSourceRequestHeaderPosition();
    writeInt32(threadState->shouldPropagateWorkSource() ?
            threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
    // currently the interface identification token is just its name as a string
    return writeString16(interface);//interface是"android.os.IServiceManager"
}

 2.3.3 writeStrongBinder

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);//ProcessState是进程状态,val是new MediaPlayerService,BBinder实体。
	//this是Parcel对象data
}

2.3.4  flatten_binder

1.parcel对象内部会有一个buffer,记录着parcel中所有扁平化的数据,有些扁平数据是普通数据,而另一些扁平数据则记录着binder对象。所以parcel中会构造另一个mObjects数组,专门记录那些binder扁平数据所在的位置,

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;

    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
        /* minimum priority for all nodes is nice 0 */
        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
    } else {
        /* minimum priority for all nodes is MAX_NICE(19) */
        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    }

    if (binder != nullptr) {
        BBinder *local = binder->localBinder();//如果是BBinder则返回BBinder,如果是Bpbinder则返回空
		/**
        if (!local) {//如果是bpbinder,代理
            BpBinder *proxy = binder->remoteBinder();//返回Bpbinder
            if (proxy == nullptr) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;//记录此Binder代理的句柄
            obj.hdr.type = BINDER_TYPE_HANDLE;//设置type为binder句柄
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process 
            obj.handle = handle;//将此binder代理的句柄,放入flat_binder_object中。
            obj.cookie = 0;
        }
		*/
		else {//是binder实体
            if (local->isRequestingSid()) {
                obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;//安全上下文
            }
            obj.hdr.type = BINDER_TYPE_BINDER;//设置type为binder实体
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());//存储BBbinder
            obj.cookie = reinterpret_cast<uintptr_t>(local);//cookie记录Binder实体的指针
        }
    }
	/**
	else {
        obj.hdr.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }
	*/

    return finish_flatten_binder(binder, obj, out);//参数binder是new MediaPlayerService的BBbinder实体,obj是扁平的flat_binder_object,out是Parcel对象。
	//finish_flatten_binder()函数。这个函数内部会记录下刚刚被扁平化的flat_binder_object在parcel中的位置。
	//说得更详细点儿就是,parcel对象内部会有一个buffer,记录着parcel中所有扁平化的数据,
	//有些扁平数据是普通数据,而另一些扁平数据则记录着binder对象。
	//所以parcel中会构造另一个mObjects数组,专门记录那些binder扁平数据所在的位置,
}
BBinder* BBinder::localBinder()//如果是BBinder则返回BBinder,
{
    return this;
}

BBinder* IBinder::localBinder()//如果是Bpbinder则返回空
{
    return nullptr;
}

BpBinder* BpBinder::remoteBinder()//返回Bpbinder
{
    return this;
}

2.3.5 BpBinder::transact

//transact(ADD_SERVICE_TRANSACTION, data, &reply);
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
	//参数分析:
	//code是3,也是ADD_SERVICE_TRANSACTION
	//data中包含要注册的media服务的名字和media服务的BBinder实体。
	//reply为空
	//flag是0
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {//291行,BpBinder构造函数中是1,表示是否活着
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
			//mHandle是0,代表SMBPbinder的句柄,
			//code是code是3,也是ADD_SERVICE_TRANSACTION
			//data是data中包含要注册的media服务的名字和media服务的BBinder实体。
			//reply为空
			//flag是0
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

2.3.6 IPCThreadState::transact

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
								//mHandle是0,代表SMBPbinder的句柄,
								//code是code是3,也是ADD_SERVICE_TRANSACTION
								//data是data中包含要注册的media服务的名字和media服务的BBinder实体。
								//reply为空
								//flag是0
{
    status_t err;

    flags |= TF_ACCEPT_FDS;//TF_ACCEPT_FDS表示允许使用文件描述符进行答复


    LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
        (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");//是否异步回复,此处应该是阻塞的
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);//将消息打包成结构体写入mout中
	/**
    if (err != NO_ERROR) {//如果出错
        if (reply) reply->setError(err);
        return (mLastError = err);
    }
	*/

    if ((flags & TF_ONE_WAY) == 0) {//如果是同步的。
        if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
            if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
                ALOGE("Process making non-oneway call but is restricted.");
                CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
                    ANDROID_LOG_ERROR);
            } else /* FATAL_IF_NOT_ONEWAY */ {
                LOG_ALWAYS_FATAL("Process may not make oneway calls.");
            }
        }

        if (reply) {//reply存在,则waitForResponse
            err = waitForResponse(reply);
        } else {//如果reply不存在,则构造一个出来
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }

    } else {
        err = waitForResponse(nullptr, nullptr);
    }

    return err;
}

2.3.7 IPCThreadState::writeTransactionData

1.再对数据封装填充到binder_transaction_data结构体中。

2.将要发送给驱动的数据写入mout中。

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
	//参数分析:
	//cmd是BC_TRANSACTION,代表请求运输
	//binderFlags是允许使用文件描述符进行答复,值是0X10
	//mHandle是0,代表SM 的BPbinder的句柄,
	//code是code是3,也是ADD_SERVICE_TRANSACTION
	//data是data中包含要注册的media服务的名字和media服务的BBinder实体。
	//statusBuffer是空
{
    binder_transaction_data tr;//此结构体可查看驱动结构体全代码分析

    tr.target.ptr = 0; //不用ptr,因为此时要发送的是SM服务的handle句柄
    tr.target.handle = handle;//SM服务的handle句柄0
    tr.code = code;//code是3,也是ADD_SERVICE_TRANSACTION
    tr.flags = binderFlags;//允许使用文件描述符进行答复,值是0X10
    tr.cookie = 0;//实体的cookie才有用
    tr.sender_pid = 0;//发送方pid
    tr.sender_euid = 0;//发送方uid

    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);//ipcObjectsCount函数返回的是mObjectsSize,而mObjects
		//存储的是多个扁平的binder对象的位置。是offsets_size的偏移大小
        tr.data.ptr.offsets = data.ipcObjects();//指向mObjects数组的首地址。mObjects里面记录了所有binder实体或引用在buffer中的位置。
    }
	/**
	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中写入BC_TRANSACTION,注意309行,此时还有一个BC_INCREFS的命令
    mOut.write(&tr, sizeof(tr));//写入tr结构体

    return NO_ERROR;
}

2.3.8 IPCThreadState::waitForResponse向驱动发送请求add服务的消息

//第一次循环时,向驱动发送请求add服务的消息,mout中有值
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)//acquireResult默认是nullptr
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;//第一次循环时,向驱动发送请求add消息,mout中有值
		
		//后面则是对reply回复消息的处理
        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;

        case BR_FAILED_REPLY:
            err = FAILED_TRANSACTION;
            goto finish;

        case BR_ACQUIRE_RESULT:
            {
                ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
                const int32_t result = mIn.readInt32();
                if (!acquireResult) continue;
                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
            }
            goto finish;

        case BR_REPLY:
            {
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr));
                ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
                if (err != NO_ERROR) goto finish;

                if (reply) {
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        reply->ipcSetDataReference(
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(binder_size_t),
                            freeBuffer, this);
                    } else {
                        err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
                        freeBuffer(nullptr,
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(binder_size_t), this);
                    }
                } else {
                    freeBuffer(nullptr,
                        reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                        tr.data_size,
                        reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                        tr.offsets_size/sizeof(binder_size_t), this);
                    continue;
                }
            }
            goto finish;

        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

finish:
    if (err != NO_ERROR) {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
    }

    return err;
}

2.3.9 IPCThreadState::talkWithDriver

status_t IPCThreadState::talkWithDriver(bool doReceive)//doReceive默认是true
{
	/**
    if (mProcess->mDriverFD < 0) {
        return -EBADF;
    }
	*/

    binder_write_read bwr;
	//struct binder_write_read {
	//binder_size_t		write_size;//要写入的字节数,write_buffer的总字节数
	//binder_size_t		write_consumed;//驱动程序占用的字节数,write_buffer已消费的字节数
	//binder_uintptr_t	write_buffer;//写缓冲数据的指针
	//binder_size_t		read_size;//要读的字节数,read_buffer的总字节数
	//binder_size_t		read_consumed;//驱动程序占用的字节数,read_buffer已消费的字节数
	//binder_uintptr_t	read_buffer;//读缓存数据的指针
	//};

    // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();//此时needRead是ture
	//因为mIn.dataPosition返回值和mIn.dataSize相等


	//当我们正在从min中读取数据,或者调用方打算读取下一条数据(doReceive为true时),我们不会写入任何内容。
	//此时outAvail值等于mOut.dataSize()
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    bwr.write_size = outAvail;//write_size是mOut.dataSize()
    bwr.write_buffer = (uintptr_t)mOut.data();

	
    if (doReceive && needRead) {//当我们需要从驱动中读的时候。
        bwr.read_size = mIn.dataCapacity();//设置大小为256字节
        bwr.read_buffer = (uintptr_t)mIn.data();
    }
	/*
	else {//当不读的时候,设置读的大小和buffer为0
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }*/
	

    // 如果读缓冲区和写缓冲区都为0,代表无事可做,立即返回,此时write_size中有数据。
	/**
    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 defined(__ANDROID__)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//向binder驱动区写,因为此时是add服务,所以mout有数据
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
		/**
        if (mProcess->mDriverFD < 0) {
            err = -EBADF;
        }
		*/
    } while (err == -EINTR);


    if (err >= NO_ERROR) {//代表驱动收到了消息
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())//如果驱动消费的数据大小小于mout的大小,则说明驱动没有消费mout数据
                LOG_ALWAYS_FATAL("Driver did not consume write buffer. "
                                 "err: %s consumed: %zu of %zu",
                            
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值