binder驱动binder_transaction
case BINDER_TYPE_FD: {
int target_fd;
struct file *file;
if (reply) {
if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
proc->pid, thread->pid, fp->handle);
return_error = BR_FAILED_REPLY;
goto err_fd_not_allowed;
}
} else if (!target_node->accept_fds) {
binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
proc->pid, thread->pid, fp->handle);
return_error = BR_FAILED_REPLY;
goto err_fd_not_allowed;
}
file = fget(fp->handle);
if (file == NULL) {
binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
proc->pid, thread->pid, fp->handle);
return_error = BR_FAILED_REPLY;
goto err_fget_failed;
}
target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
if (target_fd < 0) {
fput(file);
return_error = BR_FAILED_REPLY;
goto err_get_unused_fd_failed;
}
task_fd_install(target_proc, target_fd, file);
binder_debug(BINDER_DEBUG_TRANSACTION,
" fd %ld -> %d\n", fp->handle, target_fd);
/* TODO: fput? */
fp->handle = target_fd;
} break;
以上的file = fget(fp->handle)和task_get_unused_fd_flags共同完成dup包含操作集fops的file,然后assertReallyMapped将再次执行mmap,映射ashmem或pmem申请到的同一块物理内存.
BpMemoryHeap::assertReallyMapped
remote()->transact(HEAP_ID, data, &reply);
会被binder另一端的onTransact函数接收并处理
BnMemoryHeap::onTransact
status_t BnMemoryHeap::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case HEAP_ID: {
CHECK_INTERFACE(IMemoryHeap, data, reply);
reply->writeFileDescriptor(getHeapID());
reply->writeInt32(getSize());
reply->writeInt32(getFlags());
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
status_t Parcel::writeFileDescriptor(int fd)
{
flat_binder_object obj;
obj.type = BINDER_TYPE_FD;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
obj.handle = fd;
obj.cookie = (void*)0;
return writeObject(obj, true);
}
void* BpMemoryHeap::getBase() const {
assertMapped();
return mBase;
}
BpMemoryHeap::assertMapped
void BpMemoryHeap::assertMapped() const
{
if (mHeapId == -1) {
sp binder(const_cast(this)->asBinder());
sp heap(static_cast(find_heap(binder).get()));
heap->assertReallyMapped(); // 这会做实际的map工作
if (heap->mBase != MAP_FAILED) {
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
mBase = heap->mBase;
mSize = heap->mSize;
android_atomic_write( dup( heap->mHeapId ), &mHeapId );
}
} else {
// something went wrong
free_heap(binder);
}
}
}
void BpMemoryHeap::assertReallyMapped() const
{
if (mHeapId == -1) {
// remote call without mLock held, worse case scenario, we end up
// calling transact() from multiple threads, but that's not a problem,
// only mmap below must be in the critical section.
Parcel data, reply;
data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
status_t err = remote()->transact(HEAP_ID, data, &reply);
int parcel_fd = reply.readFileDescriptor(); // 在驱动binder_transaction中BINDER_TYPE_FD
// 然后remote的file结构体,在kernel中被执行file = fget(fp->handle);获取设备描述符号
ssize_t size = reply.readInt32();
uint32_t flags = reply.readInt32();
LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
asBinder().get(), parcel_fd, size, err, strerror(-err));
int fd = dup( parcel_fd );
LOGE_IF(fd==-1, "cannot dup fd=%d, size=%ld, err=%d (%s)",
parcel_fd, size, err, strerror(errno));
int access = PROT_READ;
if (!(flags & READ_ONLY)) {
access |= PROT_WRITE;
}
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
mRealHeap = true;
mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
if (mBase == MAP_FAILED) {
LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
asBinder().get(), size, fd, strerror(errno));
close(fd);
} else {
mSize = size;
mFlags = flags;
android_atomic_write(fd, &mHeapId);
}
}
}
}
BootAnimation::BootAnimation() : Thread(false)
{
mSession = new SurfaceComposerClient(); // 与SurfaceFlinger创建一个Connection,也叫session
}
SurfaceComposerClient::SurfaceComposerClient()
sp sm(getComposerService()); // 就是binder获取"SurfaceFlinger"系统服务,即SurfaceFlinger::instantiate()添加的service
_init(sm, sm->createConnection());
SurfaceFlinger::createConnection()
==> sp client = new Client(token, this);
==> sp bclient =
new BClient(this, token, client->getControlBlockMemory());
frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp
Client::Client(ClientID clientID, const sp& flinger)
: ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
{
const int pgsize = getpagesize();
const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0,
"SurfaceFlinger Client control-block");
ctrlblk = static_cast(mCblkHeap->getBase());
if (ctrlblk) { // construct the shared structure in-place.
new(ctrlblk) SharedClient;
}
}
首先在上面通过createConnection()创建一个client,然后才能创建SurfaceFlinger::createSurface
SurfaceComposerClient::createSurface