Successfully write transaction 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 return rv;
111 }
112
113 } // namespace minibind