Begin processing read commands.
[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 #define BINDER_RP(br) ALOG("return_proto: %s: %d (0x%x)", #br, br, br)
50 BINDER_RP(BR_ERROR);
51 BINDER_RP(BR_OK);
52 BINDER_RP(BR_TRANSACTION);
53 BINDER_RP(BR_REPLY);
54 BINDER_RP(BR_ACQUIRE_RESULT);
55 BINDER_RP(BR_DEAD_REPLY);
56 BINDER_RP(BR_TRANSACTION_COMPLETE);
57 BINDER_RP(BR_INCREFS);
58 BINDER_RP(BR_ACQUIRE);
59 BINDER_RP(BR_RELEASE);
60 BINDER_RP(BR_DECREFS);
61 BINDER_RP(BR_ATTEMPT_ACQUIRE);
62 BINDER_RP(BR_NOOP);
63 BINDER_RP(BR_SPAWN_LOOPER);
64 BINDER_RP(BR_FINISHED);
65 BINDER_RP(BR_DEAD_BINDER);
66 BINDER_RP(BR_CLEAR_DEATH_NOTIFICATION_DONE);
67 BINDER_RP(BR_FAILED_REPLY);
68
69 return fd;
70 }
71
72 void CopyCommandsToBuffer(const std::vector<Command*>& commands,
73 std::vector<unsigned char>* buffer) {
74 size_t last_command_size = 0;
75 for (const Command* command : commands) {
76 memcpy(&(*buffer)[last_command_size], reinterpret_cast<void*>(command->GetData()), command->GetSize());
77 last_command_size += command->GetSize();
78 }
79 }
80
81 } // namespace
82
83 Channel::Channel(uint32_t handle)
84 : handle_(handle),
85 driver_(ConnectDriver()),
86 reader_() {
87 reader_.SetDataSize(256);
88 }
89
90 Channel::~Channel() {
91 }
92
93 int Channel::Call(uint32_t code, const Parcel& in, Parcel* out) {
94 reader_.SetDataPosition(0);
95
96 struct binder_write_read bwr = {};
97
98 TransactionCommand command(TransactionCommand::TWO_WAY);
99 command.SetHandle(handle());
100 command.SetCode(code);
101 command.SetParcel(in);
102
103 bwr.write_size = command.GetSize();
104 bwr.write_buffer = command.GetData();
105 bwr.read_size = reader_.DataSize();
106 bwr.read_buffer = reader_.DataPointer();
107
108 int rv = ioctl(driver_, BINDER_WRITE_READ, &bwr);
109 ALOG("BINDER_WRITE_READ %d (written %d/%d, read %d/%d)", rv, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size);
110 if (rv != 0)
111 return -errno;
112
113 for (binder_size_t index = 0;
114 index < bwr.read_consumed;
115 index = reader_.DataPosition()) {
116 size_t remaining = bwr.read_consumed - index;
117 if (remaining < sizeof(uint32_t))
118 break;
119
120 uint32_t command = 0;
121 if (!reader_.ReadUInt32(&command))
122 break;
123
124 if (!ProcessCommand(command, remaining))
125 break;
126 }
127
128 return rv;
129 }
130
131 bool Channel::ProcessCommand(uint32_t command, size_t data_remaining) {
132 ALOG("ProcessCommand: 0x%x", command);
133 switch (command) {
134 case BR_ERROR: {
135 if (data_remaining < sizeof(int))
136 return false;
137
138 uint32_t error_code = 0;
139 if (!reader_.ReadUInt32(&error_code))
140 return false;
141
142 ALOG("BR_ERROR: %d", error_code);
143 break;
144 }
145 case BR_OK:
146 ALOG("BR_OK");
147 break;
148 case BR_TRANSACTION:
149 break;
150 case BR_REPLY:
151 break;
152 case BR_ACQUIRE_RESULT:
153 break;
154 case BR_DEAD_REPLY:
155 break;
156 case BR_TRANSACTION_COMPLETE:
157 break;
158 case BR_INCREFS:
159 break;
160 case BR_ACQUIRE:
161 break;
162 case BR_RELEASE:
163 break;
164 case BR_DECREFS:
165 break;
166 case BR_ATTEMPT_ACQUIRE:
167 break;
168 case BR_NOOP:
169 ALOG("BR_NOOP");
170 break;
171 case BR_SPAWN_LOOPER:
172 break;
173 case BR_FINISHED:
174 break;
175 case BR_DEAD_BINDER:
176 break;
177 case BR_CLEAR_DEATH_NOTIFICATION_DONE:
178 break;
179 case BR_FAILED_REPLY:
180 ALOG("BR_FAILED_REPLY");
181 break;
182 };
183 }
184
185 } // namespace minibind