// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromeos/binder/transaction_data_reader.h" #include #include #include "base/logging.h" #include "chromeos/binder/binder_driver_api.h" #include "chromeos/binder/local_object.h" #include "chromeos/binder/object.h" #include "chromeos/binder/remote_object.h" #include "chromeos/binder/transaction_data.h" namespace binder { namespace { // Adds appropriate padding to the given size to make it 4-byte aligned. size_t AddPadding(size_t n) { return (n + 3) & (~3); } } // namespace TransactionDataReader::TransactionDataReader(const TransactionData& data) : data_(data), reader_(reinterpret_cast(data.GetData()), data.GetDataSize()) {} TransactionDataReader::~TransactionDataReader() {} bool TransactionDataReader::HasMoreData() const { return reader_.HasMoreData(); } bool TransactionDataReader::ReadData(void* buf, size_t n) { DCHECK(buf); return reader_.Read(buf, n) && reader_.Skip(AddPadding(n) - n); } bool TransactionDataReader::ReadInt32(int32_t* value) { return ReadData(value, sizeof(*value)); } bool TransactionDataReader::ReadUint32(uint32_t* value) { return ReadData(value, sizeof(*value)); } bool TransactionDataReader::ReadInt64(int64_t* value) { return ReadData(value, sizeof(*value)); } bool TransactionDataReader::ReadUint64(uint64_t* value) { return ReadData(value, sizeof(*value)); } bool TransactionDataReader::ReadFloat(float* value) { return ReadData(value, sizeof(*value)); } bool TransactionDataReader::ReadDouble(double* value) { return ReadData(value, sizeof(*value)); } bool TransactionDataReader::ReadCString(const char** value) { *value = reader_.current(); for (size_t len = 0; reader_.HasMoreData(); ++len) { char c = 0; if (!reader_.Read(&c, sizeof(c))) { return false; } if (c == 0) { return reader_.Skip(AddPadding(len + 1) - (len + 1)); } } return false; } bool TransactionDataReader::ReadString(std::string* value) { int32_t len = 0; if (!ReadInt32(&len)) { return false; } if (len == 0) { // Read only when the string is not empty. // This is different from ReadString16(). value->clear(); return true; } const char* start = reader_.current(); if (!reader_.Skip(AddPadding(len + 1))) { return false; } value->assign(start, len); return true; } bool TransactionDataReader::ReadString16(base::string16* value) { int32_t len = 0; if (!ReadInt32(&len)) { return false; } const base::char16* start = reinterpret_cast(reader_.current()); if (!reader_.Skip(AddPadding((len + 1) * sizeof(base::char16)))) { return false; } value->assign(start, len); return true; } scoped_refptr TransactionDataReader::ReadObject( CommandBroker* command_broker) { DCHECK(command_broker); flat_binder_object obj = {}; if (!ReadData(&obj, sizeof(obj))) { return scoped_refptr(); } switch (obj.type) { case BINDER_TYPE_HANDLE: return make_scoped_refptr(new RemoteObject(command_broker, obj.handle)); case BINDER_TYPE_BINDER: return make_scoped_refptr(reinterpret_cast(obj.cookie)); } return scoped_refptr(); } bool TransactionDataReader::ReadFileDescriptor(int* fd) { flat_binder_object obj = {}; if (!ReadData(&obj, sizeof(obj)) || obj.type != BINDER_TYPE_FD) { return false; } *fd = obj.handle; return true; } } // namespace binder