#include "binder.h" int binder_become_context_manager( PBINDER_INFO info, binder_uintptr_t cookie, binder_uintptr_t binder, BOOL ext ){ DCHECK(ext < BOOL_BOUND); if(ext){ struct flat_binder_object fbo; fbo.hdr.type = BINDER_TYPE_BINDER; fbo.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; fbo.binder = binder; fbo.cookie = cookie; return ioctl(info->fd_, BINDER_SET_CONTEXT_MGR_EXT, &fbo); } else { return ioctl(info->fd_, BINDER_SET_CONTEXT_MGR, NULL); } } int binder_free_buffer( PBINDER_INFO info, binder_uintptr_t buffer ){ struct { uint32_t cmd_; binder_uintptr_t buffer_; }__packed data; data.cmd_ = BC_FREE_BUFFER; data.buffer_ = buffer; return binder_write(info, (BYTE*)&data, sizeof(data)); } int binder_freeze( PBINDER_INFO info, uint32_t pid, uint32_t enable, uint32_t timeout_ms ){ struct binder_freeze_info bfi; bfi.pid = pid; bfi.enable = enable; bfi.timeout_ms = timeout_ms; return ioctl(info->fd_, BINDER_FREEZE, &bfi); } int binder_open(PBINDER_INFO info, size_t mapsize){ struct binder_version ver; size_t max_threads = DEFAULT_MAX_BINDER_THREADS; info->fd_ = open(BINDER_DEVICE, O_RDWR | O_CLOEXEC); CHECK_LOG("binder device open failed!", info->fd_ >= 0); if(ioctl(info->fd_, BINDER_VERSION, &ver) < 0) return BINDER_VERSION_ERROR; if(ioctl(info->fd_, BINDER_SET_MAX_THREADS, &max_threads) < 0) return BINDER_SET_MAX_THREADS_ERROR; info->mapsize_ = mapsize; info->mapped_ = mmap( NULL, mapsize, PROT_READ, MAP_PRIVATE, info->fd_, 0); if(info->mapped_ == MAP_FAILED) return BINDER_MAPPED_ERROR; return BINDER_SUCCESS; } int binder_close(PBINDER_INFO info){ munmap(info->mapped_, info->mapsize_); close(info->fd_); return BINDER_SUCCESS; } int binder_increfs(PBINDER_INFO info, uint32_t target){ struct { uint32_t cmd_; uint32_t target_; }__packed data; data.cmd_ = BC_INCREFS; data.target_ = target; return binder_write(info, (BYTE*)&data, sizeof(data)); } int binder_acquire(PBINDER_INFO info, uint32_t target){ struct { uint32_t cmd_; uint32_t target_; }__packed data; data.cmd_ = BC_ACQUIRE; data.target_ = target; return binder_write(info, (BYTE*)&data, sizeof(data)); } int binder_release(PBINDER_INFO info, uint32_t target){ struct { uint32_t cmd_; uint32_t target_; }__packed data; data.cmd_ = BC_RELEASE; data.target_ = target; return binder_write(info, (BYTE*)&data, sizeof(data)); } int binder_decrefs(PBINDER_INFO info, uint32_t target){ struct { uint32_t cmd_; uint32_t target_; }__packed data; data.cmd_ = BC_DECREFS; data.target_ = target; return binder_write(info, (BYTE*)&data, sizeof(data)); } size_t binder_read_write( PBINDER_INFO info, BYTE* wbuffer, size_t wsize, BYTE* rbuffer, size_t rsize ){ struct binder_write_read bwr; bwr.read_buffer = (binder_uintptr_t)rbuffer; bwr.read_size = rsize; bwr.read_consumed = 0; bwr.write_buffer = (binder_uintptr_t)wbuffer; bwr.write_size = wsize; bwr.write_consumed = 0; ioctl(info->fd_, BINDER_WRITE_READ, &bwr); return bwr.read_consumed; } size_t binder_read(PBINDER_INFO info, BYTE* buffer, size_t size){ return binder_read_write(info, NULL, 0, buffer, size); } int binder_write(PBINDER_INFO info, BYTE* buffer, size_t size){ return binder_read_write(info, buffer, size, NULL, 0); } size_t binder_transaction( PBINDER_INFO info, BYTE* reply, size_t rsize, struct binder_transaction_data tr ){ struct { uint32_t cmd_; struct binder_transaction_data tr_; }__packed data; size_t res = 0; data.cmd_ = BC_TRANSACTION; data.tr_ = tr; res = binder_read_write( info, (BYTE*)&data, sizeof(data), reply, rsize); return res; } void* parse_binder_message( BYTE* rbuffer, size_t rsize ){ size_t end_addr = (size_t)rbuffer + rsize; for (size_t ptr = (size_t)rbuffer; ptr < end_addr; ptr+=sizeof(uint32_t)){ uint32_t cmd = *((uint32_t*)ptr); if((cmd == BR_REPLY) || (cmd == BR_TRANSACTION)){ ptr += sizeof(uint32_t); return (void*)ptr; } } return NULL; } void binder_set_looper( PBINDER_INFO info ){ uint32_t cmd = BC_ENTER_LOOPER; binder_write(info, (BYTE*)&cmd, sizeof(uint32_t)); } void binder_reg_looper( PBINDER_INFO info ){ uint32_t cmd = BC_REGISTER_LOOPER; binder_write(info, (BYTE*)&cmd, sizeof(uint32_t)); } size_t binder_transaction_sg( PBINDER_INFO info, BYTE* reply, size_t rsize, struct binder_transaction_data_sg tr ){ struct { uint32_t cmd_; struct binder_transaction_data_sg tr_; }__packed data; size_t res = 0; data.cmd_ = BC_TRANSACTION_SG; binder_size_t bz = tr.buffers_size; while(((unsigned long long)bz) % sizeof(8)){ bz++; } tr.buffers_size = bz; data.tr_ = tr; res = binder_read_write( info, (BYTE*)&data, sizeof(data), reply, rsize); return res; } int binder_reply( PBINDER_INFO info, BYTE* rbuffer, size_t rsize, struct binder_transaction_data tr ){ struct { uint32_t cmd_; struct binder_transaction_data tr_; }__packed data; data.cmd_ = BC_REPLY; data.tr_ = tr; return binder_read_write( info, (BYTE*)&data, sizeof(data), rbuffer, rsize); } int binder_reply_sg( PBINDER_INFO info, BYTE* rbuffer, size_t rsize, struct binder_transaction_data tr ){ struct { uint32_t cmd_; struct binder_transaction_data_sg tr_; }__packed data; data.cmd_ = BC_REPLY_SG; data.tr_.buffers_size = sizeof(tr); data.tr_.transaction_data = tr; return binder_read_write( info, (BYTE*)&data, sizeof(data), rbuffer, rsize); } int binder_request_death_notification( PBINDER_INFO info, uint32_t target, binder_uintptr_t cookie ){ struct { uint32_t cmd_; uint32_t target_; binder_uintptr_t cookie_; }__packed data; data.cmd_ = BC_REQUEST_DEATH_NOTIFICATION; data.target_ = target; data.cookie_ = cookie; return binder_read_write( info, (BYTE*)&data, sizeof(data), (BYTE*)NULL, 0); } int binder_clear_death_notification( PBINDER_INFO info, uint32_t target, binder_uintptr_t cookie ){ struct { uint32_t cmd_; uint32_t target_; binder_uintptr_t cookie_; }__packed data; data.cmd_ = BC_CLEAR_DEATH_NOTIFICATION; data.target_ = target; data.cookie_ = cookie; return binder_read_write( info, (BYTE*)&data, sizeof(data), (BYTE*)NULL, 0); } void set_tr_target_handle( PTR_BUILDER this, uint32_t handle ){ this->tr_.target.handle = handle; } void set_tr_target_ptr( PTR_BUILDER this, binder_uintptr_t ptr ){ this->tr_.target.ptr = ptr; } void set_tr_cookie( PTR_BUILDER this, binder_uintptr_t cookie ){ this->tr_.cookie = cookie; } void set_tr_code( PTR_BUILDER this, uint32_t code ){ this->tr_.code = code; } void set_tr_flags( PTR_BUILDER this, uint32_t flags ){ this->tr_.flags = flags; } void set_tr_sender_pid( PTR_BUILDER this, pid_t sender_pid ){ this->tr_.sender_pid = sender_pid; } void set_tr_sender_euid( PTR_BUILDER this, uid_t sender_euid ){ this->tr_.sender_euid = sender_euid; } void set_tr_data_size( PTR_BUILDER this, binder_size_t data_size ){ this->tr_.data_size = data_size; } void set_tr_offsets_size( PTR_BUILDER this, binder_size_t offsets_size ){ this->tr_.offsets_size = offsets_size; } void set_tr_data_ptr_buffer( PTR_BUILDER this, binder_uintptr_t buffer ){ this->tr_.data.ptr.buffer = buffer; } void set_tr_data_ptr_offsets( PTR_BUILDER this, binder_uintptr_t offsets ){ this->tr_.data.ptr.offsets = offsets; } void set_fbo_flags( PBINDER_OBJECT_BUILDER this, uint32_t flags ){ this->obj_.flags = flags; } void set_fbo_cookie( PBINDER_OBJECT_BUILDER this, binder_uintptr_t cookie ){ this->obj_.cookie = cookie; } void set_fbo_binder( PBINDER_OBJECT_BUILDER this, binder_uintptr_t binder ){ this->obj_.binder = binder; } void set_fbo_handle( PBINDER_OBJECT_BUILDER this, uint32_t handle ){ this->obj_.handle = handle; } void set_fbo_hdr_type( PBINDER_OBJECT_BUILDER this, uint32_t type ){ this->obj_.hdr.type = type; }