blob: 5f206af25b6b879b54ed27bd595d92e0e65ca109 [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/* Copyright 2008 The Android Open Source Project
2 */
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <errno.h>
7#include <unistd.h>
8#include <fcntl.h>
9#include <sys/mman.h>
10
11#include "binder.h"
12
13#define MAX_BIO_SIZE (1 << 30)
14
15#define TRACE 0
16
17#define LOG_TAG "Binder"
18#include <cutils/log.h>
19
Serban Constantinescubcf38882014-01-10 13:56:27 +000020void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -070021
22#if TRACE
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000023void hexdump(void *_data, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -070024{
25 unsigned char *data = _data;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000026 size_t count;
Mike Lockwood94afecf2012-10-24 10:45:23 -070027
28 for (count = 0; count < len; count++) {
29 if ((count & 15) == 0)
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000030 fprintf(stderr,"%04zu:", count);
Mike Lockwood94afecf2012-10-24 10:45:23 -070031 fprintf(stderr," %02x %c", *data,
32 (*data < 32) || (*data > 126) ? '.' : *data);
33 data++;
34 if ((count & 15) == 15)
35 fprintf(stderr,"\n");
36 }
37 if ((count & 15) != 0)
38 fprintf(stderr,"\n");
39}
40
Serban Constantinescubcf38882014-01-10 13:56:27 +000041void binder_dump_txn(struct binder_transaction_data *txn)
Mike Lockwood94afecf2012-10-24 10:45:23 -070042{
Serban Constantinescubcf38882014-01-10 13:56:27 +000043 struct flat_binder_object *obj;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000044 size_t *offs = txn->data.ptr.offsets;
45 size_t count = txn->offsets_size / sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -070046
47 fprintf(stderr," target %p cookie %p code %08x flags %08x\n",
Serban Constantinescubcf38882014-01-10 13:56:27 +000048 txn->target.ptr, txn->cookie, txn->code, txn->flags);
49 fprintf(stderr," pid %8d uid %8d data %zu offs %zu\n",
50 txn->sender_pid, txn->sender_euid, txn->data_size, txn->offsets_size);
51 hexdump(txn->data.ptr.buffer, txn->data_size);
Mike Lockwood94afecf2012-10-24 10:45:23 -070052 while (count--) {
Serban Constantinescubcf38882014-01-10 13:56:27 +000053 obj = (struct flat_binder_object *) (((char*) txn->data.ptr.buffer) + *offs++);
Mike Lockwood94afecf2012-10-24 10:45:23 -070054 fprintf(stderr," - type %08x flags %08x ptr %p cookie %p\n",
Serban Constantinescubcf38882014-01-10 13:56:27 +000055 obj->type, obj->flags, obj->binder, obj->cookie);
Mike Lockwood94afecf2012-10-24 10:45:23 -070056 }
57}
58
59#define NAME(n) case n: return #n
60const char *cmd_name(uint32_t cmd)
61{
62 switch(cmd) {
63 NAME(BR_NOOP);
64 NAME(BR_TRANSACTION_COMPLETE);
65 NAME(BR_INCREFS);
66 NAME(BR_ACQUIRE);
67 NAME(BR_RELEASE);
68 NAME(BR_DECREFS);
69 NAME(BR_TRANSACTION);
70 NAME(BR_REPLY);
71 NAME(BR_FAILED_REPLY);
72 NAME(BR_DEAD_REPLY);
73 NAME(BR_DEAD_BINDER);
74 default: return "???";
75 }
76}
77#else
78#define hexdump(a,b) do{} while (0)
79#define binder_dump_txn(txn) do{} while (0)
80#endif
81
82#define BIO_F_SHARED 0x01 /* needs to be buffer freed */
83#define BIO_F_OVERFLOW 0x02 /* ran out of space */
84#define BIO_F_IOERROR 0x04
85#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */
86
87struct binder_state
88{
89 int fd;
90 void *mapped;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000091 size_t mapsize;
Mike Lockwood94afecf2012-10-24 10:45:23 -070092};
93
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000094struct binder_state *binder_open(size_t mapsize)
Mike Lockwood94afecf2012-10-24 10:45:23 -070095{
96 struct binder_state *bs;
Serban Constantinescua44542c2014-01-30 15:16:45 +000097 struct binder_version vers;
Mike Lockwood94afecf2012-10-24 10:45:23 -070098
99 bs = malloc(sizeof(*bs));
100 if (!bs) {
101 errno = ENOMEM;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000102 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700103 }
104
105 bs->fd = open("/dev/binder", O_RDWR);
106 if (bs->fd < 0) {
107 fprintf(stderr,"binder: cannot open device (%s)\n",
108 strerror(errno));
109 goto fail_open;
110 }
111
Serban Constantinescua44542c2014-01-30 15:16:45 +0000112 if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
113 (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
114 fprintf(stderr, "binder: driver version differs from user space\n");
115 goto fail_open;
116 }
117
Mike Lockwood94afecf2012-10-24 10:45:23 -0700118 bs->mapsize = mapsize;
119 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
120 if (bs->mapped == MAP_FAILED) {
121 fprintf(stderr,"binder: cannot map device (%s)\n",
122 strerror(errno));
123 goto fail_map;
124 }
125
Mike Lockwood94afecf2012-10-24 10:45:23 -0700126 return bs;
127
128fail_map:
129 close(bs->fd);
130fail_open:
131 free(bs);
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000132 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700133}
134
135void binder_close(struct binder_state *bs)
136{
137 munmap(bs->mapped, bs->mapsize);
138 close(bs->fd);
139 free(bs);
140}
141
142int binder_become_context_manager(struct binder_state *bs)
143{
144 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
145}
146
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000147int binder_write(struct binder_state *bs, void *data, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700148{
149 struct binder_write_read bwr;
150 int res;
151 bwr.write_size = len;
152 bwr.write_consumed = 0;
153 bwr.write_buffer = (unsigned) data;
154 bwr.read_size = 0;
155 bwr.read_consumed = 0;
156 bwr.read_buffer = 0;
157 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
158 if (res < 0) {
159 fprintf(stderr,"binder_write: ioctl failed (%s)\n",
160 strerror(errno));
161 }
162 return res;
163}
164
165void binder_send_reply(struct binder_state *bs,
166 struct binder_io *reply,
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000167 const void *buffer_to_free,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700168 int status)
169{
170 struct {
171 uint32_t cmd_free;
172 void *buffer;
173 uint32_t cmd_reply;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000174 struct binder_transaction_data txn;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700175 } __attribute__((packed)) data;
176
177 data.cmd_free = BC_FREE_BUFFER;
178 data.buffer = buffer_to_free;
179 data.cmd_reply = BC_REPLY;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000180 data.txn.target.ptr = 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700181 data.txn.cookie = 0;
182 data.txn.code = 0;
183 if (status) {
184 data.txn.flags = TF_STATUS_CODE;
185 data.txn.data_size = sizeof(int);
Serban Constantinescubcf38882014-01-10 13:56:27 +0000186 data.txn.offsets_size = 0;
187 data.txn.data.ptr.buffer = &status;
188 data.txn.data.ptr.offsets = 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700189 } else {
190 data.txn.flags = 0;
191 data.txn.data_size = reply->data - reply->data0;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000192 data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
193 data.txn.data.ptr.buffer = reply->data0;
194 data.txn.data.ptr.offsets = reply->offs0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700195 }
196 binder_write(bs, &data, sizeof(data));
197}
198
199int binder_parse(struct binder_state *bs, struct binder_io *bio,
200 uint32_t *ptr, uint32_t size, binder_handler func)
201{
202 int r = 1;
203 uint32_t *end = ptr + (size / 4);
204
205 while (ptr < end) {
206 uint32_t cmd = *ptr++;
207#if TRACE
208 fprintf(stderr,"%s:\n", cmd_name(cmd));
209#endif
210 switch(cmd) {
211 case BR_NOOP:
212 break;
213 case BR_TRANSACTION_COMPLETE:
214 break;
215 case BR_INCREFS:
216 case BR_ACQUIRE:
217 case BR_RELEASE:
218 case BR_DECREFS:
219#if TRACE
220 fprintf(stderr," %08x %08x\n", ptr[0], ptr[1]);
221#endif
222 ptr += 2;
223 break;
224 case BR_TRANSACTION: {
Serban Constantinescubcf38882014-01-10 13:56:27 +0000225 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
226 if ((end - ptr) * sizeof(uint32_t) < sizeof(*txn)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700227 ALOGE("parse: txn too small!\n");
228 return -1;
229 }
230 binder_dump_txn(txn);
231 if (func) {
232 unsigned rdata[256/4];
233 struct binder_io msg;
234 struct binder_io reply;
235 int res;
236
237 bio_init(&reply, rdata, sizeof(rdata), 4);
238 bio_init_from_txn(&msg, txn);
239 res = func(bs, txn, &msg, &reply);
Serban Constantinescubcf38882014-01-10 13:56:27 +0000240 binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700241 }
242 ptr += sizeof(*txn) / sizeof(uint32_t);
243 break;
244 }
245 case BR_REPLY: {
Serban Constantinescubcf38882014-01-10 13:56:27 +0000246 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
247 if ((end - ptr) * sizeof(uint32_t) < sizeof(*txn)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700248 ALOGE("parse: reply too small!\n");
249 return -1;
250 }
251 binder_dump_txn(txn);
252 if (bio) {
253 bio_init_from_txn(bio, txn);
254 bio = 0;
255 } else {
256 /* todo FREE BUFFER */
257 }
258 ptr += (sizeof(*txn) / sizeof(uint32_t));
259 r = 0;
260 break;
261 }
262 case BR_DEAD_BINDER: {
263 struct binder_death *death = (void*) *ptr++;
264 death->func(bs, death->ptr);
265 break;
266 }
267 case BR_FAILED_REPLY:
268 r = -1;
269 break;
270 case BR_DEAD_REPLY:
271 r = -1;
272 break;
273 default:
274 ALOGE("parse: OOPS %d\n", cmd);
275 return -1;
276 }
277 }
278
279 return r;
280}
281
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000282void binder_acquire(struct binder_state *bs, uint32_t target)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700283{
284 uint32_t cmd[2];
285 cmd[0] = BC_ACQUIRE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000286 cmd[1] = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700287 binder_write(bs, cmd, sizeof(cmd));
288}
289
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000290void binder_release(struct binder_state *bs, uint32_t target)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700291{
292 uint32_t cmd[2];
293 cmd[0] = BC_RELEASE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000294 cmd[1] = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700295 binder_write(bs, cmd, sizeof(cmd));
296}
297
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000298void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700299{
300 uint32_t cmd[3];
301 cmd[0] = BC_REQUEST_DEATH_NOTIFICATION;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000302 cmd[1] = (uint32_t) target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700303 cmd[2] = (uint32_t) death;
304 binder_write(bs, cmd, sizeof(cmd));
305}
306
307
308int binder_call(struct binder_state *bs,
309 struct binder_io *msg, struct binder_io *reply,
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000310 uint32_t target, uint32_t code)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700311{
312 int res;
313 struct binder_write_read bwr;
314 struct {
315 uint32_t cmd;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000316 struct binder_transaction_data txn;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700317 } writebuf;
318 unsigned readbuf[32];
319
320 if (msg->flags & BIO_F_OVERFLOW) {
321 fprintf(stderr,"binder: txn buffer overflow\n");
322 goto fail;
323 }
324
325 writebuf.cmd = BC_TRANSACTION;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000326 writebuf.txn.target.handle = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700327 writebuf.txn.code = code;
328 writebuf.txn.flags = 0;
329 writebuf.txn.data_size = msg->data - msg->data0;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000330 writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
331 writebuf.txn.data.ptr.buffer = msg->data0;
332 writebuf.txn.data.ptr.offsets = msg->offs0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700333
334 bwr.write_size = sizeof(writebuf);
335 bwr.write_consumed = 0;
336 bwr.write_buffer = (unsigned) &writebuf;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000337
Mike Lockwood94afecf2012-10-24 10:45:23 -0700338 hexdump(msg->data0, msg->data - msg->data0);
339 for (;;) {
340 bwr.read_size = sizeof(readbuf);
341 bwr.read_consumed = 0;
342 bwr.read_buffer = (unsigned) readbuf;
343
344 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
345
346 if (res < 0) {
347 fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
348 goto fail;
349 }
350
351 res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);
352 if (res == 0) return 0;
353 if (res < 0) goto fail;
354 }
355
356fail:
357 memset(reply, 0, sizeof(*reply));
358 reply->flags |= BIO_F_IOERROR;
359 return -1;
360}
361
362void binder_loop(struct binder_state *bs, binder_handler func)
363{
364 int res;
365 struct binder_write_read bwr;
366 unsigned readbuf[32];
367
368 bwr.write_size = 0;
369 bwr.write_consumed = 0;
370 bwr.write_buffer = 0;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000371
Mike Lockwood94afecf2012-10-24 10:45:23 -0700372 readbuf[0] = BC_ENTER_LOOPER;
373 binder_write(bs, readbuf, sizeof(unsigned));
374
375 for (;;) {
376 bwr.read_size = sizeof(readbuf);
377 bwr.read_consumed = 0;
378 bwr.read_buffer = (unsigned) readbuf;
379
380 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
381
382 if (res < 0) {
383 ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
384 break;
385 }
386
387 res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
388 if (res == 0) {
389 ALOGE("binder_loop: unexpected reply?!\n");
390 break;
391 }
392 if (res < 0) {
393 ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
394 break;
395 }
396 }
397}
398
Serban Constantinescubcf38882014-01-10 13:56:27 +0000399void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700400{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000401 bio->data = bio->data0 = txn->data.ptr.buffer;
402 bio->offs = bio->offs0 = txn->data.ptr.offsets;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700403 bio->data_avail = txn->data_size;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000404 bio->offs_avail = txn->offsets_size / 4;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700405 bio->flags = BIO_F_SHARED;
406}
407
408void bio_init(struct binder_io *bio, void *data,
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000409 size_t maxdata, size_t maxoffs)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700410{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000411 size_t n = maxoffs * sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700412
413 if (n > maxdata) {
414 bio->flags = BIO_F_OVERFLOW;
415 bio->data_avail = 0;
416 bio->offs_avail = 0;
417 return;
418 }
419
420 bio->data = bio->data0 = (char *) data + n;
421 bio->offs = bio->offs0 = data;
422 bio->data_avail = maxdata - n;
423 bio->offs_avail = maxoffs;
424 bio->flags = 0;
425}
426
427static void *bio_alloc(struct binder_io *bio, uint32_t size)
428{
429 size = (size + 3) & (~3);
430 if (size > bio->data_avail) {
431 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000432 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700433 } else {
434 void *ptr = bio->data;
435 bio->data += size;
436 bio->data_avail -= size;
437 return ptr;
438 }
439}
440
441void binder_done(struct binder_state *bs,
442 struct binder_io *msg,
443 struct binder_io *reply)
444{
445 if (reply->flags & BIO_F_SHARED) {
446 uint32_t cmd[2];
447 cmd[0] = BC_FREE_BUFFER;
448 cmd[1] = (uint32_t) reply->data0;
449 binder_write(bs, cmd, sizeof(cmd));
450 reply->flags = 0;
451 }
452}
453
Serban Constantinescubcf38882014-01-10 13:56:27 +0000454static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700455{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000456 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700457
458 obj = bio_alloc(bio, sizeof(*obj));
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000459
Mike Lockwood94afecf2012-10-24 10:45:23 -0700460 if (obj && bio->offs_avail) {
461 bio->offs_avail--;
462 *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
463 return obj;
464 }
465
466 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000467 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700468}
469
470void bio_put_uint32(struct binder_io *bio, uint32_t n)
471{
472 uint32_t *ptr = bio_alloc(bio, sizeof(n));
473 if (ptr)
474 *ptr = n;
475}
476
477void bio_put_obj(struct binder_io *bio, void *ptr)
478{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000479 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700480
481 obj = bio_alloc_obj(bio);
482 if (!obj)
483 return;
484
485 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
486 obj->type = BINDER_TYPE_BINDER;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000487 obj->binder = ptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700488 obj->cookie = 0;
489}
490
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000491void bio_put_ref(struct binder_io *bio, uint32_t handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700492{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000493 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700494
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000495 if (handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700496 obj = bio_alloc_obj(bio);
497 else
498 obj = bio_alloc(bio, sizeof(*obj));
499
500 if (!obj)
501 return;
502
503 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
504 obj->type = BINDER_TYPE_HANDLE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000505 obj->handle = handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700506 obj->cookie = 0;
507}
508
509void bio_put_string16(struct binder_io *bio, const uint16_t *str)
510{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000511 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700512 uint16_t *ptr;
513
514 if (!str) {
515 bio_put_uint32(bio, 0xffffffff);
516 return;
517 }
518
519 len = 0;
520 while (str[len]) len++;
521
522 if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
523 bio_put_uint32(bio, 0xffffffff);
524 return;
525 }
526
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000527 /* Note: The payload will carry 32bit size instead of size_t */
528 bio_put_uint32(bio, (uint32_t) len);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700529 len = (len + 1) * sizeof(uint16_t);
530 ptr = bio_alloc(bio, len);
531 if (ptr)
532 memcpy(ptr, str, len);
533}
534
535void bio_put_string16_x(struct binder_io *bio, const char *_str)
536{
537 unsigned char *str = (unsigned char*) _str;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000538 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700539 uint16_t *ptr;
540
541 if (!str) {
542 bio_put_uint32(bio, 0xffffffff);
543 return;
544 }
545
546 len = strlen(_str);
547
548 if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
549 bio_put_uint32(bio, 0xffffffff);
550 return;
551 }
552
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000553 /* Note: The payload will carry 32bit size instead of size_t */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700554 bio_put_uint32(bio, len);
555 ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
556 if (!ptr)
557 return;
558
559 while (*str)
560 *ptr++ = *str++;
561 *ptr++ = 0;
562}
563
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000564static void *bio_get(struct binder_io *bio, size_t size)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700565{
566 size = (size + 3) & (~3);
567
568 if (bio->data_avail < size){
569 bio->data_avail = 0;
570 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000571 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700572 } else {
573 void *ptr = bio->data;
574 bio->data += size;
575 bio->data_avail -= size;
576 return ptr;
577 }
578}
579
580uint32_t bio_get_uint32(struct binder_io *bio)
581{
582 uint32_t *ptr = bio_get(bio, sizeof(*ptr));
583 return ptr ? *ptr : 0;
584}
585
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000586uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700587{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000588 size_t len;
589
590 /* Note: The payload will carry 32bit size instead of size_t */
591 len = (size_t) bio_get_uint32(bio);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700592 if (sz)
593 *sz = len;
594 return bio_get(bio, (len + 1) * sizeof(uint16_t));
595}
596
Serban Constantinescubcf38882014-01-10 13:56:27 +0000597static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700598{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000599 size_t n;
600 size_t off = bio->data - bio->data0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700601
602 /* TODO: be smarter about this? */
603 for (n = 0; n < bio->offs_avail; n++) {
604 if (bio->offs[n] == off)
Serban Constantinescubcf38882014-01-10 13:56:27 +0000605 return bio_get(bio, sizeof(struct flat_binder_object));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700606 }
607
608 bio->data_avail = 0;
609 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000610 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700611}
612
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000613uint32_t bio_get_ref(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700614{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000615 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700616
617 obj = _bio_get_obj(bio);
618 if (!obj)
619 return 0;
620
621 if (obj->type == BINDER_TYPE_HANDLE)
Serban Constantinescubcf38882014-01-10 13:56:27 +0000622 return obj->handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700623
624 return 0;
625}