// 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/writable_transaction_data.h" #include "chromeos/binder/binder_driver_api.h" #include "chromeos/binder/constants.h" #include "chromeos/binder/local_object.h" #include "chromeos/binder/object.h" #include "chromeos/binder/remote_object.h" namespace binder { WritableTransactionData::WritableTransactionData() {} WritableTransactionData::~WritableTransactionData() {} uintptr_t WritableTransactionData::GetCookie() const { return 0; } uint32_t WritableTransactionData::GetCode() const { return code_; } pid_t WritableTransactionData::GetSenderPID() const { return 0; } uid_t WritableTransactionData::GetSenderEUID() const { return 0; } bool WritableTransactionData::IsOneWay() const { return is_one_way_; } bool WritableTransactionData::HasStatus() const { return false; } Status WritableTransactionData::GetStatus() const { return Status::OK; } const void* WritableTransactionData::GetData() const { return data_.data(); } size_t WritableTransactionData::GetDataSize() const { return data_.size(); } const binder_uintptr_t* WritableTransactionData::GetObjectOffsets() const { return object_offsets_.data(); } size_t WritableTransactionData::GetNumObjectOffsets() const { return object_offsets_.size(); } void WritableTransactionData::Reserve(size_t n) { data_.reserve(n); } void WritableTransactionData::WriteData(const void* data, size_t n) { data_.insert(data_.end(), static_cast(data), static_cast(data) + n); if (n % 4 != 0) { // Add padding. data_.resize(data_.size() + 4 - (n % 4)); } } void WritableTransactionData::WriteInt32(int32_t value) { WriteData(&value, sizeof(value)); } void WritableTransactionData::WriteUint32(uint32_t value) { WriteData(&value, sizeof(value)); } void WritableTransactionData::WriteInt64(int64_t value) { WriteData(&value, sizeof(value)); } void WritableTransactionData::WriteUint64(uint64_t value) { WriteData(&value, sizeof(value)); } void WritableTransactionData::WriteFloat(float value) { WriteData(&value, sizeof(value)); } void WritableTransactionData::WriteDouble(double value) { WriteData(&value, sizeof(value)); } void WritableTransactionData::WriteCString(const char* value) { WriteData(value, strlen(value) + 1); } void WritableTransactionData::WriteString(const std::string& value) { WriteInt32(value.size()); if (value.size() > 0) { // Write only when the string is not empty. // This is different from WriteString16(). // // Despite having the length info, null-terminate the data to be consistent // with libbinder. WriteData(value.c_str(), value.size() + 1); } } void WritableTransactionData::WriteString16(const base::string16& value) { WriteInt32(value.size()); // Despite having the length info, null-terminate the data to be consistent // with libbinder. WriteData(value.c_str(), (value.size() + 1) * sizeof(base::char16)); } void WritableTransactionData::WriteInterfaceToken( const base::string16& interface, int32_t strict_mode_policy) { WriteInt32(kStrictModePenaltyGather | strict_mode_policy); WriteString16(interface); } void WritableTransactionData::WriteObject(scoped_refptr object) { objects_.push_back(object); // Hold reference. flat_binder_object flat = {}; flat.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; switch (object->GetType()) { case Object::TYPE_LOCAL: { auto* local = static_cast(object.get()); flat.type = BINDER_TYPE_BINDER; flat.cookie = reinterpret_cast(local); // flat.binder is unused, but the driver requires it to be a non-zero // unique value. flat.binder = reinterpret_cast(local); break; } case Object::TYPE_REMOTE: { auto* remote = static_cast(object.get()); flat.type = BINDER_TYPE_HANDLE; flat.handle = remote->GetHandle(); break; } } object_offsets_.push_back(data_.size()); WriteData(&flat, sizeof(flat)); } void WritableTransactionData::WriteFileDescriptor(base::ScopedFD fd) { files_.push_back(std::move(fd)); flat_binder_object flat = {}; flat.type = BINDER_TYPE_FD; flat.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; flat.handle = files_.back().get(); object_offsets_.push_back(data_.size()); WriteData(&flat, sizeof(flat)); } } // namespace binder