19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Copyright 2008 The Android Open Source Project 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/mman.h> 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "binder.h" 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define MAX_BIO_SIZE (1 << 30) 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define TRACE 0 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "Binder" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/log.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_init_from_txn(struct binder_io *io, struct binder_txn *txn); 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if TRACE 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid hexdump(void *_data, unsigned len) 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *data = _data; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned count; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (count = 0; count < len; count++) { 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((count & 15) == 0) 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"%04x:", count); 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr," %02x %c", *data, 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (*data < 32) || (*data > 126) ? '.' : *data); 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data++; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((count & 15) == 15) 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"\n"); 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((count & 15) != 0) 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"\n"); 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_dump_txn(struct binder_txn *txn) 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_object *obj; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned *offs = txn->offs; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned count = txn->offs_size / 4; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr," target %p cookie %p code %08x flags %08x\n", 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project txn->target, txn->cookie, txn->code, txn->flags); 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr," pid %8d uid %8d data %8d offs %8d\n", 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project txn->sender_pid, txn->sender_euid, txn->data_size, txn->offs_size); 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hexdump(txn->data, txn->data_size); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (count--) { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj = (void*) (((char*) txn->data) + *offs++); 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr," - type %08x flags %08x ptr %p cookie %p\n", 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->type, obj->flags, obj->pointer, obj->cookie); 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define NAME(n) case n: return #n 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char *cmd_name(uint32_t cmd) 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch(cmd) { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_NOOP); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_TRANSACTION_COMPLETE); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_INCREFS); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_ACQUIRE); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_RELEASE); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_DECREFS); 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_TRANSACTION); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_REPLY); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_FAILED_REPLY); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_DEAD_REPLY); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NAME(BR_DEAD_BINDER); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: return "???"; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define hexdump(a,b) do{} while (0) 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define binder_dump_txn(txn) do{} while (0) 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_SHARED 0x01 /* needs to be buffer freed */ 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_OVERFLOW 0x02 /* ran out of space */ 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_IOERROR 0x04 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct binder_state 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *mapped; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned mapsize; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct binder_state *binder_open(unsigned mapsize) 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_state *bs; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs = malloc(sizeof(*bs)); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!bs) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project errno = ENOMEM; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs->fd = open("/dev/binder", O_RDWR); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bs->fd < 0) { 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"binder: cannot open device (%s)\n", 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno)); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto fail_open; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs->mapsize = mapsize; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bs->mapped == MAP_FAILED) { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"binder: cannot map device (%s)\n", 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno)); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto fail_map; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* TODO: check version */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bs; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfail_map: 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(bs->fd); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfail_open: 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(bs); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_close(struct binder_state *bs) 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project munmap(bs->mapped, bs->mapsize); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(bs->fd); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(bs); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_become_context_manager(struct binder_state *bs) 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_write(struct binder_state *bs, void *data, unsigned len) 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_write_read bwr; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int res; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_size = len; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_consumed = 0; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_buffer = (unsigned) data; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_size = 0; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_consumed = 0; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_buffer = 0; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res < 0) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"binder_write: ioctl failed (%s)\n", 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno)); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_send_reply(struct binder_state *bs, 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_io *reply, 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buffer_to_free, 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int status) 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd_free; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buffer; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd_reply; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_txn txn; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } __attribute__((packed)) data; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.cmd_free = BC_FREE_BUFFER; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.buffer = buffer_to_free; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.cmd_reply = BC_REPLY; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.target = 0; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.cookie = 0; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.code = 0; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.flags = TF_STATUS_CODE; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.data_size = sizeof(int); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.offs_size = 0; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.data = &status; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.offs = 0; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.flags = 0; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.data_size = reply->data - reply->data0; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.data = reply->data0; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project data.txn.offs = reply->offs0; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_write(bs, &data, sizeof(data)); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_parse(struct binder_state *bs, struct binder_io *bio, 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t *ptr, uint32_t size, binder_handler func) 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int r = 1; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t *end = ptr + (size / 4); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (ptr < end) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd = *ptr++; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if TRACE 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"%s:\n", cmd_name(cmd)); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch(cmd) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_NOOP: 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_TRANSACTION_COMPLETE: 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_INCREFS: 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_ACQUIRE: 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_RELEASE: 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_DECREFS: 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if TRACE 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr," %08x %08x\n", ptr[0], ptr[1]); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr += 2; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_TRANSACTION: { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_txn *txn = (void *) ptr; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) { 2223762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("parse: txn too small!\n"); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_dump_txn(txn); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (func) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned rdata[256/4]; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_io msg; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_io reply; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int res; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_init(&reply, rdata, sizeof(rdata), 4); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_init_from_txn(&msg, txn); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = func(bs, txn, &msg, &reply); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_send_reply(bs, &reply, txn->data, res); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr += sizeof(*txn) / sizeof(uint32_t); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_REPLY: { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_txn *txn = (void*) ptr; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) { 2433762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("parse: reply too small!\n"); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_dump_txn(txn); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bio) { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_init_from_txn(bio, txn); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio = 0; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* todo FREE BUFFER */ 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr += (sizeof(*txn) / sizeof(uint32_t)); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = 0; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_DEAD_BINDER: { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_death *death = (void*) *ptr++; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project death->func(bs, death->ptr); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_FAILED_REPLY: 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = -1; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_DEAD_REPLY: 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = -1; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 2693762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("parse: OOPS %d\n", cmd); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return r; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_acquire(struct binder_state *bs, void *ptr) 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd[2]; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[0] = BC_ACQUIRE; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[1] = (uint32_t) ptr; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_write(bs, cmd, sizeof(cmd)); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_release(struct binder_state *bs, void *ptr) 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd[2]; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[0] = BC_RELEASE; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[1] = (uint32_t) ptr; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_write(bs, cmd, sizeof(cmd)); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death) 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd[3]; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[0] = BC_REQUEST_DEATH_NOTIFICATION; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[1] = (uint32_t) ptr; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[2] = (uint32_t) death; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_write(bs, cmd, sizeof(cmd)); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint binder_call(struct binder_state *bs, 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_io *msg, struct binder_io *reply, 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *target, uint32_t code) 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int res; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_write_read bwr; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct { 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_txn txn; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } writebuf; 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned readbuf[32]; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (msg->flags & BIO_F_OVERFLOW) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"binder: txn buffer overflow\n"); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto fail; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.cmd = BC_TRANSACTION; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.target = target; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.code = code; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.flags = 0; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.data_size = msg->data - msg->data0; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.offs_size = ((char*) msg->offs) - ((char*) msg->offs0); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.data = msg->data0; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writebuf.txn.offs = msg->offs0; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_size = sizeof(writebuf); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_consumed = 0; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_buffer = (unsigned) &writebuf; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hexdump(msg->data0, msg->data - msg->data0); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (;;) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_size = sizeof(readbuf); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_consumed = 0; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_buffer = (unsigned) readbuf; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res < 0) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno)); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto fail; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res == 0) return 0; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res < 0) goto fail; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfail: 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(reply, 0, sizeof(*reply)); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reply->flags |= BIO_F_IOERROR; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_loop(struct binder_state *bs, binder_handler func) 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int res; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_write_read bwr; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned readbuf[32]; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_size = 0; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_consumed = 0; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.write_buffer = 0; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readbuf[0] = BC_ENTER_LOOPER; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_write(bs, readbuf, sizeof(unsigned)); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (;;) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_size = sizeof(readbuf); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_consumed = 0; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bwr.read_buffer = (unsigned) readbuf; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res < 0) { 3783762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res == 0) { 3843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("binder_loop: unexpected reply?!\n"); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res < 0) { 3883762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn) 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data = bio->data0 = txn->data; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->offs = bio->offs0 = txn->offs; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail = txn->data_size; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->offs_avail = txn->offs_size / 4; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags = BIO_F_SHARED; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_init(struct binder_io *bio, void *data, 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t maxdata, uint32_t maxoffs) 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t n = maxoffs * sizeof(uint32_t); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (n > maxdata) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags = BIO_F_OVERFLOW; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail = 0; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->offs_avail = 0; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41577b07ff2c10becd3223c2ed6a6052f61c826b5a1Glenn Kasten bio->data = bio->data0 = (char *) data + n; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->offs = bio->offs0 = data; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail = maxdata - n; 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->offs_avail = maxoffs; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags = 0; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void *bio_alloc(struct binder_io *bio, uint32_t size) 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = (size + 3) & (~3); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (size > bio->data_avail) { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags |= BIO_F_OVERFLOW; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *ptr = bio->data; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data += size; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail -= size; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ptr; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid binder_done(struct binder_state *bs, 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_io *msg, 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_io *reply) 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (reply->flags & BIO_F_SHARED) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t cmd[2]; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[0] = BC_FREE_BUFFER; 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd[1] = (uint32_t) reply->data0; 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder_write(bs, cmd, sizeof(cmd)); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reply->flags = 0; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct binder_object *bio_alloc_obj(struct binder_io *bio) 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_object *obj; 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj = bio_alloc(bio, sizeof(*obj)); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj && bio->offs_avail) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->offs_avail--; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *bio->offs++ = ((char*) obj) - ((char*) bio->data0); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return obj; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags |= BIO_F_OVERFLOW; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_uint32(struct binder_io *bio, uint32_t n) 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t *ptr = bio_alloc(bio, sizeof(n)); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ptr) 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *ptr = n; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_obj(struct binder_io *bio, void *ptr) 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_object *obj; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj = bio_alloc_obj(bio); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!obj) 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->type = BINDER_TYPE_BINDER; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->pointer = ptr; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->cookie = 0; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_ref(struct binder_io *bio, void *ptr) 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_object *obj; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ptr) 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj = bio_alloc_obj(bio); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj = bio_alloc(bio, sizeof(*obj)); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!obj) 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->type = BINDER_TYPE_HANDLE; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->pointer = ptr; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->cookie = 0; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_string16(struct binder_io *bio, const uint16_t *str) 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t len; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint16_t *ptr; 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!str) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_put_uint32(bio, 0xffffffff); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = 0; 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (str[len]) len++; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_put_uint32(bio, 0xffffffff); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_put_uint32(bio, len); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = (len + 1) * sizeof(uint16_t); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr = bio_alloc(bio, len); 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ptr) 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(ptr, str, len); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid bio_put_string16_x(struct binder_io *bio, const char *_str) 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *str = (unsigned char*) _str; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t len; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint16_t *ptr; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!str) { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_put_uint32(bio, 0xffffffff); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = strlen(_str); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_put_uint32(bio, 0xffffffff); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio_put_uint32(bio, len); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t)); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!ptr) 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (*str) 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *ptr++ = *str++; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *ptr++ = 0; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void *bio_get(struct binder_io *bio, uint32_t size) 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = (size + 3) & (~3); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bio->data_avail < size){ 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail = 0; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags |= BIO_F_OVERFLOW; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *ptr = bio->data; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data += size; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail -= size; 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ptr; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t bio_get_uint32(struct binder_io *bio) 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t *ptr = bio_get(bio, sizeof(*ptr)); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ptr ? *ptr : 0; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint16_t *bio_get_string16(struct binder_io *bio, unsigned *sz) 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned len; 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = bio_get_uint32(bio); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sz) 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *sz = len; 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bio_get(bio, (len + 1) * sizeof(uint16_t)); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct binder_object *_bio_get_obj(struct binder_io *bio) 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned n; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned off = bio->data - bio->data0; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* TODO: be smarter about this? */ 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (n = 0; n < bio->offs_avail; n++) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bio->offs[n] == off) 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bio_get(bio, sizeof(struct binder_object)); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->data_avail = 0; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bio->flags |= BIO_F_OVERFLOW; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid *bio_get_ref(struct binder_io *bio) 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct binder_object *obj; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj = _bio_get_obj(bio); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!obj) 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj->type == BINDER_TYPE_HANDLE) 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return obj->pointer; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 617