From 935d9f8717116ac855dffb56fbbd533eeb8f1dc4 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Wed, 21 Jan 2015 20:23:30 -0500 Subject: [PATCH] Successfully write transaction commands. --- jni/minibind/channel.cc | 41 +++++++--- jni/minibind/channel.h | 15 ++-- jni/minibind/minibind.cc | 169 +++++---------------------------------- jni/minibind/parcel.cc | 24 +++++- jni/minibind/parcel.h | 6 ++ 5 files changed, 84 insertions(+), 171 deletions(-) diff --git a/jni/minibind/channel.cc b/jni/minibind/channel.cc index 97f7b67..717cbb8 100644 --- a/jni/minibind/channel.cc +++ b/jni/minibind/channel.cc @@ -46,6 +46,26 @@ int ConnectDriver() { abort(); } +#define BINDER_RP(br) ALOG("return_proto: %s: %d (0x%x)", #br, br, br) + BINDER_RP(BR_ERROR); + BINDER_RP(BR_OK); + BINDER_RP(BR_TRANSACTION); + BINDER_RP(BR_REPLY); + BINDER_RP(BR_ACQUIRE_RESULT); + BINDER_RP(BR_DEAD_REPLY); + BINDER_RP(BR_TRANSACTION_COMPLETE); + BINDER_RP(BR_INCREFS); + BINDER_RP(BR_ACQUIRE); + BINDER_RP(BR_RELEASE); + BINDER_RP(BR_DECREFS); + BINDER_RP(BR_ATTEMPT_ACQUIRE); + BINDER_RP(BR_NOOP); + BINDER_RP(BR_SPAWN_LOOPER); + BINDER_RP(BR_FINISHED); + BINDER_RP(BR_DEAD_BINDER); + BINDER_RP(BR_CLEAR_DEATH_NOTIFICATION_DONE); + BINDER_RP(BR_FAILED_REPLY); + return fd; } @@ -63,8 +83,6 @@ void CopyCommandsToBuffer(const std::vector& commands, Channel::Channel(uint32_t handle) : handle_(handle), driver_(ConnectDriver()), - write_commands_size_(0), - write_commands_(), reader_() { reader_.SetDataSize(256); } @@ -72,24 +90,23 @@ Channel::Channel(uint32_t handle) Channel::~Channel() { } -void Channel::QueueCommand(Command* cmd) { - write_commands_size_ += cmd->GetSize(); - write_commands_.push_back(cmd); -} +int Channel::Call(uint32_t code, const Parcel& in, Parcel* out) { + reader_.SetDataPosition(0); -int Channel::TransactCommands() { struct binder_write_read bwr = {}; - std::vector write_data(write_commands_size_, 0); - CopyCommandsToBuffer(write_commands_, &write_data); + TransactionCommand command(TransactionCommand::TWO_WAY); + command.SetHandle(handle()); + command.SetCode(code); + command.SetParcel(in); - bwr.write_size = write_commands_size_; - bwr.write_buffer = reinterpret_cast(&write_data[0]); + bwr.write_size = command.GetSize(); + bwr.write_buffer = command.GetData(); bwr.read_size = reader_.DataSize(); bwr.read_buffer = reader_.DataPointer(); int rv = ioctl(driver_, BINDER_WRITE_READ, &bwr); - ALOG("BINDER_WRITE_READ %d", rv); + ALOG("BINDER_WRITE_READ %d (written %d/%d, read %d/%d)", rv, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size); return rv; } diff --git a/jni/minibind/channel.h b/jni/minibind/channel.h index bbd8004..edfa500 100644 --- a/jni/minibind/channel.h +++ b/jni/minibind/channel.h @@ -17,26 +17,27 @@ class Command; class Channel { public: + enum { + FIRST_CALL_CODE = 0x00000001, + LAST_CALL_CODE = 0x00ffffff, + + PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'), + }; + explicit Channel(uint32_t handle); ~Channel(); - void QueueCommand(Command* cmd); - - int TransactCommands(); + int Call(uint32_t code, const Parcel& in, Parcel* out); Parcel* reader() { return &reader_; } uint32_t handle() const { return handle_; } - const std::vector& write_commands() const { return write_commands_; } private: uint32_t handle_; int driver_; Parcel reader_; - - size_t write_commands_size_; - std::vector write_commands_; }; } // namespace minibind diff --git a/jni/minibind/minibind.cc b/jni/minibind/minibind.cc index 0feb8e8..d39b3d8 100644 --- a/jni/minibind/minibind.cc +++ b/jni/minibind/minibind.cc @@ -4,14 +4,6 @@ #include "minibind.h" -#include -#include -#include -#include -#include - -#include - #include "channel.h" #include "command.h" #include "common.h" @@ -19,163 +11,40 @@ namespace minibind { -int ConnectDriver() { - int fd = open("/dev/binder", O_RDONLY); - if (fd < 0) { - AERR("open driver"); - abort(); - } +namespace { - if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { - AERR("fcntl FD_CLOEXEC"); - } +Channel* GetServiceManager() { + static Channel* service_manager = nullptr; + if (!service_manager) { + service_manager = new Channel(0); - struct binder_version version; - int rv = ioctl(fd, BINDER_VERSION, &version); - if (rv) { - AERR("ioctl BINDER_VERSION"); - abort(); - } - ALOG("Binder version: %d", version.protocol_version); - if (version.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION) { - ALOG("Version is not compatible with current protocol: %d", BINDER_CURRENT_PROTOCOL_VERSION); - abort(); + Parcel in, out; + service_manager->Call(Channel::PING_TRANSACTION, in, &out); + service_manager->reader()->Print(); } - void* vm = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0); - if (vm == MAP_FAILED) { - AERR("mmap BINDER_VM_SIZE"); - abort(); - } - - return fd; + return service_manager; } -class Transaction { - public: - Transaction() : sealed_(false), - read_buffer_(), - write_buffer_(), - command_(), - write_tx_(), - read_tx_() { - read_buffer_.resize(64); - } - ~Transaction() {} - - void WriteString8(const std::string& str) { - CHECK(!sealed_); - for (size_t i = 0; i < str.length(); ++i) { - write_buffer_.push_back(str[i]); - } - write_buffer_.push_back('\0'); - } - - void WriteInt32(uint32_t i) { - CHECK(!sealed_); - write_buffer_.push_back((i >> 24) & 0xFF); - write_buffer_.push_back((i >> 16) & 0xFF); - write_buffer_.push_back((i >> 8) & 0xFF); - write_buffer_.push_back((i >> 0) & 0xFF); - } - - const struct binder_transaction_data* read_data() const { return &read_tx_.data; } - - private: - friend class Channel2; - - struct TransactionBuffer { - TransactionBuffer() : command(BC_TRANSACTION), data() {} - - uint32_t command; - struct binder_transaction_data data; - }; - - void Seal() { - CHECK(!sealed_); - - write_tx_.data.data_size = write_buffer_.size(); - write_tx_.data.data.ptr.buffer = reinterpret_cast(&write_buffer_[0]); - - read_tx_.command = BC_REPLY; - read_tx_.data.data_size = read_buffer_.size(); - read_tx_.data.data.ptr.buffer = reinterpret_cast(&read_buffer_[0]); - - command_.write_size = sizeof(write_tx_); - command_.write_buffer = reinterpret_cast(&write_tx_); - command_.read_size = sizeof(read_tx_); - command_.read_buffer = reinterpret_cast(&read_tx_); - - sealed_ = true; - } - - bool sealed_; - - std::vector write_buffer_; - std::vector read_buffer_; - - struct binder_write_read command_; - TransactionBuffer write_tx_; - TransactionBuffer read_tx_; -}; - -class Channel2 { - public: - Channel2(const std::string& interface) - : interface_(interface), - fd_(ConnectDriver()) { - } - ~Channel2() {} - - Transaction* NewTransaction(uint32_t code) const { - Transaction* t = new Transaction(); - t->write_tx_.data.code = code; - t->WriteString8(interface()); - return t; - } - - int ExecuteTransaction(Transaction* tx) { - tx->Seal(); - int rv = ioctl(fd_, BINDER_WRITE_READ, &tx->command_); - ALOG("BINDER_WRITE_READ: %d", rv); - if (rv) { - AERR("BINDER_WRITE_READ"); - } - - for (size_t i = 0; i < tx->read_buffer_.size(); i += 4) { - ALOG("%0x %0x %0x %0x", tx->read_buffer_[i], tx->read_buffer_[i+1], tx->read_buffer_[i+2], tx->read_buffer_[i+3]); - } - } - - const std::string& interface() const { return interface_; } - - private: - const std::string interface_; - int fd_; -}; +} // namespace Channel* LookupService(const std::string& name) { Parcel data; data.WriteInterfaceToken("android.os.IServiceManager"); data.WriteUTF8(name); - Channel channel(0); + Parcel reply; - TransactionCommand command(TransactionCommand::TWO_WAY); - command.SetHandle(channel.handle()); - command.SetCode(2 /*CHECK_SERVICE_TRANSACTION*/); - command.SetParcel(data); + Channel* channel = GetServiceManager(); + channel->Call(2 /*CHECK_SERVICE_TRANSACTION*/, data, &reply); - channel.QueueCommand(&command); - channel.TransactCommands(); - channel.reader()->Print(); + channel->reader()->Print(); -#if 0 - Channel2* ch = new Channel2("android.os.IServiceManager"); - Transaction* tx = ch->NewTransaction(2 /*CHECK_SERVICE_TRANSACTION*/); - tx->WriteString8(name); - ch->ExecuteTransaction(tx); -#endif + uint32_t cmd = 0; + CHECK(channel->reader()->ReadUInt32(&cmd)); + ALOG("Got command: %x (dec %d %u)", cmd, cmd, cmd); + CHECK(channel->reader()->ReadUInt32(&cmd)); + ALOG("Got command: %x (dec %d %u)", cmd, cmd, cmd); } } // namespace minibind diff --git a/jni/minibind/parcel.cc b/jni/minibind/parcel.cc index 7cf419d..9e2367a 100644 --- a/jni/minibind/parcel.cc +++ b/jni/minibind/parcel.cc @@ -8,7 +8,7 @@ namespace minibind { -Parcel::Parcel() : data_(), objects_() {} +Parcel::Parcel() : data_position_(0), data_(), objects_() {} Parcel::~Parcel() {} @@ -27,12 +27,27 @@ void Parcel::WriteUInt32(uint32_t ui32) { data_.push_back((ui32 >> 0) & 0xff); } +bool Parcel::ReadUInt32(uint32_t* ui32) { + return ReadBytes(sizeof(*ui32), ui32); +} + +bool Parcel::ReadBytes(size_t count, void* buffer) { + // TODO: overflow + ALOG("count=%d, data_position_=%d, datasize=%d", count, data_position_, DataSize()); + if (count + data_position_ >= DataSize()) + return false; + + memcpy(buffer, &data_[data_position_], count); + data_position_ += count; + return true; +} + binder_uintptr_t Parcel::DataPointer() const { return reinterpret_cast(&data_[0]); } size_t Parcel::DataSize() const { - return 0; + return data_.size(); } void Parcel::SetDataSize(size_t size) { @@ -41,6 +56,11 @@ void Parcel::SetDataSize(size_t size) { data_.resize(size); } +void Parcel::SetDataPosition(size_t pos) { + CHECK(pos < DataSize()); + data_position_ = pos; +} + void Parcel::Print() const { for (size_t i = 0; i < data_.size(); i += 4) { ALOG("%0x %0x %0x %0x", data_[i], data_[i+1], data_[i+2], data_[i+3]); diff --git a/jni/minibind/parcel.h b/jni/minibind/parcel.h index f7718f5..ba017f2 100644 --- a/jni/minibind/parcel.h +++ b/jni/minibind/parcel.h @@ -24,13 +24,19 @@ class Parcel { void WriteUTF8(const std::string& str); void WriteUInt32(uint32_t ui32); + bool ReadUInt32(uint32_t* ui32); + bool ReadBytes(size_t count, void* buffer); + binder_uintptr_t DataPointer() const; size_t DataSize() const; void SetDataSize(size_t size); + void SetDataPosition(size_t pos); + void Print() const; private: + size_t data_position_; std::vector data_; std::vector objects_; }; -- 2.22.5