First cut at minibind classes.
[minibind.git] / jni / minibind / channel.cc
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "channel.h"
6
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <sys/mman.h>
10
11 #include <linux/binder.h>
12
13 #include "command.h"
14 #include "common.h"
15
16 namespace minibind {
17
18 namespace {
19
20 int ConnectDriver() {
21 int fd = open("/dev/binder", O_RDONLY);
22 if (fd < 0) {
23 AERR("open driver");
24 abort();
25 }
26
27 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
28 AERR("fcntl FD_CLOEXEC");
29 }
30
31 struct binder_version version;
32 int rv = ioctl(fd, BINDER_VERSION, &version);
33 if (rv) {
34 AERR("ioctl BINDER_VERSION");
35 abort();
36 }
37 ALOG("Binder version: %d", version.protocol_version);
38 if (version.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION) {
39 ALOG("Version is not compatible with current protocol: %d", BINDER_CURRENT_PROTOCOL_VERSION);
40 abort();
41 }
42
43 void* vm = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
44 if (vm == MAP_FAILED) {
45 AERR("mmap BINDER_VM_SIZE");
46 abort();
47 }
48
49 return fd;
50 }
51
52 void CopyCommandsToBuffer(const std::vector<Command*>& commands,
53 std::vector<unsigned char>* buffer) {
54 size_t last_command_size = 0;
55 for (const Command* command : commands) {
56 memcpy(&(*buffer)[last_command_size], reinterpret_cast<void*>(command->GetData()), command->GetSize());
57 last_command_size += command->GetSize();
58 }
59 }
60
61 } // namespace
62
63 Channel::Channel(uint32_t handle)
64 : handle_(handle),
65 driver_(ConnectDriver()),
66 write_commands_size_(0),
67 write_commands_(),
68 reader_() {
69 reader_.SetDataSize(256);
70 }
71
72 Channel::~Channel() {
73 }
74
75 void Channel::QueueCommand(Command* cmd) {
76 write_commands_size_ += cmd->GetSize();
77 write_commands_.push_back(cmd);
78 }
79
80 int Channel::TransactCommands() {
81 struct binder_write_read bwr = {};
82
83 std::vector<unsigned char> write_data(write_commands_size_, 0);
84 CopyCommandsToBuffer(write_commands_, &write_data);
85
86 bwr.write_size = write_commands_size_;
87 bwr.write_buffer = reinterpret_cast<binder_uintptr_t>(&write_data[0]);
88 bwr.read_size = reader_.DataSize();
89 bwr.read_buffer = reader_.DataPointer();
90
91 int rv = ioctl(driver_, BINDER_WRITE_READ, &bwr);
92 ALOG("BINDER_WRITE_READ %d", rv);
93 return rv;
94 }
95
96 } // namespace minibind