// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "minibind.h" #include #include #include #include #include #include #include "channel.h" #include "command.h" #include "common.h" #include "parcel.h" namespace minibind { int ConnectDriver() { int fd = open("/dev/binder", O_RDONLY); if (fd < 0) { AERR("open driver"); abort(); } if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { AERR("fcntl FD_CLOEXEC"); } 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(); } 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; } 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_; }; Channel* LookupService(const std::string& name) { Parcel data; data.WriteInterfaceToken("android.os.IServiceManager"); data.WriteUTF8(name); Channel channel(0); TransactionCommand command(TransactionCommand::TWO_WAY); command.SetHandle(channel.handle()); command.SetCode(2 /*CHECK_SERVICE_TRANSACTION*/); command.SetParcel(data); channel.QueueCommand(&command); channel.TransactCommands(); 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 } } // namespace minibind