在上一篇文章中,我们分析了Android系统进程间通信机制Binder中的Server在启动过程使用Service Manager的addService接口把自己添加到Service Manager守护过程中接受管理。在这一篇文章中,我们将深入到Binder驱动程序源代码去分析Client是如何通过Service Manager的getService接口中来获得Server远程接口的。Client只有获得了Server的远程接口之后,才能进一步调用Server提供的服务。
这里,我们仍然是通过Android系统中自带的多媒体播放器为例子来说明Client是如何通过IServiceManager::getService接口来获得MediaPlayerService这个Server的远程接口的。假设计读者已经阅读过前面三篇文章浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路、浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路和Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析,即假设Service Manager和MediaPlayerService已经启动完毕,Service Manager现在等待Client的请求。
这里,我们要举例子说明的Client便是MediaPlayer了,它声明和实现在frameworks/base/include/media/mediaplayer.h和frameworks/base/media/libmedia/mediaplayer.cpp文件中。MediaPlayer继承于IMediaDeathNotifier类,这个类声明和实现在frameworks/base/include/media/IMediaDeathNotifier.h和frameworks/base/media/libmedia//IMediaDeathNotifier.cpp文件中,里面有一个静态成员函数getMeidaPlayerService,它通过IServiceManager::getService接口来获得MediaPlayerService的远程接口。
在介绍IMediaDeathNotifier::getMeidaPlayerService函数之前,我们先了解一下这个函数的目标。看来前面浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路这篇文章的读者知道,我们在获取Service Manager远程接口时,最终是获得了一个BpServiceManager对象的IServiceManager接口。类似地,我们要获得MediaPlayerService的远程接口,实际上就是要获得一个称为BpMediaPlayerService对象的IMediaPlayerService接口。现在,我们就先来看一下BpMediaPlayerService的类图:
从这个类图可以看到,BpMediaPlayerService继承于BpInterface<IMediaPlayerService>类,即BpMediaPlayerService继承了IMediaPlayerService类和BpRefBase类,这两个类又分别继续了RefBase类。BpRefBase类有一个成员变量mRemote,它的类型为IBinder,实际是一个BpBinder对象。BpBinder类使用了IPCThreadState类来与Binder驱动程序进行交互,而IPCThreadState类有一个成员变量mProcess,它的类型为ProcessState,IPCThreadState类借助ProcessState类来打开Binder设备文件/dev/binder,因此,它可以和Binder驱动程序进行交互。
BpMediaPlayerService的构造函数有一个参数impl,它的类型为const sp<IBinder>&,从上面的描述中,这个实际上就是一个BpBinder对象。这样,要创建一个BpMediaPlayerService对象,首先就要有一个BpBinder对象。再来看BpBinder类的构造函数,它有一个参数handle,类型为int32_t,这个参数的意义就是请求MediaPlayerService这个远程接口的进程对MediaPlayerService这个Binder实体的引用了。因此,获取MediaPlayerService这个远程接口的本质问题就变为从Service Manager中获得MediaPlayerService的一个句柄了。
现在,我们就来看一下IMediaDeathNotifier::getMeidaPlayerService的实现:
- // establish binder interface to MediaPlayerService
- /*static*/const sp<IMediaPlayerService>&
- IMediaDeathNotifier::getMediaPlayerService()
- {
- LOGV("getMediaPlayerService");
- Mutex::Autolock _l(sServiceLock);
- if (sMediaPlayerService.get() == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("media.player"));
- if (binder != 0) {
- break;
- }
- LOGW("Media player service not published, waiting...");
- usleep(500000); // 0.5 s
- } while(true);
- if (sDeathNotifier == NULL) {
- sDeathNotifier = new DeathNotifier();
- }
- binder->linkToDeath(sDeathNotifier);
- sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
- }
- LOGE_IF(sMediaPlayerService == 0, "no media player service!?");
- return sMediaPlayerService;
- }
函数首先通过defaultServiceManager函数来获得Service Manager的远程接口,实际上就是获得BpServiceManager的IServiceManager接口,具体可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文。总的来说,这里的语句:
- sp<IServiceManager> sm = defaultServiceManager();
相当于是:
- sp<IServiceManager> sm = new BpServiceManager(new BpBinder(0));
这里的0表示Service Manager的远程接口的句柄值是0。
接下去的while循环是通过sm->getService接口来不断尝试获得名称为“media.player”的Service,即MediaPlayerService。为什么要通过这无穷循环来得MediaPlayerService呢?因为这时候MediaPlayerService可能还没有启动起来,所以这里如果发现取回来的binder接口为NULL,就睡眠0.5秒,然后再尝试获取,这是获取Service接口的标准做法。
我们来看一下BpServiceManager::getService的实现:
- class BpServiceManager : public BpInterface<IServiceManager>
- {
- ......
- virtual sp<IBinder> getService(const String16& name) const
- {
- unsigned n;
- for (n = 0; n < 5; n++){
- sp<IBinder> svc = checkService(name);
- if (svc != NULL) return svc;
- LOGI("Waiting for service %s...\n", String8(name).string());
- sleep(1);
- }
- return NULL;
- }
- virtual sp<IBinder> checkService( const String16& name) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
- data.writeString16(name);
- remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
- return reply.readStrongBinder();
- }
- ......
- };
BpServiceManager::getService通过BpServiceManager::checkService执行操作。
在BpServiceManager::checkService中,首先是通过Parcel::writeInterfaceToken往data写入一个RPC头,这个我们在Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文已经介绍过了,就是写往data里面写入了一个整数和一个字符串“android.os.IServiceManager”, Service Manager来处理CHECK_SERVICE_TRANSACTION请求之前,会先验证一下这个RPC头,看看是否正确。接着再往data写入一个字符串name,这里就是“media.player”了。回忆一下Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析这篇文章,那里已经往Service Manager中注册了一个名字为“media.player”的MediaPlayerService。
这里的remote()返回的是一个BpBinder,具体可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文,于是,就进行到BpBinder::transact函数了:
- status_t BpBinder::transact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- // Once a binder has died, it will never come back to life.
- if (mAlive) {
- status_t status = IPCThreadState::self()->transact(
- mHandle, code, data, reply, flags);
- if (status == DEAD_OBJECT) mAlive = 0;
- return status;
- }
- return DEAD_OBJECT;
- }
这里的mHandle = 0,code = CHECK_SERVICE_TRANSACTION,flags = 0。
这里再进入到IPCThread::transact函数中:
- status_t IPCThreadState::transact(int32_t handle,
- uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags)
- {
- status_t err = data.errorCheck();
- flags |= TF_ACCEPT_FDS;
- IF_LOG_TRANSACTIONS() {
- TextOutput::Bundle _b(alog);
- alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
- << handle << " / code " << TypeCode(code) << ": "
- << indent << data << dedent << endl;
- }
- if (err == NO_ERROR) {
- 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, NULL);
- }
- if (err != NO_ERROR) {
- if (reply) reply->setError(err);
- return (mLastError = err);
- }
- if ((flags & TF_ONE_WAY) == 0) {
- #if 0
- if (code == 4) { // relayout
- LOGI(">>>>>> CALLING transaction 4");
- } else {
- LOGI(">>>>>> CALLING transaction %d", code);
- }
- #endif
- if (reply) {
- err = waitForResponse(reply);
- } else {
- Parcel fakeReply;
- err = waitForResponse(&fakeReply);
- }
- #if 0
- if (code == 4) { // relayout
- LOGI("<<<<<< RETURNING transaction 4");
- } else {
- LOGI("<<<<<< RETURNING transaction %d", code);
- }
- #endif
- IF_LOG_TRANSACTIONS() {
- TextOutput::Bundle _b(alog);
- alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
- << handle << ": ";
- if (reply) alog << indent << *reply << dedent << endl;
- else alog << "(none requested)" << endl;
- }
- } else {
- err = waitForResponse(NULL, NULL);
- }
- return err;
- }
首先是调用函数writeTransactionData写入将要传输的数据到IPCThreadState的成员变量mOut中去:
- status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
- int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
- {
- binder_transaction_data tr;
- tr.target.handle = handle;
- tr.code = code;
- tr.flags = binderFlags;
- 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(size_t);
- tr.data.ptr.offsets = data.ipcObjects();
- } else if (statusBuffer) {
- tr.flags |= TF_STATUS_CODE;
- *statusBuffer = err;
- tr.data_size = sizeof(status_t);
- tr.data.ptr.buffer = statusBuffer;
- tr.offsets_size = 0;
- tr.data.ptr.offsets = NULL;
- } else {
- return (mLastError = err);
- }
- mOut.writeInt32(cmd);
- mOut.write(&tr, sizeof(tr));
- return NO_ERROR;
- }
结构体binder_transaction_data在上一篇文章Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析已经介绍过,这里不再累述,这个结构体是用来描述要传输的参数的内容的。这里着重描述一下将要传输的参数tr里面的内容,handle = 0,code = CHECK_SERVICE_TRANSACTION,cmd = BC_TRANSACTION,data里面的数据分别为:
- writeInt32(IPCThreadState::self()->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
- writeString16("android.os.IServiceManager");
- writeString16("media.player");
这是在BpServiceManager::checkService函数里面写进去的,其中前两个是RPC头,Service Manager在收到这个请求时会验证这两个参数是否正确,这点前面也提到了。IPCThread->getStrictModePolicy默认返回0,STRICT_MODE_PENALTY_GATHER定义为:
- // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
- #define STRICT_MODE_PENALTY_GATHER 0x100
我们不关心这个参数的含义,这不会影响我们分析下面的源代码,有兴趣的读者可以研究一下。这里要注意的是,要传输的参数不包含有Binder对象,因此tr.offsets_size = 0。要传输的参数最后写入到IPCThreadState的成员变量mOut中,包括cmd和tr两个数据。
回到IPCThread::transact函数中,由于(flags & TF_ONE_WAY) == 0为true,即这是一个同步请求,并且reply != NULL,最终调用:
- err = waitForResponse(reply);
进入到waitForResponse函数中:
- status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
- {
- int32_t cmd;
- int32_t err;
- while (1) {
- if ((err=talkWithDriver()) < NO_ERROR) break;
- err = mIn.errorCheck();
- if (err < NO_ERROR) break;
- if (mIn.dataAvail() == 0) continue;
- cmd = 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:
- {
- LOG_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));
- LOG_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 size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(size_t),
- freeBuffer, this);
- } else {
- err = *static_cast<const status_t*>(tr.data.ptr.buffer);
- freeBuffer(NULL,
- reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
- tr.data_size,
- reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(size_t), this);
- }
- } else {
- freeBuffer(NULL,
- reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
- tr.data_size,
- reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(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;
- }
这个函数通过IPCThreadState::talkWithDriver与驱动程序进行交互:
- status_t IPCThreadState::talkWithDriver(bool doReceive)
- {
- LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
- binder_write_read bwr;
- // Is the read buffer empty?
- const bool needRead = mIn.dataPosition() >= mIn.dataSize();
- // We don't want to write anything if we are still reading
- // from data left in the input buffer and the caller
- // has requested to read the next data.
- const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
- bwr.write_size = outAvail;
- bwr.write_buffer = (long unsigned int)mOut.data();
- // This is what we'll read.
- if (doReceive && needRead) {
- bwr.read_size = mIn.dataCapacity();
- bwr.read_buffer = (long unsigned int)mIn.data();
- } else {
- bwr.read_size = 0;
- }
- ......
- // Return immediately if there is nothing to do.
- 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(HAVE_ANDROID_OS)
- if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
- err = NO_ERROR;
- else
- err = -errno;
- #else
- err = INVALID_OPERATION;
- #endif
- ......
- } while (err == -EINTR);
- ......
- if (err >= NO_ERROR) {
- if (bwr.write_consumed > 0) {
- if (bwr.write_consumed < (ssize_t)mOut.dataSize())
- mOut.remove(0, bwr.write_consumed);
- else
- mOut.setDataSize(0);
- }
- if (bwr.read_consumed > 0) {
- mIn.setDataSize(bwr.read_consumed);
- mIn.setDataPosition(0);
- }
- ......
- return NO_ERROR;
- }
- return err;
- }
这里的needRead为true,因此,bwr.read_size大于0;outAvail也大于0,因此,bwr.write_size也大于0。函数最后通过:
- ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
进入到Binder驱动程序的binder_ioctl函数中。注意,这里的mProcess->mDriverFD是在我们前面调用defaultServiceManager函数获得Service Manager远程接口时,打开的设备文件/dev/binder的文件描述符,mProcess是IPCSThreadState的成员变量。
Binder驱动程序的binder_ioctl函数中,我们只关注BINDER_WRITE_READ命令相关的逻辑:
- 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;
- /*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
- ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
- if (ret)
- return ret;
- mutex_lock(&binder_lock);
- thread = binder_get_thread(proc);
- if (thread == NULL) {
- ret = -ENOMEM;
- goto err;
- }
- switch (cmd) {
- case BINDER_WRITE_READ: {
- struct binder_write_read bwr;
- if (size != sizeof(struct binder_write_read)) {
- ret = -EINVAL;
- goto err;
- }
- if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
- ret = -EFAULT;
- goto err;
- }
- if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)
- printk(KERN_INFO "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
- proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer);
- if (bwr.write_size > 0) {
- ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
- if (ret < 0) {
- bwr.read_consumed = 0;
- if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
- ret = -EFAULT;
- goto err;
- }
- }
- if (bwr.read_size > 0) {
- ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
- if (!list_empty(&proc->todo))
- wake_up_interruptible(&proc->wait);
- if (ret < 0) {
- if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
- ret = -EFAULT;
- goto err;
- }
- }
- if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)
- printk(KERN_INFO "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
- proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size);
- if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
- ret = -EFAULT;
- goto err;
- }
- break;
- }
- ......
- default:
- ret = -EINVAL;
- goto err;
- }
- ret = 0;
- err:
- ......
- return ret;
- }
这里的filp->private_data的值是在defaultServiceManager函数创建ProcessState对象时,在ProcessState构造函数通过open文件操作函数打开设备文件/dev/binder时设置好的,它表示的是调用open函数打开设备文件/dev/binder的进程上下文信息,这里将它取出来保存在proc本地变量中。
这里的thread本地变量表示当前线程上下文信息,通过binder_get_thread函数获得。在前面执行ProcessState构造函数时,也会通过ioctl文件操作函数进入到这个函数,那是第一次进入到binder_ioctl这里,因此,调用binder_get_thread时,表示当前进程上下文信息的proc变量还没有关于当前线程的上下文信息,因此,会为proc创建一个表示当前线程上下文信息的thread,会保存在proc->threads表示的红黑树结构中。这里调用binder_get_thread就可以直接从proc找到并返回了。
进入到BINDER_WRITE_READ相关的逻辑。先看看BINDER_WRITE_READ的定义:
- #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
这里可以看出,BINDER_WRITE_READ命令的参数类型为struct binder_write_read:
- struct binder_write_read {
- signed long write_size; /* bytes to write */
- signed long write_consumed; /* bytes consumed by driver */
- unsigned long write_buffer;
- signed long read_size; /* bytes to read */
- signed long read_consumed; /* bytes consumed by driver */
- unsigned long read_buffer;
- };
这个结构体的含义可以参考浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路一文。这里首先是通过copy_from_user函数把用户传进来的参数的内容拷贝到本地变量bwr中。
从上面的调用过程,我们知道,这里bwr.write_size是大于0的,因此进入到binder_thread_write函数中,我们只关注BC_TRANSACTION相关的逻辑:
- int
- binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
- void __user *buffer, int size, signed long *consumed)
- {
- uint32_t cmd;
- void __user *ptr = buffer + *consumed;
- void __user *end = buffer + size;
- while (ptr < end && thread->return_error == BR_OK) {
- if (get_user(cmd, (uint32_t __user *)ptr))
- return -EFAULT;
- ptr += sizeof(uint32_t);
- if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
- binder_stats.bc[_IOC_NR(cmd)]++;
- proc->stats.bc[_IOC_NR(cmd)]++;
- thread->stats.bc[_IOC_NR(cmd)]++;
- }
- switch (cmd) {
- ......
- case BC_TRANSACTION:
- case BC_REPLY: {
- struct binder_transaction_data tr;
- if (copy_from_user(&tr, ptr, sizeof(tr)))
- return -EFAULT;
- ptr += sizeof(tr);
- binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
- break;
- }
- ......
- default:
- printk(KERN_ERR "binder: %d:%d unknown command %d\n", proc->pid, thread->pid, cmd);
- return -EINVAL;
- }
- *consumed = ptr - buffer;
- }
- return 0;
- }
这里再次把用户传出来的参数拷贝到本地变量tr中,tr的类型为struct binder_transaction_data,这个就是前面我们在IPCThreadState::writeTransactionData写入的内容了。
接着进入到binder_transaction函数中,不相关的代码我们忽略掉:
- static void
- binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
- struct binder_transaction_data *tr, int reply)
- {
- struct binder_transaction *t;
- struct binder_work *tcomplete;
- size_t *offp, *off_end;
- struct binder_proc *target_proc;
- struct binder_thread *target_thread = NULL;
- struct binder_node *target_node = NULL;
- struct list_head *target_list;
- wait_queue_head_t *target_wait;
- struct binder_transaction *in_reply_to = NULL;
- struct binder_transaction_log_entry *e;
- uint32_t return_error;
- .......
- if (reply) {
- ......
- } else {
- if (tr->target.handle) {
- ......
- } else {
- target_node = binder_context_mgr_node;
- if (target_node == NULL) {
- return_error = BR_DEAD_REPLY;
- goto err_no_context_mgr_node;
- }
- }
- ......
- target_proc = target_node->proc;
- if (target_proc == NULL) {
- return_error = BR_DEAD_REPLY;
- goto err_dead_binder;
- }
- if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
- ......
- }
- }
- if (target_thread) {
- ......
- } else {
- target_list = &target_proc->todo;
- target_wait = &target_proc->wait;
- }
- ......
- /* TODO: reuse incoming transaction for reply */
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if (t == NULL) {
- return_error = BR_FAILED_REPLY;
- goto err_alloc_t_failed;
- }
- binder_stats.obj_created[BINDER_STAT_TRANSACTION]++;
- tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
- if (tcomplete == NULL) {
- return_error = BR_FAILED_REPLY;
- goto err_alloc_tcomplete_failed;
- }
- binder_stats.obj_created[BINDER_STAT_TRANSACTION_COMPLETE]++;
- t->debug_id = ++binder_last_id;
- ......
- if (!reply && !(tr->flags & TF_ONE_WAY))
- t->from = thread;
- else
- t->from = NULL;
- t->sender_euid = proc->tsk->cred->euid;
- t->to_proc = target_proc;
- t->to_thread = target_thread;
- t->code = tr->code;
- t->flags = tr->flags;
- t->priority = task_nice(current);
- t->buffer = binder_alloc_buf(target_proc, tr->data_size,
- tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
- if (t->buffer == NULL) {
- return_error = BR_FAILED_REPLY;
- goto err_binder_alloc_buf_failed;
- }
- t->buffer->allow_user_free = 0;
- t->buffer->debug_id = t->debug_id;
- t->buffer->transaction = t;
- t->buffer->target_node = target_node;
- if (target_node)
- binder_inc_node(target_node, 1, 0, NULL);
- offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
- if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
- ......
- return_error = BR_FAILED_REPLY;
- goto err_copy_data_failed;
- }
- ......
- if (reply) {
- ......
- } else if (!(t->flags & TF_ONE_WAY)) {
- BUG_ON(t->buffer->async_transaction != 0);
- t->need_reply = 1;
- t->from_parent = thread->transaction_stack;
- thread->transaction_stack = t;
- } else {
- ......
- }
- t->work.type = BINDER_WORK_TRANSACTION;
- list_add_tail(&t->work.entry, target_list);
- tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
- list_add_tail(&tcomplete->entry, &thread->todo);
- if (target_wait)
- wake_up_interruptible(target_wait);
- return;
- ......
- }