upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
53
android/system/libhidl/base/Android.bp
Normal file
53
android/system/libhidl/base/Android.bp
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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.
|
||||
|
||||
cc_library_shared {
|
||||
name: "libhidlbase",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
cflags: libhidl_flags,
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libutils",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libutils",
|
||||
"libcutils", // for native_handle.h
|
||||
],
|
||||
local_include_dirs: ["include"],
|
||||
export_include_dirs: ["include"],
|
||||
|
||||
clang: true,
|
||||
sanitize: {
|
||||
misc_undefined: ["integer"],
|
||||
},
|
||||
|
||||
srcs: [
|
||||
"HidlInternal.cpp",
|
||||
"HidlSupport.cpp",
|
||||
"Status.cpp",
|
||||
"TaskRunner.cpp",
|
||||
],
|
||||
|
||||
product_variables: {
|
||||
debuggable: {
|
||||
cflags: ["-DLIBHIDL_TARGET_DEBUGGABLE"],
|
||||
},
|
||||
},
|
||||
}
|
162
android/system/libhidl/base/HidlInternal.cpp
Normal file
162
android/system/libhidl/base/HidlInternal.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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 "HidlInternal"
|
||||
|
||||
#include <hidl/HidlInternal.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#ifdef LIBHIDL_TARGET_DEBUGGABLE
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <regex>
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace details {
|
||||
|
||||
void logAlwaysFatal(const char *message) {
|
||||
LOG(FATAL) << message;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// HidlInstrumentor implementation.
|
||||
HidlInstrumentor::HidlInstrumentor(const std::string& package, const std::string& interface)
|
||||
: mEnableInstrumentation(false),
|
||||
mInstrumentationLibPackage(package),
|
||||
mInterfaceName(interface) {
|
||||
configureInstrumentation(false);
|
||||
}
|
||||
|
||||
HidlInstrumentor:: ~HidlInstrumentor() {}
|
||||
|
||||
void HidlInstrumentor::configureInstrumentation(bool log) {
|
||||
bool enableInstrumentation = property_get_bool(
|
||||
"hal.instrumentation.enable",
|
||||
false);
|
||||
if (enableInstrumentation != mEnableInstrumentation) {
|
||||
mEnableInstrumentation = enableInstrumentation;
|
||||
if (mEnableInstrumentation) {
|
||||
if (log) {
|
||||
LOG(INFO) << "Enable instrumentation.";
|
||||
}
|
||||
registerInstrumentationCallbacks (&mInstrumentationCallbacks);
|
||||
} else {
|
||||
if (log) {
|
||||
LOG(INFO) << "Disable instrumentation.";
|
||||
}
|
||||
mInstrumentationCallbacks.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HidlInstrumentor::registerInstrumentationCallbacks(
|
||||
std::vector<InstrumentationCallback> *instrumentationCallbacks) {
|
||||
#ifdef LIBHIDL_TARGET_DEBUGGABLE
|
||||
std::vector<std::string> instrumentationLibPaths;
|
||||
char instrumentationLibPath[PROPERTY_VALUE_MAX];
|
||||
if (property_get("hal.instrumentation.lib.path",
|
||||
instrumentationLibPath,
|
||||
"") > 0) {
|
||||
instrumentationLibPaths.push_back(instrumentationLibPath);
|
||||
} else {
|
||||
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
|
||||
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VNDK_SP);
|
||||
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
|
||||
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
|
||||
}
|
||||
|
||||
for (auto path : instrumentationLibPaths) {
|
||||
DIR *dir = opendir(path.c_str());
|
||||
if (dir == 0) {
|
||||
LOG(WARNING) << path << " does not exist. ";
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *file;
|
||||
while ((file = readdir(dir)) != NULL) {
|
||||
if (!isInstrumentationLib(file))
|
||||
continue;
|
||||
|
||||
void *handle = dlopen((path + file->d_name).c_str(), RTLD_NOW);
|
||||
char *error;
|
||||
if (handle == nullptr) {
|
||||
LOG(WARNING) << "couldn't load file: " << file->d_name
|
||||
<< " error: " << dlerror();
|
||||
continue;
|
||||
}
|
||||
|
||||
dlerror(); /* Clear any existing error */
|
||||
|
||||
using cbFun = void (*)(
|
||||
const InstrumentationEvent,
|
||||
const char *,
|
||||
const char *,
|
||||
const char *,
|
||||
const char *,
|
||||
std::vector<void *> *);
|
||||
std::string package = mInstrumentationLibPackage;
|
||||
for (size_t i = 0; i < package.size(); i++) {
|
||||
if (package[i] == '.') {
|
||||
package[i] = '_';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (package[i] == '@') {
|
||||
package[i] = '_';
|
||||
package.insert(i + 1, "V");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto cb = (cbFun)dlsym(handle, ("HIDL_INSTRUMENTATION_FUNCTION_"
|
||||
+ package + "_" + mInterfaceName).c_str());
|
||||
if ((error = dlerror()) != NULL) {
|
||||
LOG(WARNING)
|
||||
<< "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_"
|
||||
<< package << "_" << mInterfaceName << ", error: " << error;
|
||||
continue;
|
||||
}
|
||||
instrumentationCallbacks->push_back(cb);
|
||||
LOG(INFO) << "Register instrumentation callback from "
|
||||
<< file->d_name;
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
#else
|
||||
// No-op for user builds.
|
||||
(void) instrumentationCallbacks;
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool HidlInstrumentor::isInstrumentationLib(const dirent *file) {
|
||||
#ifdef LIBHIDL_TARGET_DEBUGGABLE
|
||||
if (file->d_type != DT_REG) return false;
|
||||
std::cmatch cm;
|
||||
std::regex e("^" + mInstrumentationLibPackage + "(.*).profiler.so$");
|
||||
if (std::regex_match(file->d_name, cm, e)) return true;
|
||||
#else
|
||||
(void) file;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace hardware
|
||||
} // namespace android
|
279
android/system/libhidl/base/HidlSupport.cpp
Normal file
279
android/system/libhidl/base/HidlSupport.cpp
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
|
165
android/system/libhidl/base/Status.cpp
Normal file
165
android/system/libhidl/base/Status.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 "HidlStatus"
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <hidl/Status.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
||||
static std::string statusToString(status_t s) {
|
||||
const std::unordered_map<status_t, std::string> statusStrings{{
|
||||
#define STATUS_TO_STRING_PAIR(STATUS) {STATUS, #STATUS}
|
||||
STATUS_TO_STRING_PAIR(OK),
|
||||
STATUS_TO_STRING_PAIR(UNKNOWN_ERROR),
|
||||
STATUS_TO_STRING_PAIR(NO_MEMORY),
|
||||
STATUS_TO_STRING_PAIR(INVALID_OPERATION),
|
||||
STATUS_TO_STRING_PAIR(BAD_VALUE),
|
||||
STATUS_TO_STRING_PAIR(BAD_TYPE),
|
||||
STATUS_TO_STRING_PAIR(NAME_NOT_FOUND),
|
||||
STATUS_TO_STRING_PAIR(PERMISSION_DENIED),
|
||||
STATUS_TO_STRING_PAIR(NO_INIT),
|
||||
STATUS_TO_STRING_PAIR(ALREADY_EXISTS),
|
||||
STATUS_TO_STRING_PAIR(DEAD_OBJECT),
|
||||
STATUS_TO_STRING_PAIR(FAILED_TRANSACTION),
|
||||
STATUS_TO_STRING_PAIR(BAD_INDEX),
|
||||
STATUS_TO_STRING_PAIR(NOT_ENOUGH_DATA),
|
||||
STATUS_TO_STRING_PAIR(WOULD_BLOCK),
|
||||
STATUS_TO_STRING_PAIR(TIMED_OUT),
|
||||
STATUS_TO_STRING_PAIR(UNKNOWN_TRANSACTION),
|
||||
STATUS_TO_STRING_PAIR(FDS_NOT_ALLOWED),
|
||||
STATUS_TO_STRING_PAIR(UNEXPECTED_NULL)
|
||||
}};
|
||||
auto it = statusStrings.find(s);
|
||||
if (it != statusStrings.end()) {
|
||||
return it->second;
|
||||
}
|
||||
std::string str = std::to_string(s);
|
||||
char *err = strerror(-s);
|
||||
if (err != NULL) {
|
||||
str.append(1, ' ').append(err);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static std::string exceptionToString(int32_t ex) {
|
||||
const std::unordered_map<int32_t, std::string> exceptionStrings{{
|
||||
#define EXCEPTION_TO_STRING_PAIR(EXCEPTION) {Status::Exception::EXCEPTION, #EXCEPTION}
|
||||
EXCEPTION_TO_STRING_PAIR(EX_NONE),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_SECURITY),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_BAD_PARCELABLE),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_ARGUMENT),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_NULL_POINTER),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_ILLEGAL_STATE),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_NETWORK_MAIN_THREAD),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_UNSUPPORTED_OPERATION),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_HAS_REPLY_HEADER),
|
||||
EXCEPTION_TO_STRING_PAIR(EX_TRANSACTION_FAILED)
|
||||
}};
|
||||
auto it = exceptionStrings.find(ex);
|
||||
return it == exceptionStrings.end() ? std::to_string(ex) : it->second;
|
||||
}
|
||||
|
||||
Status Status::ok() {
|
||||
return Status();
|
||||
}
|
||||
|
||||
Status Status::fromExceptionCode(int32_t exceptionCode) {
|
||||
return Status(exceptionCode, OK);
|
||||
}
|
||||
|
||||
Status Status::fromExceptionCode(int32_t exceptionCode,
|
||||
const char *message) {
|
||||
return Status(exceptionCode, OK, message);
|
||||
}
|
||||
|
||||
Status Status::fromStatusT(status_t status) {
|
||||
Status ret;
|
||||
ret.setFromStatusT(status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Status::Status(int32_t exceptionCode, int32_t errorCode)
|
||||
: mException(exceptionCode),
|
||||
mErrorCode(errorCode) {}
|
||||
|
||||
Status::Status(int32_t exceptionCode, int32_t errorCode, const char *message)
|
||||
: mException(exceptionCode),
|
||||
mErrorCode(errorCode),
|
||||
mMessage(message) {}
|
||||
|
||||
void Status::setException(int32_t ex, const char *message) {
|
||||
mException = ex;
|
||||
mErrorCode = NO_ERROR; // an exception, not a transaction failure.
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
void Status::setFromStatusT(status_t status) {
|
||||
mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
|
||||
mErrorCode = status;
|
||||
mMessage.clear();
|
||||
}
|
||||
|
||||
std::string Status::description() const {
|
||||
std::ostringstream oss;
|
||||
oss << (*this);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream& stream, const Status& s) {
|
||||
if (s.exceptionCode() == Status::EX_NONE) {
|
||||
stream << "No error";
|
||||
} else {
|
||||
stream << "Status(" << exceptionToString(s.exceptionCode()) << "): '";
|
||||
if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
|
||||
stream << statusToString(s.transactionError()) << ": ";
|
||||
}
|
||||
stream << s.exceptionMessage() << "'";
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
namespace details {
|
||||
void return_status::assertOk() const {
|
||||
if (!isOk()) {
|
||||
LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description();
|
||||
}
|
||||
}
|
||||
|
||||
return_status::~return_status() {
|
||||
// mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
|
||||
if (!mCheckedStatus && !isOk()) {
|
||||
LOG(FATAL) << "Failed HIDL return status not checked: " << description();
|
||||
}
|
||||
}
|
||||
|
||||
return_status &return_status::operator=(return_status &&other) {
|
||||
if (!mCheckedStatus && !isOk()) {
|
||||
LOG(FATAL) << "Failed HIDL return status not checked: " << description();
|
||||
}
|
||||
std::swap(mStatus, other.mStatus);
|
||||
std::swap(mCheckedStatus, other.mCheckedStatus);
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace hardware
|
||||
} // namespace android
|
53
android/system/libhidl/base/TaskRunner.cpp
Normal file
53
android/system/libhidl/base/TaskRunner.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <hidl/TaskRunner.h>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace details {
|
||||
|
||||
TaskRunner::TaskRunner() {
|
||||
}
|
||||
|
||||
void TaskRunner::start(size_t limit) {
|
||||
mQueue = std::make_shared<SynchronizedQueue<Task>>(limit);
|
||||
|
||||
// Allow the thread to continue running in background;
|
||||
// TaskRunner do not care about the std::thread object.
|
||||
std::thread{[q = mQueue] {
|
||||
Task nextTask;
|
||||
while (!!(nextTask = q->wait_pop())) {
|
||||
nextTask();
|
||||
}
|
||||
}}.detach();
|
||||
}
|
||||
|
||||
TaskRunner::~TaskRunner() {
|
||||
if (mQueue) {
|
||||
mQueue->push(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool TaskRunner::push(const Task &t) {
|
||||
return (mQueue != nullptr) && (!!t) && this->mQueue->push(t);
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
191
android/system/libhidl/base/include/hidl/HidlInternal.h
Normal file
191
android/system/libhidl/base/include/hidl/HidlInternal.h
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HIDL_INTERNAL_H
|
||||
#define ANDROID_HIDL_INTERNAL_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <dirent.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace details {
|
||||
|
||||
//Templated classes can use the below method
|
||||
//to avoid creating dependencies on liblog.
|
||||
void logAlwaysFatal(const char *message);
|
||||
|
||||
// HIDL client/server code should *NOT* use this class.
|
||||
//
|
||||
// hidl_pointer wraps a pointer without taking ownership,
|
||||
// and stores it in a union with a uint64_t. This ensures
|
||||
// that we always have enough space to store a pointer,
|
||||
// regardless of whether we're running in a 32-bit or 64-bit
|
||||
// process.
|
||||
template<typename T>
|
||||
struct hidl_pointer {
|
||||
hidl_pointer()
|
||||
: _pad(0) {
|
||||
}
|
||||
hidl_pointer(T* ptr) : hidl_pointer() { mPointer = ptr; }
|
||||
hidl_pointer(const hidl_pointer<T>& other) : hidl_pointer() { mPointer = other.mPointer; }
|
||||
hidl_pointer(hidl_pointer<T>&& other) : hidl_pointer() { *this = std::move(other); }
|
||||
|
||||
hidl_pointer &operator=(const hidl_pointer<T>& other) {
|
||||
mPointer = other.mPointer;
|
||||
return *this;
|
||||
}
|
||||
hidl_pointer &operator=(hidl_pointer<T>&& other) {
|
||||
mPointer = other.mPointer;
|
||||
other.mPointer = nullptr;
|
||||
return *this;
|
||||
}
|
||||
hidl_pointer &operator=(T* ptr) {
|
||||
mPointer = ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T*() const {
|
||||
return mPointer;
|
||||
}
|
||||
explicit operator void*() const { // requires explicit cast to avoid ambiguity
|
||||
return mPointer;
|
||||
}
|
||||
T& operator*() const {
|
||||
return *mPointer;
|
||||
}
|
||||
T* operator->() const {
|
||||
return mPointer;
|
||||
}
|
||||
T &operator[](size_t index) {
|
||||
return mPointer[index];
|
||||
}
|
||||
const T &operator[](size_t index) const {
|
||||
return mPointer[index];
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
T* mPointer;
|
||||
uint64_t _pad;
|
||||
};
|
||||
};
|
||||
|
||||
#define HAL_LIBRARY_PATH_SYSTEM_64BIT "/system/lib64/hw/"
|
||||
#define HAL_LIBRARY_PATH_VNDK_SP_64BIT "/system/lib64/vndk-sp/hw/"
|
||||
#define HAL_LIBRARY_PATH_VENDOR_64BIT "/vendor/lib64/hw/"
|
||||
#define HAL_LIBRARY_PATH_ODM_64BIT "/odm/lib64/hw/"
|
||||
#define HAL_LIBRARY_PATH_SYSTEM_32BIT "/system/lib/hw/"
|
||||
#define HAL_LIBRARY_PATH_VNDK_SP_32BIT "/system/lib/vndk-sp/hw/"
|
||||
#define HAL_LIBRARY_PATH_VENDOR_32BIT "/vendor/lib/hw/"
|
||||
#define HAL_LIBRARY_PATH_ODM_32BIT "/odm/lib/hw/"
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define HAL_LIBRARY_PATH_SYSTEM HAL_LIBRARY_PATH_SYSTEM_64BIT
|
||||
#define HAL_LIBRARY_PATH_VNDK_SP HAL_LIBRARY_PATH_VNDK_SP_64BIT
|
||||
#define HAL_LIBRARY_PATH_VENDOR HAL_LIBRARY_PATH_VENDOR_64BIT
|
||||
#define HAL_LIBRARY_PATH_ODM HAL_LIBRARY_PATH_ODM_64BIT
|
||||
#else
|
||||
#define HAL_LIBRARY_PATH_SYSTEM HAL_LIBRARY_PATH_SYSTEM_32BIT
|
||||
#define HAL_LIBRARY_PATH_VNDK_SP HAL_LIBRARY_PATH_VNDK_SP_32BIT
|
||||
#define HAL_LIBRARY_PATH_VENDOR HAL_LIBRARY_PATH_VENDOR_32BIT
|
||||
#define HAL_LIBRARY_PATH_ODM HAL_LIBRARY_PATH_ODM_32BIT
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Class that provides Hidl instrumentation utilities.
|
||||
struct HidlInstrumentor {
|
||||
// Event that triggers the instrumentation. e.g. enter of an API call on
|
||||
// the server/client side, exit of an API call on the server/client side
|
||||
// etc.
|
||||
enum InstrumentationEvent {
|
||||
SERVER_API_ENTRY = 0,
|
||||
SERVER_API_EXIT,
|
||||
CLIENT_API_ENTRY,
|
||||
CLIENT_API_EXIT,
|
||||
SYNC_CALLBACK_ENTRY,
|
||||
SYNC_CALLBACK_EXIT,
|
||||
ASYNC_CALLBACK_ENTRY,
|
||||
ASYNC_CALLBACK_EXIT,
|
||||
PASSTHROUGH_ENTRY,
|
||||
PASSTHROUGH_EXIT,
|
||||
};
|
||||
|
||||
// Signature of the instrumentation callback function.
|
||||
using InstrumentationCallback = std::function<void(
|
||||
const InstrumentationEvent event,
|
||||
const char *package,
|
||||
const char *version,
|
||||
const char *interface,
|
||||
const char *method,
|
||||
std::vector<void *> *args)>;
|
||||
|
||||
explicit HidlInstrumentor(
|
||||
const std::string &package,
|
||||
const std::string &insterface);
|
||||
virtual ~HidlInstrumentor();
|
||||
|
||||
public:
|
||||
const std::vector<InstrumentationCallback>& getInstrumentationCallbacks() {
|
||||
return mInstrumentationCallbacks;
|
||||
}
|
||||
bool isInstrumentationEnabled() { return mEnableInstrumentation; }
|
||||
|
||||
protected:
|
||||
// Set mEnableInstrumentation based on system property
|
||||
// hal.instrumentation.enable, register/de-register instrumentation
|
||||
// callbacks if mEnableInstrumentation is true/false.
|
||||
void configureInstrumentation(bool log=true);
|
||||
// Function that lookup and dynamically loads the hidl instrumentation
|
||||
// libraries and registers the instrumentation callback functions.
|
||||
//
|
||||
// The instrumentation libraries should be stored under any of the following
|
||||
// directories: HAL_LIBRARY_PATH_SYSTEM, HAL_LIBRARY_PATH_VNDK_SP,
|
||||
// HAL_LIBRARY_PATH_VENDOR and HAL_LIBRARY_PATH_ODM.
|
||||
// The name of instrumentation libraries should follow pattern:
|
||||
// ^profilerPrefix(.*).profiler.so$
|
||||
//
|
||||
// Each instrumentation library is expected to implement the instrumentation
|
||||
// function called HIDL_INSTRUMENTATION_FUNCTION.
|
||||
//
|
||||
// A no-op for user build.
|
||||
void registerInstrumentationCallbacks(
|
||||
std::vector<InstrumentationCallback> *instrumentationCallbacks);
|
||||
|
||||
// Utility function to determine whether a give file is a instrumentation
|
||||
// library (i.e. the file name follow the expected pattern).
|
||||
bool isInstrumentationLib(const dirent *file);
|
||||
|
||||
// A list of registered instrumentation callbacks.
|
||||
std::vector<InstrumentationCallback> mInstrumentationCallbacks;
|
||||
// Flag whether to enable instrumentation.
|
||||
bool mEnableInstrumentation;
|
||||
// Prefix to lookup the instrumentation libraries.
|
||||
std::string mInstrumentationLibPackage;
|
||||
// Used for dlsym to load the profiling method for given interface.
|
||||
std::string mInterfaceName;
|
||||
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HIDL_INTERNAL_H
|
952
android/system/libhidl/base/include/hidl/HidlSupport.h
Normal file
952
android/system/libhidl/base/include/hidl/HidlSupport.h
Normal file
|
@ -0,0 +1,952 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HIDL_SUPPORT_H
|
||||
#define ANDROID_HIDL_SUPPORT_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
#include <cutils/native_handle.h>
|
||||
#include <hidl/HidlInternal.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <stddef.h>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
|
||||
// this file is included by all hidl interface, so we must forward declare the
|
||||
// IMemory and IBase types.
|
||||
namespace hidl {
|
||||
namespace memory {
|
||||
namespace V1_0 {
|
||||
struct IMemory;
|
||||
}; // namespace V1_0
|
||||
}; // namespace manager
|
||||
}; // namespace hidl
|
||||
|
||||
namespace hidl {
|
||||
namespace base {
|
||||
namespace V1_0 {
|
||||
struct IBase;
|
||||
}; // namespace V1_0
|
||||
}; // namespace base
|
||||
}; // namespace hidl
|
||||
|
||||
namespace hardware {
|
||||
|
||||
namespace details {
|
||||
// Return true on userdebug / eng builds and false on user builds.
|
||||
bool debuggable();
|
||||
} // namespace details
|
||||
|
||||
// hidl_death_recipient is a callback interfaced that can be used with
|
||||
// linkToDeath() / unlinkToDeath()
|
||||
struct hidl_death_recipient : public virtual RefBase {
|
||||
virtual void serviceDied(uint64_t cookie,
|
||||
const ::android::wp<::android::hidl::base::V1_0::IBase>& who) = 0;
|
||||
};
|
||||
|
||||
// hidl_handle wraps a pointer to a native_handle_t in a hidl_pointer,
|
||||
// so that it can safely be transferred between 32-bit and 64-bit processes.
|
||||
// The ownership semantics for this are:
|
||||
// 1) The conversion constructor and assignment operator taking a const native_handle_t*
|
||||
// do not take ownership of the handle; this is because these operations are usually
|
||||
// just done for IPC, and cloning by default is a waste of resources. If you want
|
||||
// a hidl_handle to take ownership, call setTo(handle, true /*shouldOwn*/);
|
||||
// 2) The copy constructor/assignment operator taking a hidl_handle *DO* take ownership;
|
||||
// that is because it's not intuitive that this class encapsulates a native_handle_t
|
||||
// which needs cloning to be valid; in particular, this allows constructs like this:
|
||||
// hidl_handle copy;
|
||||
// foo->someHidlCall([&](auto incoming_handle) {
|
||||
// copy = incoming_handle;
|
||||
// });
|
||||
// // copy and its enclosed file descriptors will remain valid here.
|
||||
// 3) The move constructor does what you would expect; it only owns the handle if the
|
||||
// original did.
|
||||
struct hidl_handle {
|
||||
hidl_handle();
|
||||
~hidl_handle();
|
||||
|
||||
hidl_handle(const native_handle_t *handle);
|
||||
|
||||
// copy constructor.
|
||||
hidl_handle(const hidl_handle &other);
|
||||
|
||||
// move constructor.
|
||||
hidl_handle(hidl_handle &&other) noexcept;
|
||||
|
||||
// assignment operators
|
||||
hidl_handle &operator=(const hidl_handle &other);
|
||||
|
||||
hidl_handle &operator=(const native_handle_t *native_handle);
|
||||
|
||||
hidl_handle &operator=(hidl_handle &&other) noexcept;
|
||||
|
||||
void setTo(native_handle_t* handle, bool shouldOwn = false);
|
||||
|
||||
const native_handle_t* operator->() const;
|
||||
|
||||
// implicit conversion to const native_handle_t*
|
||||
operator const native_handle_t *() const;
|
||||
|
||||
// explicit conversion
|
||||
const native_handle_t *getNativeHandle() const;
|
||||
private:
|
||||
void freeHandle();
|
||||
|
||||
details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
|
||||
bool mOwnsHandle __attribute ((aligned(8)));
|
||||
};
|
||||
|
||||
struct hidl_string {
|
||||
hidl_string();
|
||||
~hidl_string();
|
||||
|
||||
// copy constructor.
|
||||
hidl_string(const hidl_string &);
|
||||
// copy from a C-style string. nullptr will create an empty string
|
||||
hidl_string(const char *);
|
||||
// copy the first length characters from a C-style string.
|
||||
hidl_string(const char *, size_t length);
|
||||
// copy from an std::string.
|
||||
hidl_string(const std::string &);
|
||||
|
||||
// move constructor.
|
||||
hidl_string(hidl_string &&) noexcept;
|
||||
|
||||
const char *c_str() const;
|
||||
size_t size() const;
|
||||
bool empty() const;
|
||||
|
||||
// copy assignment operator.
|
||||
hidl_string &operator=(const hidl_string &);
|
||||
// copy from a C-style string.
|
||||
hidl_string &operator=(const char *s);
|
||||
// copy from an std::string.
|
||||
hidl_string &operator=(const std::string &);
|
||||
// move assignment operator.
|
||||
hidl_string &operator=(hidl_string &&other) noexcept;
|
||||
// cast to std::string.
|
||||
operator std::string() const;
|
||||
|
||||
void clear();
|
||||
|
||||
// Reference an external char array. Ownership is _not_ transferred.
|
||||
// Caller is responsible for ensuring that underlying memory is valid
|
||||
// for the lifetime of this hidl_string.
|
||||
void setToExternal(const char *data, size_t size);
|
||||
|
||||
// offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
|
||||
static const size_t kOffsetOfBuffer;
|
||||
|
||||
private:
|
||||
details::hidl_pointer<const char> mBuffer;
|
||||
uint32_t mSize; // NOT including the terminating '\0'.
|
||||
bool mOwnsBuffer; // if true then mBuffer is a mutable char *
|
||||
|
||||
// copy from data with size. Assume that my memory is freed
|
||||
// (through clear(), for example)
|
||||
void copyFrom(const char *data, size_t size);
|
||||
// move from another hidl_string
|
||||
void moveFrom(hidl_string &&);
|
||||
};
|
||||
|
||||
#define HIDL_STRING_OPERATOR(OP) \
|
||||
inline bool operator OP(const hidl_string &hs1, const hidl_string &hs2) { \
|
||||
return strcmp(hs1.c_str(), hs2.c_str()) OP 0; \
|
||||
} \
|
||||
inline bool operator OP(const hidl_string &hs, const char *s) { \
|
||||
return strcmp(hs.c_str(), s) OP 0; \
|
||||
} \
|
||||
inline bool operator OP(const char *s, const hidl_string &hs) { \
|
||||
return strcmp(hs.c_str(), s) OP 0; \
|
||||
}
|
||||
|
||||
HIDL_STRING_OPERATOR(==)
|
||||
HIDL_STRING_OPERATOR(!=)
|
||||
HIDL_STRING_OPERATOR(<)
|
||||
HIDL_STRING_OPERATOR(<=)
|
||||
HIDL_STRING_OPERATOR(>)
|
||||
HIDL_STRING_OPERATOR(>=)
|
||||
|
||||
#undef HIDL_STRING_OPERATOR
|
||||
|
||||
// Send our content to the output stream
|
||||
std::ostream& operator<<(std::ostream& os, const hidl_string& str);
|
||||
|
||||
|
||||
// hidl_memory is a structure that can be used to transfer
|
||||
// pieces of shared memory between processes. The assumption
|
||||
// of this object is that the memory remains accessible as
|
||||
// long as the file descriptors in the enclosed mHandle
|
||||
// - as well as all of its cross-process dups() - remain opened.
|
||||
struct hidl_memory {
|
||||
|
||||
hidl_memory() : mHandle(nullptr), mSize(0), mName("") {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hidl_memory object, but doesn't take ownership of
|
||||
* the passed in native_handle_t; callers are responsible for
|
||||
* making sure the handle remains valid while this object is
|
||||
* used.
|
||||
*/
|
||||
hidl_memory(const hidl_string &name, const native_handle_t *handle, size_t size)
|
||||
: mHandle(handle),
|
||||
mSize(size),
|
||||
mName(name)
|
||||
{}
|
||||
|
||||
// copy constructor
|
||||
hidl_memory(const hidl_memory& other) {
|
||||
*this = other;
|
||||
}
|
||||
|
||||
// copy assignment
|
||||
hidl_memory &operator=(const hidl_memory &other) {
|
||||
if (this != &other) {
|
||||
mHandle = other.mHandle;
|
||||
mSize = other.mSize;
|
||||
mName = other.mName;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// move constructor
|
||||
hidl_memory(hidl_memory&& other) noexcept {
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
// move assignment
|
||||
hidl_memory &operator=(hidl_memory &&other) noexcept {
|
||||
if (this != &other) {
|
||||
mHandle = std::move(other.mHandle);
|
||||
mSize = other.mSize;
|
||||
mName = std::move(other.mName);
|
||||
other.mSize = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
~hidl_memory() {
|
||||
}
|
||||
|
||||
const native_handle_t* handle() const {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
const hidl_string &name() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
uint64_t size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
// offsetof(hidl_memory, mHandle) exposed since mHandle is private.
|
||||
static const size_t kOffsetOfHandle;
|
||||
// offsetof(hidl_memory, mName) exposed since mHandle is private.
|
||||
static const size_t kOffsetOfName;
|
||||
|
||||
private:
|
||||
hidl_handle mHandle __attribute__ ((aligned(8)));
|
||||
uint64_t mSize __attribute__ ((aligned(8)));
|
||||
hidl_string mName __attribute__ ((aligned(8)));
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
struct hidl_vec {
|
||||
hidl_vec()
|
||||
: mBuffer(NULL),
|
||||
mSize(0),
|
||||
mOwnsBuffer(true) {
|
||||
static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
|
||||
}
|
||||
|
||||
hidl_vec(const hidl_vec<T> &other) : hidl_vec() {
|
||||
*this = other;
|
||||
}
|
||||
|
||||
hidl_vec(hidl_vec<T> &&other) noexcept
|
||||
: mOwnsBuffer(false) {
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
hidl_vec(const std::initializer_list<T> list)
|
||||
: mOwnsBuffer(true) {
|
||||
if (list.size() > UINT32_MAX) {
|
||||
details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
|
||||
}
|
||||
mSize = static_cast<uint32_t>(list.size());
|
||||
mBuffer = new T[mSize];
|
||||
|
||||
size_t idx = 0;
|
||||
for (auto it = list.begin(); it != list.end(); ++it) {
|
||||
mBuffer[idx++] = *it;
|
||||
}
|
||||
}
|
||||
|
||||
hidl_vec(const std::vector<T> &other) : hidl_vec() {
|
||||
*this = other;
|
||||
}
|
||||
|
||||
template <typename InputIterator,
|
||||
typename = typename std::enable_if<std::is_convertible<
|
||||
typename std::iterator_traits<InputIterator>::iterator_category,
|
||||
std::input_iterator_tag>::value>::type>
|
||||
hidl_vec(InputIterator first, InputIterator last) : mOwnsBuffer(true) {
|
||||
auto size = std::distance(first, last);
|
||||
if (size > static_cast<int64_t>(UINT32_MAX)) {
|
||||
details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
|
||||
}
|
||||
if (size < 0) {
|
||||
details::logAlwaysFatal("size can't be negative.");
|
||||
}
|
||||
mSize = static_cast<uint32_t>(size);
|
||||
mBuffer = new T[mSize];
|
||||
|
||||
size_t idx = 0;
|
||||
for (; first != last; ++first) {
|
||||
mBuffer[idx++] = static_cast<T>(*first);
|
||||
}
|
||||
}
|
||||
|
||||
~hidl_vec() {
|
||||
if (mOwnsBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
mBuffer = NULL;
|
||||
}
|
||||
|
||||
// Reference an existing array, optionally taking ownership. It is the
|
||||
// caller's responsibility to ensure that the underlying memory stays
|
||||
// valid for the lifetime of this hidl_vec.
|
||||
void setToExternal(T *data, size_t size, bool shouldOwn = false) {
|
||||
if (mOwnsBuffer) {
|
||||
delete [] mBuffer;
|
||||
}
|
||||
mBuffer = data;
|
||||
if (size > UINT32_MAX) {
|
||||
details::logAlwaysFatal("external vector size exceeds 2^32 elements.");
|
||||
}
|
||||
mSize = static_cast<uint32_t>(size);
|
||||
mOwnsBuffer = shouldOwn;
|
||||
}
|
||||
|
||||
T *data() {
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
const T *data() const {
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
T *releaseData() {
|
||||
if (!mOwnsBuffer && mSize > 0) {
|
||||
resize(mSize);
|
||||
}
|
||||
mOwnsBuffer = false;
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
hidl_vec &operator=(hidl_vec &&other) noexcept {
|
||||
if (mOwnsBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
mBuffer = other.mBuffer;
|
||||
mSize = other.mSize;
|
||||
mOwnsBuffer = other.mOwnsBuffer;
|
||||
other.mOwnsBuffer = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
hidl_vec &operator=(const hidl_vec &other) {
|
||||
if (this != &other) {
|
||||
if (mOwnsBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
copyFrom(other, other.mSize);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// copy from an std::vector.
|
||||
hidl_vec &operator=(const std::vector<T> &other) {
|
||||
if (mOwnsBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
copyFrom(other, other.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// cast to an std::vector.
|
||||
operator std::vector<T>() const {
|
||||
std::vector<T> v(mSize);
|
||||
for (size_t i = 0; i < mSize; ++i) {
|
||||
v[i] = mBuffer[i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// equality check, assuming that T::operator== is defined.
|
||||
bool operator==(const hidl_vec &other) const {
|
||||
if (mSize != other.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < mSize; ++i) {
|
||||
if (!(mBuffer[i] == other.mBuffer[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// inequality check, assuming that T::operator== is defined.
|
||||
inline bool operator!=(const hidl_vec &other) const {
|
||||
return !((*this) == other);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
T &operator[](size_t index) {
|
||||
return mBuffer[index];
|
||||
}
|
||||
|
||||
const T &operator[](size_t index) const {
|
||||
return mBuffer[index];
|
||||
}
|
||||
|
||||
void resize(size_t size) {
|
||||
if (size > UINT32_MAX) {
|
||||
details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
|
||||
}
|
||||
T *newBuffer = new T[size];
|
||||
|
||||
for (size_t i = 0; i < std::min(static_cast<uint32_t>(size), mSize); ++i) {
|
||||
newBuffer[i] = mBuffer[i];
|
||||
}
|
||||
|
||||
if (mOwnsBuffer) {
|
||||
delete[] mBuffer;
|
||||
}
|
||||
mBuffer = newBuffer;
|
||||
|
||||
mSize = static_cast<uint32_t>(size);
|
||||
mOwnsBuffer = true;
|
||||
}
|
||||
|
||||
// offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
|
||||
static const size_t kOffsetOfBuffer;
|
||||
|
||||
private:
|
||||
// Define std interator interface for walking the array contents
|
||||
template<bool is_const>
|
||||
class iter : public std::iterator<
|
||||
std::random_access_iterator_tag, /* Category */
|
||||
T,
|
||||
ptrdiff_t, /* Distance */
|
||||
typename std::conditional<is_const, const T *, T *>::type /* Pointer */,
|
||||
typename std::conditional<is_const, const T &, T &>::type /* Reference */>
|
||||
{
|
||||
using traits = std::iterator_traits<iter>;
|
||||
using ptr_type = typename traits::pointer;
|
||||
using ref_type = typename traits::reference;
|
||||
using diff_type = typename traits::difference_type;
|
||||
public:
|
||||
iter(ptr_type ptr) : mPtr(ptr) { }
|
||||
inline iter &operator++() { mPtr++; return *this; }
|
||||
inline iter operator++(int) { iter i = *this; mPtr++; return i; }
|
||||
inline iter &operator--() { mPtr--; return *this; }
|
||||
inline iter operator--(int) { iter i = *this; mPtr--; return i; }
|
||||
inline friend iter operator+(diff_type n, const iter &it) { return it.mPtr + n; }
|
||||
inline iter operator+(diff_type n) const { return mPtr + n; }
|
||||
inline iter operator-(diff_type n) const { return mPtr - n; }
|
||||
inline diff_type operator-(const iter &other) const { return mPtr - other.mPtr; }
|
||||
inline iter &operator+=(diff_type n) { mPtr += n; return *this; }
|
||||
inline iter &operator-=(diff_type n) { mPtr -= n; return *this; }
|
||||
inline ref_type operator*() const { return *mPtr; }
|
||||
inline ptr_type operator->() const { return mPtr; }
|
||||
inline bool operator==(const iter &rhs) const { return mPtr == rhs.mPtr; }
|
||||
inline bool operator!=(const iter &rhs) const { return mPtr != rhs.mPtr; }
|
||||
inline bool operator< (const iter &rhs) const { return mPtr < rhs.mPtr; }
|
||||
inline bool operator> (const iter &rhs) const { return mPtr > rhs.mPtr; }
|
||||
inline bool operator<=(const iter &rhs) const { return mPtr <= rhs.mPtr; }
|
||||
inline bool operator>=(const iter &rhs) const { return mPtr >= rhs.mPtr; }
|
||||
inline ref_type operator[](size_t n) const { return mPtr[n]; }
|
||||
private:
|
||||
ptr_type mPtr;
|
||||
};
|
||||
public:
|
||||
using iterator = iter<false /* is_const */>;
|
||||
using const_iterator = iter<true /* is_const */>;
|
||||
|
||||
iterator begin() { return data(); }
|
||||
iterator end() { return data()+mSize; }
|
||||
const_iterator begin() const { return data(); }
|
||||
const_iterator end() const { return data()+mSize; }
|
||||
|
||||
private:
|
||||
details::hidl_pointer<T> mBuffer;
|
||||
uint32_t mSize;
|
||||
bool mOwnsBuffer;
|
||||
|
||||
// copy from an array-like object, assuming my resources are freed.
|
||||
template <typename Array>
|
||||
void copyFrom(const Array &data, size_t size) {
|
||||
mSize = static_cast<uint32_t>(size);
|
||||
mOwnsBuffer = true;
|
||||
if (mSize > 0) {
|
||||
mBuffer = new T[size];
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
mBuffer[i] = data[i];
|
||||
}
|
||||
} else {
|
||||
mBuffer = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const size_t hidl_vec<T>::kOffsetOfBuffer = offsetof(hidl_vec<T>, mBuffer);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace details {
|
||||
|
||||
template<size_t SIZE1, size_t... SIZES>
|
||||
struct product {
|
||||
static constexpr size_t value = SIZE1 * product<SIZES...>::value;
|
||||
};
|
||||
|
||||
template<size_t SIZE1>
|
||||
struct product<SIZE1> {
|
||||
static constexpr size_t value = SIZE1;
|
||||
};
|
||||
|
||||
template<typename T, size_t SIZE1, size_t... SIZES>
|
||||
struct std_array {
|
||||
using type = std::array<typename std_array<T, SIZES...>::type, SIZE1>;
|
||||
};
|
||||
|
||||
template<typename T, size_t SIZE1>
|
||||
struct std_array<T, SIZE1> {
|
||||
using type = std::array<T, SIZE1>;
|
||||
};
|
||||
|
||||
template<typename T, size_t SIZE1, size_t... SIZES>
|
||||
struct accessor {
|
||||
|
||||
using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
|
||||
|
||||
explicit accessor(T *base)
|
||||
: mBase(base) {
|
||||
}
|
||||
|
||||
accessor<T, SIZES...> operator[](size_t index) {
|
||||
return accessor<T, SIZES...>(
|
||||
&mBase[index * product<SIZES...>::value]);
|
||||
}
|
||||
|
||||
accessor &operator=(const std_array_type &other) {
|
||||
for (size_t i = 0; i < SIZE1; ++i) {
|
||||
(*this)[i] = other[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T *mBase;
|
||||
};
|
||||
|
||||
template<typename T, size_t SIZE1>
|
||||
struct accessor<T, SIZE1> {
|
||||
|
||||
using std_array_type = typename std_array<T, SIZE1>::type;
|
||||
|
||||
explicit accessor(T *base)
|
||||
: mBase(base) {
|
||||
}
|
||||
|
||||
T &operator[](size_t index) {
|
||||
return mBase[index];
|
||||
}
|
||||
|
||||
accessor &operator=(const std_array_type &other) {
|
||||
for (size_t i = 0; i < SIZE1; ++i) {
|
||||
(*this)[i] = other[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T *mBase;
|
||||
};
|
||||
|
||||
template<typename T, size_t SIZE1, size_t... SIZES>
|
||||
struct const_accessor {
|
||||
|
||||
using std_array_type = typename std_array<T, SIZE1, SIZES...>::type;
|
||||
|
||||
explicit const_accessor(const T *base)
|
||||
: mBase(base) {
|
||||
}
|
||||
|
||||
const_accessor<T, SIZES...> operator[](size_t index) const {
|
||||
return const_accessor<T, SIZES...>(
|
||||
&mBase[index * product<SIZES...>::value]);
|
||||
}
|
||||
|
||||
operator std_array_type() {
|
||||
std_array_type array;
|
||||
for (size_t i = 0; i < SIZE1; ++i) {
|
||||
array[i] = (*this)[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private:
|
||||
const T *mBase;
|
||||
};
|
||||
|
||||
template<typename T, size_t SIZE1>
|
||||
struct const_accessor<T, SIZE1> {
|
||||
|
||||
using std_array_type = typename std_array<T, SIZE1>::type;
|
||||
|
||||
explicit const_accessor(const T *base)
|
||||
: mBase(base) {
|
||||
}
|
||||
|
||||
const T &operator[](size_t index) const {
|
||||
return mBase[index];
|
||||
}
|
||||
|
||||
operator std_array_type() {
|
||||
std_array_type array;
|
||||
for (size_t i = 0; i < SIZE1; ++i) {
|
||||
array[i] = (*this)[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private:
|
||||
const T *mBase;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// A multidimensional array of T's. Assumes that T::operator=(const T &) is defined.
|
||||
template<typename T, size_t SIZE1, size_t... SIZES>
|
||||
struct hidl_array {
|
||||
|
||||
using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
|
||||
|
||||
hidl_array() = default;
|
||||
|
||||
// Copies the data from source, using T::operator=(const T &).
|
||||
hidl_array(const T *source) {
|
||||
for (size_t i = 0; i < elementCount(); ++i) {
|
||||
mBuffer[i] = source[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Copies the data from the given std::array, using T::operator=(const T &).
|
||||
hidl_array(const std_array_type &array) {
|
||||
details::accessor<T, SIZE1, SIZES...> modifier(mBuffer);
|
||||
modifier = array;
|
||||
}
|
||||
|
||||
T *data() { return mBuffer; }
|
||||
const T *data() const { return mBuffer; }
|
||||
|
||||
details::accessor<T, SIZES...> operator[](size_t index) {
|
||||
return details::accessor<T, SIZES...>(
|
||||
&mBuffer[index * details::product<SIZES...>::value]);
|
||||
}
|
||||
|
||||
details::const_accessor<T, SIZES...> operator[](size_t index) const {
|
||||
return details::const_accessor<T, SIZES...>(
|
||||
&mBuffer[index * details::product<SIZES...>::value]);
|
||||
}
|
||||
|
||||
// equality check, assuming that T::operator== is defined.
|
||||
bool operator==(const hidl_array &other) const {
|
||||
for (size_t i = 0; i < elementCount(); ++i) {
|
||||
if (!(mBuffer[i] == other.mBuffer[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!=(const hidl_array &other) const {
|
||||
return !((*this) == other);
|
||||
}
|
||||
|
||||
using size_tuple_type = std::tuple<decltype(SIZE1), decltype(SIZES)...>;
|
||||
|
||||
static constexpr size_tuple_type size() {
|
||||
return std::make_tuple(SIZE1, SIZES...);
|
||||
}
|
||||
|
||||
static constexpr size_t elementCount() {
|
||||
return details::product<SIZE1, SIZES...>::value;
|
||||
}
|
||||
|
||||
operator std_array_type() const {
|
||||
return details::const_accessor<T, SIZE1, SIZES...>(mBuffer);
|
||||
}
|
||||
|
||||
private:
|
||||
T mBuffer[elementCount()];
|
||||
};
|
||||
|
||||
// An array of T's. Assumes that T::operator=(const T &) is defined.
|
||||
template<typename T, size_t SIZE1>
|
||||
struct hidl_array<T, SIZE1> {
|
||||
|
||||
using std_array_type = typename details::std_array<T, SIZE1>::type;
|
||||
|
||||
hidl_array() = default;
|
||||
|
||||
// Copies the data from source, using T::operator=(const T &).
|
||||
hidl_array(const T *source) {
|
||||
for (size_t i = 0; i < elementCount(); ++i) {
|
||||
mBuffer[i] = source[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Copies the data from the given std::array, using T::operator=(const T &).
|
||||
hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
|
||||
|
||||
T *data() { return mBuffer; }
|
||||
const T *data() const { return mBuffer; }
|
||||
|
||||
T &operator[](size_t index) {
|
||||
return mBuffer[index];
|
||||
}
|
||||
|
||||
const T &operator[](size_t index) const {
|
||||
return mBuffer[index];
|
||||
}
|
||||
|
||||
// equality check, assuming that T::operator== is defined.
|
||||
bool operator==(const hidl_array &other) const {
|
||||
for (size_t i = 0; i < elementCount(); ++i) {
|
||||
if (!(mBuffer[i] == other.mBuffer[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!=(const hidl_array &other) const {
|
||||
return !((*this) == other);
|
||||
}
|
||||
|
||||
static constexpr size_t size() { return SIZE1; }
|
||||
static constexpr size_t elementCount() { return SIZE1; }
|
||||
|
||||
// Copies the data to an std::array, using T::operator=(T).
|
||||
operator std_array_type() const {
|
||||
std_array_type array;
|
||||
for (size_t i = 0; i < SIZE1; ++i) {
|
||||
array[i] = mBuffer[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private:
|
||||
T mBuffer[SIZE1];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Version functions
|
||||
struct hidl_version {
|
||||
public:
|
||||
constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {}
|
||||
|
||||
bool operator==(const hidl_version& other) const {
|
||||
return (mMajor == other.get_major() && mMinor == other.get_minor());
|
||||
}
|
||||
|
||||
bool operator<(const hidl_version& other) const {
|
||||
return (mMajor < other.get_major() ||
|
||||
(mMajor == other.get_major() && mMinor < other.get_minor()));
|
||||
}
|
||||
|
||||
bool operator>(const hidl_version& other) const {
|
||||
return other < *this;
|
||||
}
|
||||
|
||||
bool operator<=(const hidl_version& other) const {
|
||||
return !(*this > other);
|
||||
}
|
||||
|
||||
bool operator>=(const hidl_version& other) const {
|
||||
return !(*this < other);
|
||||
}
|
||||
|
||||
constexpr uint16_t get_major() const { return mMajor; }
|
||||
constexpr uint16_t get_minor() const { return mMinor; }
|
||||
|
||||
private:
|
||||
uint16_t mMajor;
|
||||
uint16_t mMinor;
|
||||
};
|
||||
|
||||
inline android::hardware::hidl_version make_hidl_version(uint16_t major, uint16_t minor) {
|
||||
return hidl_version(major,minor);
|
||||
}
|
||||
|
||||
///////////////////// toString functions
|
||||
|
||||
std::string toString(const void *t);
|
||||
|
||||
// toString alias for numeric types
|
||||
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
|
||||
inline std::string toString(T t) {
|
||||
return std::to_string(t);
|
||||
}
|
||||
|
||||
namespace details {
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
|
||||
inline std::string toHexString(T t, bool prefix = true) {
|
||||
std::ostringstream os;
|
||||
if (prefix) { os << std::showbase; }
|
||||
os << std::hex << t;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::string toHexString(uint8_t t, bool prefix) {
|
||||
return toHexString(static_cast<int32_t>(t), prefix);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::string toHexString(int8_t t, bool prefix) {
|
||||
return toHexString(static_cast<int32_t>(t), prefix);
|
||||
}
|
||||
|
||||
template<typename Array>
|
||||
std::string arrayToString(const Array &a, size_t size);
|
||||
|
||||
template<size_t SIZE1>
|
||||
std::string arraySizeToString() {
|
||||
return std::string{"["} + toString(SIZE1) + "]";
|
||||
}
|
||||
|
||||
template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
|
||||
std::string arraySizeToString() {
|
||||
return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
|
||||
}
|
||||
|
||||
template<typename T, size_t SIZE1>
|
||||
std::string toString(details::const_accessor<T, SIZE1> a) {
|
||||
return arrayToString(a, SIZE1);
|
||||
}
|
||||
|
||||
template<typename Array>
|
||||
std::string arrayToString(const Array &a, size_t size) {
|
||||
using android::hardware::toString;
|
||||
std::string os;
|
||||
os += "{";
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (i > 0) {
|
||||
os += ", ";
|
||||
}
|
||||
os += toString(a[i]);
|
||||
}
|
||||
os += "}";
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
|
||||
std::string toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
|
||||
return arrayToString(a, SIZE1);
|
||||
}
|
||||
|
||||
} //namespace details
|
||||
|
||||
inline std::string toString(const void *t) {
|
||||
return details::toHexString(reinterpret_cast<uintptr_t>(t));
|
||||
}
|
||||
|
||||
// debug string dump. There will be quotes around the string!
|
||||
inline std::string toString(const hidl_string &hs) {
|
||||
return std::string{"\""} + hs.c_str() + "\"";
|
||||
}
|
||||
|
||||
// debug string dump
|
||||
inline std::string toString(const hidl_handle &hs) {
|
||||
return toString(hs.getNativeHandle());
|
||||
}
|
||||
|
||||
inline std::string toString(const hidl_memory &mem) {
|
||||
return std::string{"memory {.name = "} + toString(mem.name()) + ", .size = "
|
||||
+ toString(mem.size())
|
||||
+ ", .handle = " + toString(mem.handle()) + "}";
|
||||
}
|
||||
|
||||
inline std::string toString(const sp<hidl_death_recipient> &dr) {
|
||||
return std::string{"death_recipient@"} + toString(dr.get());
|
||||
}
|
||||
|
||||
// debug string dump, assuming that toString(T) is defined.
|
||||
template<typename T>
|
||||
std::string toString(const hidl_vec<T> &a) {
|
||||
std::string os;
|
||||
os += "[" + toString(a.size()) + "]";
|
||||
os += details::arrayToString(a, a.size());
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T, size_t SIZE1>
|
||||
std::string toString(const hidl_array<T, SIZE1> &a) {
|
||||
return details::arraySizeToString<SIZE1>()
|
||||
+ details::toString(details::const_accessor<T, SIZE1>(a.data()));
|
||||
}
|
||||
|
||||
template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
|
||||
std::string toString(const hidl_array<T, SIZE1, SIZE2, SIZES...> &a) {
|
||||
return details::arraySizeToString<SIZE1, SIZE2, SIZES...>()
|
||||
+ details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
|
||||
}
|
||||
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
|
||||
#endif // ANDROID_HIDL_SUPPORT_H
|
281
android/system/libhidl/base/include/hidl/MQDescriptor.h
Normal file
281
android/system/libhidl/base/include/hidl/MQDescriptor.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FMSGQ_DESCRIPTOR_H
|
||||
#define _FMSGQ_DESCRIPTOR_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/native_handle.h>
|
||||
#include <hidl/HidlInternal.h>
|
||||
#include <hidl/HidlSupport.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
||||
typedef uint64_t RingBufferPosition;
|
||||
|
||||
struct GrantorDescriptor {
|
||||
uint32_t flags __attribute__ ((aligned(4)));
|
||||
uint32_t fdIndex __attribute__ ((aligned(4)));
|
||||
uint32_t offset __attribute__ ((aligned(4)));
|
||||
uint64_t extent __attribute__ ((aligned(8)));
|
||||
};
|
||||
|
||||
static_assert(offsetof(GrantorDescriptor, flags) == 0, "wrong offset");
|
||||
static_assert(offsetof(GrantorDescriptor, fdIndex) == 4, "wrong offset");
|
||||
static_assert(offsetof(GrantorDescriptor, offset) == 8, "wrong offset");
|
||||
static_assert(offsetof(GrantorDescriptor, extent) == 16, "wrong offset");
|
||||
static_assert(sizeof(GrantorDescriptor) == 24, "wrong size");
|
||||
static_assert(__alignof(GrantorDescriptor) == 8, "wrong alignment");
|
||||
|
||||
enum MQFlavor : uint32_t {
|
||||
/*
|
||||
* kSynchronizedReadWrite represents the wait-free synchronized flavor of the
|
||||
* FMQ. It is intended to be have a single reader and single writer.
|
||||
* Attempts to overflow/underflow returns a failure.
|
||||
*/
|
||||
kSynchronizedReadWrite = 0x01,
|
||||
/*
|
||||
* kUnsynchronizedWrite represents the flavor of FMQ where writes always
|
||||
* succeed. This flavor allows one writer and many readers. A read operation
|
||||
* can detect an overwrite and reset the read counter.
|
||||
*/
|
||||
kUnsynchronizedWrite = 0x02
|
||||
};
|
||||
|
||||
template <typename T, MQFlavor flavor>
|
||||
struct MQDescriptor {
|
||||
MQDescriptor(
|
||||
const std::vector<GrantorDescriptor>& grantors,
|
||||
native_handle_t* nHandle, size_t size);
|
||||
|
||||
MQDescriptor(size_t bufferSize, native_handle_t* nHandle,
|
||||
size_t messageSize, bool configureEventFlag = false);
|
||||
|
||||
MQDescriptor();
|
||||
~MQDescriptor();
|
||||
|
||||
explicit MQDescriptor(const MQDescriptor &other);
|
||||
MQDescriptor &operator=(const MQDescriptor &other) = delete;
|
||||
|
||||
size_t getSize() const;
|
||||
|
||||
size_t getQuantum() const;
|
||||
|
||||
int32_t getFlags() const;
|
||||
|
||||
bool isHandleValid() const { return mHandle != nullptr; }
|
||||
size_t countGrantors() const { return mGrantors.size(); }
|
||||
|
||||
inline const ::android::hardware::hidl_vec<GrantorDescriptor> &grantors() const {
|
||||
return mGrantors;
|
||||
}
|
||||
|
||||
inline ::android::hardware::hidl_vec<GrantorDescriptor> &grantors() {
|
||||
return mGrantors;
|
||||
}
|
||||
|
||||
inline const ::native_handle_t *handle() const {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
inline ::native_handle_t *handle() {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
static const size_t kOffsetOfGrantors;
|
||||
static const size_t kOffsetOfHandle;
|
||||
enum GrantorType : int { READPTRPOS = 0, WRITEPTRPOS, DATAPTRPOS, EVFLAGWORDPOS };
|
||||
|
||||
/*
|
||||
* There should at least be GrantorDescriptors for the read counter, write
|
||||
* counter and data buffer. A GrantorDescriptor for an EventFlag word is
|
||||
* not required if there is no need for blocking FMQ operations.
|
||||
*/
|
||||
static constexpr int32_t kMinGrantorCount = DATAPTRPOS + 1;
|
||||
|
||||
/*
|
||||
* Minimum number of GrantorDescriptors required if EventFlag support is
|
||||
* needed for blocking FMQ operations.
|
||||
*/
|
||||
static constexpr int32_t kMinGrantorCountForEvFlagSupport = EVFLAGWORDPOS + 1;
|
||||
|
||||
//TODO(b/34160777) Identify a better solution that supports remoting.
|
||||
static inline size_t alignToWordBoundary(size_t length) {
|
||||
constexpr size_t kAlignmentSize = 64;
|
||||
if (kAlignmentSize % __WORDSIZE != 0) {
|
||||
details::logAlwaysFatal("Incompatible word size");
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if alignment to word boundary would cause an overflow.
|
||||
*/
|
||||
if (length > SIZE_MAX - kAlignmentSize/8 + 1) {
|
||||
details::logAlwaysFatal("Queue size too large");
|
||||
}
|
||||
|
||||
return (length + kAlignmentSize/8 - 1) & ~(kAlignmentSize/8 - 1U);
|
||||
}
|
||||
|
||||
static inline size_t isAlignedToWordBoundary(size_t offset) {
|
||||
constexpr size_t kAlignmentSize = 64;
|
||||
return (offset & (kAlignmentSize/8 - 1)) == 0;
|
||||
}
|
||||
private:
|
||||
::android::hardware::hidl_vec<GrantorDescriptor> mGrantors;
|
||||
::android::hardware::details::hidl_pointer<native_handle_t> mHandle;
|
||||
uint32_t mQuantum;
|
||||
uint32_t mFlags;
|
||||
};
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
const size_t MQDescriptor<T, flavor>::kOffsetOfGrantors = offsetof(MQDescriptor, mGrantors);
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
const size_t MQDescriptor<T, flavor>::kOffsetOfHandle = offsetof(MQDescriptor, mHandle);
|
||||
|
||||
/*
|
||||
* MQDescriptorSync will describe the wait-free synchronized
|
||||
* flavor of FMQ.
|
||||
*/
|
||||
template<typename T>
|
||||
using MQDescriptorSync = MQDescriptor<T, kSynchronizedReadWrite>;
|
||||
|
||||
/*
|
||||
* MQDescriptorUnsync will describe the unsynchronized write
|
||||
* flavor of FMQ.
|
||||
*/
|
||||
template<typename T>
|
||||
using MQDescriptorUnsync = MQDescriptor<T, kUnsynchronizedWrite>;
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
MQDescriptor<T, flavor>::MQDescriptor(
|
||||
const std::vector<GrantorDescriptor>& grantors,
|
||||
native_handle_t* nhandle,
|
||||
size_t size)
|
||||
: mHandle(nhandle),
|
||||
mQuantum(size),
|
||||
mFlags(flavor) {
|
||||
mGrantors.resize(grantors.size());
|
||||
for (size_t i = 0; i < grantors.size(); ++i) {
|
||||
if (isAlignedToWordBoundary(grantors[i].offset) == false) {
|
||||
details::logAlwaysFatal("Grantor offsets need to be aligned");
|
||||
}
|
||||
mGrantors[i] = grantors[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
MQDescriptor<T, flavor>::MQDescriptor(size_t bufferSize, native_handle_t *nHandle,
|
||||
size_t messageSize, bool configureEventFlag)
|
||||
: mHandle(nHandle), mQuantum(messageSize), mFlags(flavor) {
|
||||
/*
|
||||
* If configureEventFlag is true, allocate an additional spot in mGrantor
|
||||
* for containing the fd and offset for mmapping the EventFlag word.
|
||||
*/
|
||||
mGrantors.resize(configureEventFlag? kMinGrantorCountForEvFlagSupport : kMinGrantorCount);
|
||||
|
||||
size_t memSize[] = {
|
||||
sizeof(RingBufferPosition), /* memory to be allocated for read pointer counter */
|
||||
sizeof(RingBufferPosition), /* memory to be allocated for write pointer counter */
|
||||
bufferSize, /* memory to be allocated for data buffer */
|
||||
sizeof(std::atomic<uint32_t>)/* memory to be allocated for EventFlag word */
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a default grantor descriptor for read, write pointers and
|
||||
* the data buffer. fdIndex parameter is set to 0 by default and
|
||||
* the offset for each grantor is contiguous.
|
||||
*/
|
||||
for (size_t grantorPos = 0, offset = 0;
|
||||
grantorPos < mGrantors.size();
|
||||
offset += memSize[grantorPos++]) {
|
||||
mGrantors[grantorPos] = {
|
||||
0 /* grantor flags */,
|
||||
0 /* fdIndex */,
|
||||
static_cast<uint32_t>(alignToWordBoundary(offset)),
|
||||
memSize[grantorPos]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
MQDescriptor<T, flavor>::MQDescriptor(const MQDescriptor<T, flavor> &other)
|
||||
: mGrantors(other.mGrantors),
|
||||
mHandle(nullptr),
|
||||
mQuantum(other.mQuantum),
|
||||
mFlags(other.mFlags) {
|
||||
if (other.mHandle != nullptr) {
|
||||
mHandle = native_handle_create(
|
||||
other.mHandle->numFds, other.mHandle->numInts);
|
||||
|
||||
for (int i = 0; i < other.mHandle->numFds; ++i) {
|
||||
mHandle->data[i] = dup(other.mHandle->data[i]);
|
||||
}
|
||||
|
||||
memcpy(&mHandle->data[other.mHandle->numFds],
|
||||
&other.mHandle->data[other.mHandle->numFds],
|
||||
other.mHandle->numInts * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
MQDescriptor<T, flavor>::MQDescriptor() : MQDescriptor(
|
||||
std::vector<android::hardware::GrantorDescriptor>(),
|
||||
nullptr /* nHandle */,
|
||||
0 /* size */) {}
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
MQDescriptor<T, flavor>::~MQDescriptor() {
|
||||
if (mHandle != nullptr) {
|
||||
native_handle_close(mHandle);
|
||||
native_handle_delete(mHandle);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
size_t MQDescriptor<T, flavor>::getSize() const {
|
||||
return mGrantors[DATAPTRPOS].extent;
|
||||
}
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
size_t MQDescriptor<T, flavor>::getQuantum() const { return mQuantum; }
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
int32_t MQDescriptor<T, flavor>::getFlags() const { return mFlags; }
|
||||
|
||||
template<typename T, MQFlavor flavor>
|
||||
std::string toString(const MQDescriptor<T, flavor> &q) {
|
||||
std::string os;
|
||||
if (flavor & kSynchronizedReadWrite) {
|
||||
os += "fmq_sync";
|
||||
}
|
||||
if (flavor & kUnsynchronizedWrite) {
|
||||
os += "fmq_unsync";
|
||||
}
|
||||
os += " {"
|
||||
+ toString(q.grantors().size()) + " grantor(s), "
|
||||
+ "size = " + toString(q.getSize())
|
||||
+ ", .handle = " + toString(q.handle())
|
||||
+ ", .quantum = " + toString(q.getQuantum()) + "}";
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // FMSGQ_DESCRIPTOR_H
|
273
android/system/libhidl/base/include/hidl/Status.h
Normal file
273
android/system/libhidl/base/include/hidl/Status.h
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HARDWARE_BINDER_STATUS_H
|
||||
#define ANDROID_HARDWARE_BINDER_STATUS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
|
||||
#include <hidl/HidlInternal.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
||||
// An object similar in function to a status_t except that it understands
|
||||
// how exceptions are encoded in the prefix of a Parcel. Used like:
|
||||
//
|
||||
// Parcel data;
|
||||
// Parcel reply;
|
||||
// status_t status;
|
||||
// binder::Status remote_exception;
|
||||
// if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
|
||||
// (status = data.writeInt32(function_input)) != OK) {
|
||||
// // We failed to write into the memory of our local parcel?
|
||||
// }
|
||||
// if ((status = remote()->transact(transaction, data, &reply)) != OK) {
|
||||
// // Something has gone wrong in the binder driver or libbinder.
|
||||
// }
|
||||
// if ((status = remote_exception.readFromParcel(reply)) != OK) {
|
||||
// // The remote didn't correctly write the exception header to the
|
||||
// // reply.
|
||||
// }
|
||||
// if (!remote_exception.isOk()) {
|
||||
// // The transaction went through correctly, but the remote reported an
|
||||
// // exception during handling.
|
||||
// }
|
||||
//
|
||||
class Status final {
|
||||
public:
|
||||
// Keep the exception codes in sync with android/os/Parcel.java.
|
||||
enum Exception {
|
||||
EX_NONE = 0,
|
||||
EX_SECURITY = -1,
|
||||
EX_BAD_PARCELABLE = -2,
|
||||
EX_ILLEGAL_ARGUMENT = -3,
|
||||
EX_NULL_POINTER = -4,
|
||||
EX_ILLEGAL_STATE = -5,
|
||||
EX_NETWORK_MAIN_THREAD = -6,
|
||||
EX_UNSUPPORTED_OPERATION = -7,
|
||||
|
||||
// This is special and Java specific; see Parcel.java.
|
||||
EX_HAS_REPLY_HEADER = -128,
|
||||
// This is special, and indicates to C++ binder proxies that the
|
||||
// transaction has failed at a low level.
|
||||
EX_TRANSACTION_FAILED = -129,
|
||||
};
|
||||
|
||||
// A more readable alias for the default constructor.
|
||||
static Status ok();
|
||||
// Authors should explicitly pick whether their integer is:
|
||||
// - an exception code (EX_* above)
|
||||
// - status_t
|
||||
//
|
||||
// Prefer a generic exception code when possible or a status_t
|
||||
// for low level transport errors. Service specific errors
|
||||
// should be at a higher level in HIDL.
|
||||
static Status fromExceptionCode(int32_t exceptionCode);
|
||||
static Status fromExceptionCode(int32_t exceptionCode,
|
||||
const char *message);
|
||||
static Status fromStatusT(status_t status);
|
||||
|
||||
Status() = default;
|
||||
~Status() = default;
|
||||
|
||||
// Status objects are copyable and contain just simple data.
|
||||
Status(const Status& status) = default;
|
||||
Status(Status&& status) = default;
|
||||
Status& operator=(const Status& status) = default;
|
||||
|
||||
// Set one of the pre-defined exception types defined above.
|
||||
void setException(int32_t ex, const char *message);
|
||||
// Setting a |status| != OK causes generated code to return |status|
|
||||
// from Binder transactions, rather than writing an exception into the
|
||||
// reply Parcel. This is the least preferable way of reporting errors.
|
||||
void setFromStatusT(status_t status);
|
||||
|
||||
// Get information about an exception.
|
||||
int32_t exceptionCode() const { return mException; }
|
||||
const char *exceptionMessage() const { return mMessage.c_str(); }
|
||||
status_t transactionError() const {
|
||||
return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
|
||||
}
|
||||
|
||||
bool isOk() const { return mException == EX_NONE; }
|
||||
|
||||
// For debugging purposes only
|
||||
std::string description() const;
|
||||
|
||||
private:
|
||||
Status(int32_t exceptionCode, int32_t errorCode);
|
||||
Status(int32_t exceptionCode, int32_t errorCode, const char *message);
|
||||
|
||||
// If |mException| == EX_TRANSACTION_FAILED, generated code will return
|
||||
// |mErrorCode| as the result of the transaction rather than write an
|
||||
// exception to the reply parcel.
|
||||
//
|
||||
// Otherwise, we always write |mException| to the parcel.
|
||||
// If |mException| != EX_NONE, we write |mMessage| as well.
|
||||
int32_t mException = EX_NONE;
|
||||
int32_t mErrorCode = 0;
|
||||
std::string mMessage;
|
||||
}; // class Status
|
||||
|
||||
// For gtest output logging
|
||||
std::ostream& operator<< (std::ostream& stream, const Status& s);
|
||||
|
||||
template<typename T> class Return;
|
||||
|
||||
namespace details {
|
||||
class return_status {
|
||||
private:
|
||||
Status mStatus {};
|
||||
mutable bool mCheckedStatus = false;
|
||||
|
||||
template <typename T, typename U>
|
||||
friend Return<U> StatusOf(const Return<T> &other);
|
||||
protected:
|
||||
void assertOk() const;
|
||||
public:
|
||||
return_status() {}
|
||||
return_status(Status s) : mStatus(s) {}
|
||||
|
||||
return_status(const return_status &) = delete;
|
||||
return_status &operator=(const return_status &) = delete;
|
||||
|
||||
return_status(return_status &&other) {
|
||||
*this = std::move(other);
|
||||
}
|
||||
return_status &operator=(return_status &&other);
|
||||
|
||||
~return_status();
|
||||
|
||||
bool isOk() const {
|
||||
mCheckedStatus = true;
|
||||
return mStatus.isOk();
|
||||
}
|
||||
|
||||
// Check if underlying error is DEAD_OBJECT.
|
||||
// Check mCheckedStatus only if this method returns true.
|
||||
bool isDeadObject() const {
|
||||
bool dead = mStatus.transactionError() == DEAD_OBJECT;
|
||||
|
||||
// This way, if you only check isDeadObject your process will
|
||||
// only be killed for more serious unchecked errors
|
||||
if (dead) {
|
||||
mCheckedStatus = true;
|
||||
}
|
||||
|
||||
return dead;
|
||||
}
|
||||
|
||||
// For debugging purposes only
|
||||
std::string description() const {
|
||||
// Doesn't consider checked.
|
||||
return mStatus.description();
|
||||
}
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
template<typename T> class Return : public details::return_status {
|
||||
private:
|
||||
T mVal {};
|
||||
public:
|
||||
Return(T v) : details::return_status(), mVal{v} {}
|
||||
Return(Status s) : details::return_status(s) {}
|
||||
|
||||
// move-able.
|
||||
// precondition: "this" has checked status
|
||||
// postcondition: other is safe to destroy after moving to *this.
|
||||
Return(Return &&other) = default;
|
||||
Return &operator=(Return &&) = default;
|
||||
|
||||
~Return() = default;
|
||||
|
||||
operator T() const {
|
||||
assertOk();
|
||||
return mVal;
|
||||
}
|
||||
|
||||
T withDefault(T t) {
|
||||
return isOk() ? mVal : t;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> class Return<sp<T>> : public details::return_status {
|
||||
private:
|
||||
sp<T> mVal {};
|
||||
public:
|
||||
Return(sp<T> v) : details::return_status(), mVal{v} {}
|
||||
Return(T* v) : details::return_status(), mVal{v} {}
|
||||
// Constructors matching a different type (that is related by inheritance)
|
||||
template<typename U> Return(sp<U> v) : details::return_status(), mVal{v} {}
|
||||
template<typename U> Return(U* v) : details::return_status(), mVal{v} {}
|
||||
Return(Status s) : details::return_status(s) {}
|
||||
|
||||
// move-able.
|
||||
// precondition: "this" has checked status
|
||||
// postcondition: other is safe to destroy after moving to *this.
|
||||
Return(Return &&other) = default;
|
||||
Return &operator=(Return &&) = default;
|
||||
|
||||
~Return() = default;
|
||||
|
||||
operator sp<T>() const {
|
||||
assertOk();
|
||||
return mVal;
|
||||
}
|
||||
|
||||
sp<T> withDefault(sp<T> t) {
|
||||
return isOk() ? mVal : t;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> class Return<void> : public details::return_status {
|
||||
public:
|
||||
Return() : details::return_status() {}
|
||||
Return(Status s) : details::return_status(s) {}
|
||||
|
||||
// move-able.
|
||||
// precondition: "this" has checked status
|
||||
// postcondition: other is safe to destroy after moving to *this.
|
||||
Return(Return &&) = default;
|
||||
Return &operator=(Return &&) = default;
|
||||
|
||||
~Return() = default;
|
||||
};
|
||||
|
||||
static inline Return<void> Void() {
|
||||
return Return<void>();
|
||||
}
|
||||
|
||||
namespace details {
|
||||
// Create a Return<U> from the Status of Return<T>. The provided
|
||||
// Return<T> must have an error status and have it checked.
|
||||
template <typename T, typename U>
|
||||
Return<U> StatusOf(const Return<T> &other) {
|
||||
if (other.mStatus.isOk() || !other.mCheckedStatus) {
|
||||
details::logAlwaysFatal("cannot call statusOf on an OK Status or an unchecked status");
|
||||
}
|
||||
return Return<U>{other.mStatus};
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_BINDER_STATUS_H
|
101
android/system/libhidl/base/include/hidl/SynchronizedQueue.h
Normal file
101
android/system/libhidl/base/include/hidl/SynchronizedQueue.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
|
||||
#define ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace details {
|
||||
/* Threadsafe queue.
|
||||
*/
|
||||
template <typename T>
|
||||
struct SynchronizedQueue {
|
||||
SynchronizedQueue(size_t limit);
|
||||
|
||||
/* Gets an item from the front of the queue.
|
||||
*
|
||||
* Blocks until the item is available.
|
||||
*/
|
||||
T wait_pop();
|
||||
|
||||
/* Puts an item onto the end of the queue.
|
||||
*/
|
||||
bool push(const T& item);
|
||||
|
||||
/* Gets the size of the array.
|
||||
*/
|
||||
size_t size();
|
||||
|
||||
private:
|
||||
std::condition_variable mCondition;
|
||||
std::mutex mMutex;
|
||||
std::queue<T> mQueue;
|
||||
const size_t mQueueLimit;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
SynchronizedQueue<T>::SynchronizedQueue(size_t limit) : mQueueLimit(limit) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T SynchronizedQueue<T>::wait_pop() {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
|
||||
mCondition.wait(lock, [this]{
|
||||
return !this->mQueue.empty();
|
||||
});
|
||||
|
||||
T item = mQueue.front();
|
||||
mQueue.pop();
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SynchronizedQueue<T>::push(const T &item) {
|
||||
bool success;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (mQueue.size() < mQueueLimit) {
|
||||
mQueue.push(item);
|
||||
success = true;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
mCondition.notify_one();
|
||||
return success;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t SynchronizedQueue<T>::size() {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
|
||||
return mQueue.size();
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
|
65
android/system/libhidl/base/include/hidl/TaskRunner.h
Normal file
65
android/system/libhidl/base/include/hidl/TaskRunner.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef ANDROID_HIDL_TASK_RUNNER_H
|
||||
#define ANDROID_HIDL_TASK_RUNNER_H
|
||||
|
||||
#include "SynchronizedQueue.h"
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace details {
|
||||
|
||||
/*
|
||||
* A background infinite loop that runs the Tasks push()'ed.
|
||||
* Equivalent to a simple single-threaded Looper.
|
||||
*/
|
||||
class TaskRunner {
|
||||
public:
|
||||
using Task = std::function<void(void)>;
|
||||
|
||||
/* Create an empty task runner. Nothing will be done until start() is called. */
|
||||
TaskRunner();
|
||||
|
||||
/*
|
||||
* Notify the background thread to terminate and return immediately.
|
||||
* Tasks in the queue will continue to be done sequentially in background
|
||||
* until all tasks are finished.
|
||||
*/
|
||||
~TaskRunner();
|
||||
|
||||
/*
|
||||
* Sets the queue limit. Fails the push operation once the limit is reached.
|
||||
* Then kicks off the loop.
|
||||
*/
|
||||
void start(size_t limit);
|
||||
|
||||
/*
|
||||
* Add a task. Return true if successful, false if
|
||||
* the queue's size exceeds limit or t doesn't contain a callable target.
|
||||
*/
|
||||
bool push(const Task &t);
|
||||
|
||||
private:
|
||||
std::shared_ptr<SynchronizedQueue<Task>> mQueue;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HIDL_TASK_RUNNER_H
|
Loading…
Add table
Add a link
Reference in a new issue