|  | /* | 
|  | * Copyright (C) 2016 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  | #define LOG_TAG "HidlSupport" | 
|  |  | 
|  | #include <hidl/HidlSupport.h> | 
|  |  | 
|  | #include <unordered_map> | 
|  |  | 
|  | #include <android-base/logging.h> | 
|  | #include <android-base/parseint.h> | 
|  |  | 
|  | namespace android { | 
|  | namespace hardware { | 
|  |  | 
|  | namespace details { | 
|  | bool debuggable() { | 
|  | #ifdef LIBHIDL_TARGET_DEBUGGABLE | 
|  | return true; | 
|  | #else | 
|  | return false; | 
|  | #endif | 
|  | } | 
|  | }  // namespace details | 
|  |  | 
|  | hidl_handle::hidl_handle() { | 
|  | mHandle = nullptr; | 
|  | mOwnsHandle = false; | 
|  | } | 
|  |  | 
|  | hidl_handle::~hidl_handle() { | 
|  | freeHandle(); | 
|  | } | 
|  |  | 
|  | hidl_handle::hidl_handle(const native_handle_t *handle) { | 
|  | mHandle = handle; | 
|  | mOwnsHandle = false; | 
|  | } | 
|  |  | 
|  | // copy constructor. | 
|  | hidl_handle::hidl_handle(const hidl_handle &other) { | 
|  | mOwnsHandle = false; | 
|  | *this = other; | 
|  | } | 
|  |  | 
|  | // move constructor. | 
|  | hidl_handle::hidl_handle(hidl_handle &&other) { | 
|  | mOwnsHandle = false; | 
|  | *this = std::move(other); | 
|  | } | 
|  |  | 
|  | // assignment operators | 
|  | hidl_handle &hidl_handle::operator=(const hidl_handle &other) { | 
|  | if (this == &other) { | 
|  | return *this; | 
|  | } | 
|  | freeHandle(); | 
|  | if (other.mHandle != nullptr) { | 
|  | mHandle = native_handle_clone(other.mHandle); | 
|  | if (mHandle == nullptr) { | 
|  | PLOG(FATAL) << "Failed to clone native_handle in hidl_handle"; | 
|  | } | 
|  | mOwnsHandle = true; | 
|  | } else { | 
|  | mHandle = nullptr; | 
|  | mOwnsHandle = false; | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | hidl_handle &hidl_handle::operator=(const native_handle_t *native_handle) { | 
|  | freeHandle(); | 
|  | mHandle = native_handle; | 
|  | mOwnsHandle = false; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | hidl_handle &hidl_handle::operator=(hidl_handle &&other) { | 
|  | if (this != &other) { | 
|  | freeHandle(); | 
|  | mHandle = other.mHandle; | 
|  | mOwnsHandle = other.mOwnsHandle; | 
|  | other.mHandle = nullptr; | 
|  | other.mOwnsHandle = false; | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | void hidl_handle::setTo(native_handle_t* handle, bool shouldOwn) { | 
|  | freeHandle(); | 
|  | mHandle = handle; | 
|  | mOwnsHandle = shouldOwn; | 
|  | } | 
|  |  | 
|  | const native_handle_t* hidl_handle::operator->() const { | 
|  | return mHandle; | 
|  | } | 
|  |  | 
|  | // implicit conversion to const native_handle_t* | 
|  | hidl_handle::operator const native_handle_t *() const { | 
|  | return mHandle; | 
|  | } | 
|  |  | 
|  | // explicit conversion | 
|  | const native_handle_t *hidl_handle::getNativeHandle() const { | 
|  | return mHandle; | 
|  | } | 
|  |  | 
|  | void hidl_handle::freeHandle() { | 
|  | if (mOwnsHandle && mHandle != nullptr) { | 
|  | // This can only be true if: | 
|  | // 1. Somebody called setTo() with shouldOwn=true, so we know the handle | 
|  | //    wasn't const to begin with. | 
|  | // 2. Copy/assignment from another hidl_handle, in which case we have | 
|  | //    cloned the handle. | 
|  | // 3. Move constructor from another hidl_handle, in which case the original | 
|  | //    hidl_handle must have been non-const as well. | 
|  | native_handle_t *handle = const_cast<native_handle_t*>( | 
|  | static_cast<const native_handle_t*>(mHandle)); | 
|  | native_handle_close(handle); | 
|  | native_handle_delete(handle); | 
|  | mHandle = nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | static const char *const kEmptyString = ""; | 
|  |  | 
|  | hidl_string::hidl_string() | 
|  | : mBuffer(kEmptyString), | 
|  | mSize(0), | 
|  | mOwnsBuffer(false) { | 
|  | } | 
|  |  | 
|  | hidl_string::~hidl_string() { | 
|  | clear(); | 
|  | } | 
|  |  | 
|  | hidl_string::hidl_string(const char *s) : hidl_string() { | 
|  | if (s == nullptr) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | copyFrom(s, strlen(s)); | 
|  | } | 
|  |  | 
|  | hidl_string::hidl_string(const char *s, size_t length) : hidl_string() { | 
|  | copyFrom(s, length); | 
|  | } | 
|  |  | 
|  | hidl_string::hidl_string(const hidl_string &other): hidl_string() { | 
|  | copyFrom(other.c_str(), other.size()); | 
|  | } | 
|  |  | 
|  | hidl_string::hidl_string(const std::string &s) : hidl_string() { | 
|  | copyFrom(s.c_str(), s.size()); | 
|  | } | 
|  |  | 
|  | hidl_string::hidl_string(hidl_string &&other): hidl_string() { | 
|  | moveFrom(std::forward<hidl_string>(other)); | 
|  | } | 
|  |  | 
|  | hidl_string &hidl_string::operator=(hidl_string &&other) { | 
|  | if (this != &other) { | 
|  | clear(); | 
|  | moveFrom(std::forward<hidl_string>(other)); | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | hidl_string &hidl_string::operator=(const hidl_string &other) { | 
|  | if (this != &other) { | 
|  | clear(); | 
|  | copyFrom(other.c_str(), other.size()); | 
|  | } | 
|  |  | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | hidl_string &hidl_string::operator=(const char *s) { | 
|  | clear(); | 
|  |  | 
|  | if (s == nullptr) { | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | copyFrom(s, strlen(s)); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | hidl_string &hidl_string::operator=(const std::string &s) { | 
|  | clear(); | 
|  | copyFrom(s.c_str(), s.size()); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | hidl_string::operator std::string() const { | 
|  | return std::string(mBuffer, mSize); | 
|  | } | 
|  |  | 
|  | std::ostream& operator<<(std::ostream& os, const hidl_string& str) { | 
|  | os << str.c_str(); | 
|  | return os; | 
|  | } | 
|  |  | 
|  | void hidl_string::copyFrom(const char *data, size_t size) { | 
|  | // assume my resources are freed. | 
|  |  | 
|  | if (size >= UINT32_MAX) { | 
|  | LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size; | 
|  | } | 
|  | char *buf = (char *)malloc(size + 1); | 
|  | memcpy(buf, data, size); | 
|  | buf[size] = '\0'; | 
|  | mBuffer = buf; | 
|  |  | 
|  | mSize = static_cast<uint32_t>(size); | 
|  | mOwnsBuffer = true; | 
|  | } | 
|  |  | 
|  | void hidl_string::moveFrom(hidl_string &&other) { | 
|  | // assume my resources are freed. | 
|  |  | 
|  | mBuffer = std::move(other.mBuffer); | 
|  | mSize = other.mSize; | 
|  | mOwnsBuffer = other.mOwnsBuffer; | 
|  |  | 
|  | other.mOwnsBuffer = false; | 
|  | other.clear(); | 
|  | } | 
|  |  | 
|  | void hidl_string::clear() { | 
|  | if (mOwnsBuffer && (mBuffer != kEmptyString)) { | 
|  | free(const_cast<char *>(static_cast<const char *>(mBuffer))); | 
|  | } | 
|  |  | 
|  | mBuffer = kEmptyString; | 
|  | mSize = 0; | 
|  | mOwnsBuffer = false; | 
|  | } | 
|  |  | 
|  | void hidl_string::setToExternal(const char *data, size_t size) { | 
|  | if (size > UINT32_MAX) { | 
|  | LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size; | 
|  | } | 
|  | clear(); | 
|  |  | 
|  | mBuffer = data; | 
|  | mSize = static_cast<uint32_t>(size); | 
|  | mOwnsBuffer = false; | 
|  | } | 
|  |  | 
|  | const char *hidl_string::c_str() const { | 
|  | return mBuffer; | 
|  | } | 
|  |  | 
|  | size_t hidl_string::size() const { | 
|  | return mSize; | 
|  | } | 
|  |  | 
|  | bool hidl_string::empty() const { | 
|  | return mSize == 0; | 
|  | } | 
|  |  | 
|  | sp<HidlMemory> HidlMemory::getInstance(const hidl_memory& mem) { | 
|  | sp<HidlMemory> instance = new HidlMemory(); | 
|  | instance->hidl_memory::operator=(mem); | 
|  | return instance; | 
|  | } | 
|  |  | 
|  | sp<HidlMemory> HidlMemory::getInstance(hidl_memory&& mem) { | 
|  | sp<HidlMemory> instance = new HidlMemory(); | 
|  | instance->hidl_memory::operator=(std::move(mem)); | 
|  | return instance; | 
|  | } | 
|  |  | 
|  | sp<HidlMemory> HidlMemory::getInstance(const hidl_string& name, int fd, uint64_t size) { | 
|  | native_handle_t* handle = native_handle_create(1, 0); | 
|  | if (!handle) { | 
|  | close(fd); | 
|  | LOG(ERROR) << "native_handle_create fails"; | 
|  | return new HidlMemory(); | 
|  | } | 
|  | handle->data[0] = fd; | 
|  |  | 
|  | hidl_handle hidlHandle; | 
|  | hidlHandle.setTo(handle, true /* shouldOwn */); | 
|  |  | 
|  | sp<HidlMemory> instance = new HidlMemory(name, std::move(hidlHandle), size); | 
|  | return instance; | 
|  | } | 
|  |  | 
|  | HidlMemory::HidlMemory() : hidl_memory() {} | 
|  |  | 
|  | HidlMemory::HidlMemory(const hidl_string& name, hidl_handle&& handle, size_t size) | 
|  | : hidl_memory(name, std::move(handle), size) {} | 
|  |  | 
|  | // it's required to have at least one out-of-line method to avoid weak vtable | 
|  | HidlMemory::~HidlMemory() { | 
|  | hidl_memory::~hidl_memory(); | 
|  | } | 
|  |  | 
|  | }  // namespace hardware | 
|  | }  // namespace android | 
|  |  | 
|  |  |