summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:26:25 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:26:25 +0000
commit278e9d242f65f45265da2f14aee13355decd1bad (patch)
tree3cdc09f9859f0f721e9fb431d45cfb13c8fc9bad
parent96b10ca07bd474425614eed8d47d0db7a3d05700 (diff)
parent87d7ad9d8fe6cbb0405983b37ff9e79927451bc7 (diff)
downloadlibhidl-q_tzdata_aml_297100000.tar.gz
Change-Id: I410d82f717bc22d5640b0d86ac1fde47169456a6
-rw-r--r--Android.bp23
-rw-r--r--TEST_MAPPING3
-rw-r--r--adapter/Android.bp3
-rw-r--r--base/Android.bp5
-rw-r--r--base/HidlInternal.cpp71
-rw-r--r--base/HidlSupport.cpp13
-rw-r--r--base/Status.cpp39
-rw-r--r--base/include/hidl/HidlSupport.h55
-rw-r--r--base/include/hidl/Status.h11
-rw-r--r--gtest_helper/hidl/GtestPrinter.h58
-rw-r--r--libhidlcache/Android.bp71
-rw-r--r--libhidlcache/HidlCache.h143
-rw-r--r--libhidlcache/HidlMemoryCache.cpp127
-rw-r--r--libhidlcache/HidlMemoryCache.h62
-rw-r--r--libhidlcache/MemoryDealer.cpp325
-rw-r--r--libhidlcache/include/hidlcache/MemoryDealer.h80
-rw-r--r--libhidlcache/include/hidlcache/mapping.h54
-rw-r--r--libhidlcache/libhidlcache_test.cpp159
-rw-r--r--libhidlcache/mapping.cpp47
-rw-r--r--libhidlmemory/Android.bp1
-rw-r--r--test_main.cpp174
-rw-r--r--transport/Android.bp17
-rw-r--r--transport/HidlBinderSupport.cpp14
-rw-r--r--transport/HidlLazyUtils.cpp5
-rw-r--r--transport/HidlTransportSupport.cpp15
-rw-r--r--transport/InternalStatic.h11
-rw-r--r--transport/ServiceManagement.cpp109
-rw-r--r--transport/allocator/1.0/Android.bp1
-rw-r--r--transport/allocator/1.0/default/Android.bp2
-rw-r--r--transport/allocator/1.0/utils/Android.bp1
-rw-r--r--transport/base/1.0/Android.bp1
-rw-r--r--transport/base/1.0/vts/functional/Android.bp9
-rw-r--r--transport/base/1.0/vts/functional/vts_ibase_test.cpp142
-rw-r--r--transport/include/hidl/HidlBinderSupport.h130
-rw-r--r--transport/include/hidl/HidlLazyUtils.h9
-rw-r--r--transport/include/hidl/HidlTransportSupport.h13
-rw-r--r--transport/include/hidl/LegacySupport.h75
-rw-r--r--transport/include/hidl/ServiceManagement.h9
-rw-r--r--transport/include/hidl/Static.h11
-rw-r--r--transport/manager/1.0/Android.bp1
-rw-r--r--transport/manager/1.1/Android.bp1
-rw-r--r--transport/manager/1.2/Android.bp1
-rw-r--r--transport/memory/1.0/Android.bp1
-rw-r--r--transport/memory/1.0/default/Android.bp2
-rw-r--r--transport/memory/1.0/default/HidlFetch.cpp4
-rw-r--r--transport/safe_union/1.0/Android.bp1
-rw-r--r--transport/token/1.0/Android.bp1
-rw-r--r--transport/token/1.0/utils/Android.bp10
-rw-r--r--transport/token/1.0/utils/HybridInterface.cpp3
-rw-r--r--transport/token/1.0/utils/include/hidl/HybridInterface.h7
50 files changed, 1419 insertions, 711 deletions
diff --git a/Android.bp b/Android.bp
index 9207656..727f07f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,21 +22,8 @@ cc_defaults {
],
}
-phony {
- name: "libhidl",
- required: [
- "libhidlbase",
- ],
-}
-
-cc_library_headers {
- name: "libhidl_gtest_helper",
- export_include_dirs: ["gtest_helper"],
-}
-
cc_test {
name: "libhidl_test",
- host_supported: true,
defaults: ["libhidl-defaults"],
gtest: false,
srcs: ["test_main.cpp"],
@@ -46,6 +33,8 @@ cc_test {
"android.hidl.memory@1.0",
"libbase",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libutils",
"libcutils",
@@ -76,7 +65,6 @@ cc_defaults {
cc_library {
name: "libhidlbase",
defaults: ["libhidlbase-combined-impl"],
- host_supported: true,
recovery_available: true,
vendor_available: true,
vndk: {
@@ -101,8 +89,6 @@ cc_library {
whole_static_libs: [
"libhwbinder_pgo-impl-internal",
],
-
- visibility: ["//system/libhwbinder:__subpackages__"],
}
// WARNING: deprecated
@@ -110,5 +96,10 @@ cc_library {
// on libhidlbase instead.
cc_library {
name: "libhidltransport",
+ recovery_available: true,
vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index c4a663e..3e17fc4 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,9 +2,6 @@
"presubmit": [
{
"name": "libhidl_test"
- },
- {
- "name": "hidl_implementation_test"
}
]
}
diff --git a/adapter/Android.bp b/adapter/Android.bp
index ae801bc..eb322bc 100644
--- a/adapter/Android.bp
+++ b/adapter/Android.bp
@@ -23,11 +23,14 @@ cc_library {
shared_libs: [
"libbase",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libutils",
],
export_shared_lib_headers: [
"libhidlbase",
+ "libhidltransport",
"libutils",
],
}
diff --git a/base/Android.bp b/base/Android.bp
index ca4e259..8fe2702 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -28,9 +28,8 @@ cc_defaults {
cc_library {
name: "libhidlbase-impl-internal",
- host_supported: true,
- recovery_available: true,
vendor_available: true,
+ recovery_available: true,
defaults: [
"libhidlbase-impl-shared-libs",
"libhidl-defaults"
@@ -54,6 +53,4 @@ cc_library {
cflags: ["-DLIBHIDL_TARGET_DEBUGGABLE"],
},
},
-
- visibility: ["//system/libhidl:__subpackages__"],
}
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index 956effd..440b30f 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -21,6 +21,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
#ifdef LIBHIDL_TARGET_DEBUGGABLE
#include <dirent.h>
@@ -55,7 +56,7 @@ std::string getVndkVersionStr() {
// "0" means the vndkVersion must be initialized with the property value.
// Otherwise, return the value.
if (vndkVersion == "0") {
- vndkVersion = base::GetProperty("ro.vndk.version", "");
+ vndkVersion = android::base::GetProperty("ro.vndk.version", "");
if (vndkVersion != "" && vndkVersion != "current") {
vndkVersion = "-" + vndkVersion;
} else {
@@ -75,44 +76,44 @@ HidlInstrumentor::HidlInstrumentor(const std::string& package, const std::string
configureInstrumentation(false);
if (__sanitizer_cov_dump != nullptr) {
::android::add_sysprop_change_callback(
- []() {
- bool enableCoverage = base::GetBoolProperty(kSysPropHalCoverage, false);
- if (enableCoverage) {
- __sanitizer_cov_dump();
- }
- },
- 0);
+ []() {
+ bool enableCoverage = property_get_bool(kSysPropHalCoverage, false);
+ if (enableCoverage) {
+ __sanitizer_cov_dump();
+ }
+ },
+ 0);
}
- if (base::GetBoolProperty("ro.vts.coverage", false)) {
+ if (property_get_bool("ro.vts.coverage", false)) {
const char* prefixOverride = getenv(kGcovPrefixOverrideEnvVar);
if (prefixOverride == nullptr || strcmp(prefixOverride, "true") != 0) {
const std::string gcovPath = kGcovPrefixPath + std::to_string(getpid());
setenv(kGcovPrefixEnvVar, gcovPath.c_str(), true /* overwrite */);
}
::android::add_sysprop_change_callback(
- []() {
- const bool enableCoverage = base::GetBoolProperty(kSysPropHalCoverage, false);
- if (enableCoverage) {
- dl_iterate_phdr(
- [](struct dl_phdr_info* info, size_t /* size */, void* /* data */) {
- if (strlen(info->dlpi_name) == 0) return 0;
-
- void* handle = dlopen(info->dlpi_name, RTLD_LAZY);
- if (handle == nullptr) {
- LOG(INFO) << "coverage dlopen failed: " << dlerror();
- return 0;
- }
- void (*flush)() = (void (*)())dlsym(handle, "__gcov_flush");
- if (flush == nullptr) {
- return 0;
- }
- flush();
- return 0;
- },
- nullptr /* data */);
- }
- },
- 0 /* priority */);
+ []() {
+ const bool enableCoverage = property_get_bool(kSysPropHalCoverage, false);
+ if (enableCoverage) {
+ dl_iterate_phdr(
+ [](struct dl_phdr_info* info, size_t /* size */, void* /* data */) {
+ if (strlen(info->dlpi_name) == 0) return 0;
+
+ void* handle = dlopen(info->dlpi_name, RTLD_LAZY);
+ if (handle == nullptr) {
+ LOG(INFO) << "coverage dlopen failed: " << dlerror();
+ return 0;
+ }
+ void (*flush)() = (void (*)())dlsym(handle, "__gcov_flush");
+ if (flush == nullptr) {
+ return 0;
+ }
+ flush();
+ return 0;
+ },
+ nullptr /* data */);
+ }
+ },
+ 0 /* priority */);
}
#endif
}
@@ -120,7 +121,7 @@ HidlInstrumentor::HidlInstrumentor(const std::string& package, const std::string
HidlInstrumentor::~HidlInstrumentor() {}
void HidlInstrumentor::configureInstrumentation(bool log) {
- mEnableInstrumentation = base::GetBoolProperty("hal.instrumentation.enable", false);
+ mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
if (mEnableInstrumentation) {
if (log) {
LOG(INFO) << "Enable instrumentation.";
@@ -139,8 +140,8 @@ void HidlInstrumentor::registerInstrumentationCallbacks(
std::vector<InstrumentationCallback> *instrumentationCallbacks) {
#ifdef LIBHIDL_TARGET_DEBUGGABLE
std::vector<std::string> instrumentationLibPaths;
- const std::string instrumentationLibPath = base::GetProperty(kSysPropInstrumentationPath, "");
- if (instrumentationLibPath.size() > 0) {
+ char instrumentationLibPath[PROPERTY_VALUE_MAX];
+ if (property_get(kSysPropInstrumentationPath, instrumentationLibPath, "") > 0) {
instrumentationLibPaths.push_back(instrumentationLibPath);
} else {
static std::string halLibPathVndkSp = android::base::StringPrintf(
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index af805b9..f97f216 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -35,8 +35,10 @@ bool debuggable() {
}
} // namespace details
-hidl_handle::hidl_handle() : mHandle(nullptr), mOwnsHandle(false) {
- memset(mPad, 0, sizeof(mPad));
+hidl_handle::hidl_handle() {
+ memset(this, 0, sizeof(*this));
+ // mHandle = nullptr;
+ // mOwnsHandle = false;
}
hidl_handle::~hidl_handle() {
@@ -136,8 +138,11 @@ void hidl_handle::freeHandle() {
static const char *const kEmptyString = "";
-hidl_string::hidl_string() : mBuffer(kEmptyString), mSize(0), mOwnsBuffer(false) {
- memset(mPad, 0, sizeof(mPad));
+hidl_string::hidl_string() {
+ memset(this, 0, sizeof(*this));
+ // mSize is zero
+ // mOwnsBuffer is false
+ mBuffer = kEmptyString;
}
hidl_string::~hidl_string() {
diff --git a/base/Status.cpp b/base/Status.cpp
index 7698ff8..90474a0 100644
--- a/base/Status.cpp
+++ b/base/Status.cpp
@@ -149,51 +149,36 @@ void setProcessHidlReturnRestriction(HidlReturnRestriction restriction) {
}
namespace details {
- void return_status::onValueRetrieval() const {
+ void return_status::assertOk() const {
if (!isOk()) {
LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description();
}
}
- void return_status::onIgnored() const {
+ return_status::~return_status() {
+ // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
+ if (mCheckedStatus) return;
+
+ if (!isOk()) {
+ LOG(FATAL) << "Failed HIDL return status not checked: " << description();
+ }
+
if (gReturnRestriction == HidlReturnRestriction::NONE) {
return;
}
if (gReturnRestriction == HidlReturnRestriction::ERROR_IF_UNCHECKED) {
LOG(ERROR) << "Failed to check status of HIDL Return.";
- CallStack::logStack("unchecked HIDL return", CallStack::getCurrent(10).get(),
- ANDROID_LOG_ERROR);
+ CallStack::logStack("unchecked HIDL return", CallStack::getCurrent(10).get(), ANDROID_LOG_ERROR);
} else {
LOG(FATAL) << "Failed to check status of HIDL Return.";
}
}
- void return_status::assertOk() const {
- if (!isOk()) {
- LOG(FATAL) << "Failed HIDL return status not checked. Usually this happens because of "
- "a transport error (error parceling, binder driver, or from unparceling)"
- ". If you see this in code calling into \"Bn\" classes in for a HAL "
- "server process, then it is likely that the code there is returning "
- "transport errors there (as opposed to errors defined within its "
- "protocol). Error is: " << description();
- }
- }
-
- return_status::~return_status() {
- // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
- if (mCheckedStatus) return;
-
- assertOk();
- onIgnored();
- }
-
return_status& return_status::operator=(return_status&& other) noexcept {
- if (!mCheckedStatus) {
- assertOk();
- onIgnored();
+ if (!mCheckedStatus && !isOk()) {
+ LOG(FATAL) << "Failed HIDL return status not checked: " << description();
}
-
std::swap(mStatus, other.mStatus);
std::swap(mCheckedStatus, other.mCheckedStatus);
return *this;
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 1b91c26..93a6251 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -20,24 +20,18 @@
#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 <vector>
-
-// no requirements on types not used in scatter/gather
-// no requirements on other libraries
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpadded"
-#include <cutils/native_handle.h>
-#include <hidl/Status.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
-#pragma clang diagnostic pop
+#include <vector>
namespace android {
@@ -129,9 +123,8 @@ struct hidl_handle {
private:
void freeHandle();
- details::hidl_pointer<const native_handle_t> mHandle;
- bool mOwnsHandle;
- uint8_t mPad[7];
+ details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
+ bool mOwnsHandle __attribute ((aligned(8)));
};
struct hidl_string {
@@ -181,7 +174,6 @@ 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 *
- uint8_t mPad[3];
// copy from data with size. Assume that my memory is freed
// (through clear(), for example)
@@ -302,9 +294,9 @@ struct hidl_memory {
static const size_t kOffsetOfName;
private:
- hidl_handle mHandle;
- uint64_t mSize;
- hidl_string mName;
+ hidl_handle mHandle __attribute__ ((aligned(8)));
+ uint64_t mSize __attribute__ ((aligned(8)));
+ hidl_string mName __attribute__ ((aligned(8)));
};
// HidlMemory is a wrapper class to support sp<> for hidl_memory. It also
@@ -334,12 +326,15 @@ protected:
template<typename T>
struct hidl_vec {
- using value_type = T;
-
- hidl_vec() : mBuffer(nullptr), mSize(0), mOwnsBuffer(false) {
+ hidl_vec() {
static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
- memset(mPad, 0, sizeof(mPad));
+ memset(this, 0, sizeof(*this));
+ // mSize is 0
+ // mBuffer is nullptr
+
+ // this is for consistency with the original implementation
+ mOwnsBuffer = true;
}
// Note, does not initialize primitive types.
@@ -515,7 +510,7 @@ struct hidl_vec {
T* newBuffer = new T[size]();
for (size_t i = 0; i < std::min(static_cast<uint32_t>(size), mSize); ++i) {
- newBuffer[i] = std::move(mBuffer[i]);
+ newBuffer[i] = mBuffer[i];
}
if (mOwnsBuffer) {
@@ -576,15 +571,11 @@ public:
iterator end() { return data()+mSize; }
const_iterator begin() const { return data(); }
const_iterator end() const { return data()+mSize; }
- iterator find(const T& v) { return std::find(begin(), end(), v); }
- const_iterator find(const T& v) const { return std::find(begin(), end(), v); }
- bool contains(const T& v) const { return find(v) != end(); }
- private:
+private:
details::hidl_pointer<T> mBuffer;
uint32_t mSize;
bool mOwnsBuffer;
- uint8_t mPad[3];
// copy from an array-like object, assuming my resources are freed.
template <typename Array>
@@ -740,8 +731,6 @@ struct hidl_array {
using std_array_type = typename details::std_array<T, SIZE1, SIZES...>::type;
hidl_array() = default;
- hidl_array(const hidl_array&) noexcept = default;
- hidl_array(hidl_array&&) noexcept = default;
// Copies the data from source, using T::operator=(const T &).
hidl_array(const T *source) {
@@ -756,9 +745,6 @@ struct hidl_array {
modifier = array;
}
- hidl_array& operator=(const hidl_array&) noexcept = default;
- hidl_array& operator=(hidl_array&&) noexcept = default;
-
T *data() { return mBuffer; }
const T *data() const { return mBuffer; }
@@ -807,12 +793,10 @@ private:
// 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 value_type = T;
+
using std_array_type = typename details::std_array<T, SIZE1>::type;
hidl_array() = default;
- hidl_array(const hidl_array&) noexcept = default;
- hidl_array(hidl_array&&) noexcept = default;
// Copies the data from source, using T::operator=(const T &).
hidl_array(const T *source) {
@@ -824,9 +808,6 @@ struct hidl_array<T, SIZE1> {
// Copies the data from the given std::array, using T::operator=(const T &).
hidl_array(const std_array_type &array) : hidl_array(array.data()) {}
- hidl_array& operator=(const hidl_array&) noexcept = default;
- hidl_array& operator=(hidl_array&&) noexcept = default;
-
T *data() { return mBuffer; }
const T *data() const { return mBuffer; }
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index 74901bb..817277f 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -141,15 +141,8 @@ namespace details {
Status mStatus {};
mutable bool mCheckedStatus = false;
- // called when an unchecked status is discarded
- // makes sure this status is checked according to the preference
- // set by setProcessHidlReturnRestriction
- void onIgnored() const;
-
template <typename T, typename U>
friend Return<U> StatusOf(const Return<T> &other);
- protected:
- void onValueRetrieval() const;
public:
void assertOk() const;
return_status() {}
@@ -231,7 +224,7 @@ public:
~Return() = default;
operator T() const {
- onValueRetrieval(); // assert okay
+ assertOk();
return mVal;
}
@@ -260,7 +253,7 @@ public:
~Return() = default;
operator sp<T>() const {
- onValueRetrieval(); // assert okay
+ assertOk();
return mVal;
}
diff --git a/gtest_helper/hidl/GtestPrinter.h b/gtest_helper/hidl/GtestPrinter.h
deleted file mode 100644
index 4b5ac2d..0000000
--- a/gtest_helper/hidl/GtestPrinter.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 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 <gtest/gtest.h>
-
-namespace android {
-namespace hardware {
-
-static inline std::string Sanitize(std::string name) {
- for (size_t i = 0; i < name.size(); i++) {
- // gtest test names must only contain alphanumeric characters
- if (!std::isalnum(name[i])) name[i] = '_';
- }
- return name;
-}
-
-static inline std::string PrintInstanceNameToString(
- const testing::TestParamInfo<std::string>& info) {
- // test names need to be unique -> index prefix
- std::string name = std::to_string(info.index) + "/" + info.param;
- return Sanitize(name);
-}
-
-template <typename... T>
-static inline std::string PrintInstanceTupleNameToString(
- const testing::TestParamInfo<std::tuple<T...>>& info) {
- std::vector<std::string> instances = std::apply(
- [](auto&&... elems) {
- std::vector<std::string> instances;
- instances.reserve(sizeof...(elems));
- (instances.push_back(std::forward<decltype(elems)>(elems)), ...);
- return instances;
- },
- info.param);
- std::string param_string;
- for (const std::string& instance : instances) {
- param_string += instance + "_";
- }
- param_string += std::to_string(info.index);
-
- return Sanitize(param_string);
-}
-
-} // namespace hardware
-} // namespace android
diff --git a/libhidlcache/Android.bp b/libhidlcache/Android.bp
new file mode 100644
index 0000000..d28a4f1
--- /dev/null
+++ b/libhidlcache/Android.bp
@@ -0,0 +1,71 @@
+// 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 {
+ name: "libhidlcache",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ defaults: ["libhidl-defaults"],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "libhidlbase",
+ "libhidlmemory",
+ "libhwbinder",
+ "libhidltransport",
+ "android.hidl.memory@1.0",
+ "android.hidl.memory.block@1.0",
+ "android.hidl.memory.token@1.0",
+ ],
+ export_include_dirs: ["include"],
+
+ export_shared_lib_headers: [
+ "android.hidl.memory@1.0",
+ "android.hidl.memory.block@1.0",
+ "android.hidl.memory.token@1.0",
+ "libhidlbase",
+ ],
+ srcs: [
+ "HidlMemoryCache.cpp",
+ "MemoryDealer.cpp",
+ "mapping.cpp",
+ ],
+}
+
+cc_test {
+ name: "libhidlcache_test",
+ defaults: ["hidl-gen-defaults"],
+
+ shared_libs: [
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.memory.block@1.0",
+ "android.hidl.memory.token@1.0",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "libhidlmemory",
+ "libhidlcache",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+
+ srcs: ["libhidlcache_test.cpp"],
+}
diff --git a/libhidlcache/HidlCache.h b/libhidlcache/HidlCache.h
new file mode 100644
index 0000000..39a7b3a
--- /dev/null
+++ b/libhidlcache/HidlCache.h
@@ -0,0 +1,143 @@
+/*
+ * 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_HARDWARE_HIDL_CACHE_H
+#define ANDROID_HARDWARE_HIDL_CACHE_H
+
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+
+// A generic cache to map Key to sp<Value>. The cache records are kept with
+// wp<Value>, so that it does not block the Value to be garbage collected
+// when there's no other sp<> externally.
+template <class Key, class Value, class Compare = std::less<Key>>
+class HidlCache : public virtual RefBase {
+ using Mutex = std::mutex;
+ using Lock = std::lock_guard<Mutex>;
+
+ public:
+ // A RAII class to manage lock/unlock HidlCache.
+ class HidlCacheLock : public virtual RefBase {
+ public:
+ HidlCacheLock(sp<HidlCache> cache, const Key& key) : mCache(cache), mKey(key) {
+ mCache->lock(mKey);
+ }
+ ~HidlCacheLock() { mCache->unlock(mKey); }
+
+ private:
+ sp<HidlCache> mCache;
+ const Key mKey;
+ };
+ // lock the IMemory refered by key and keep it alive even if there's no
+ // other memory block refers to.
+ virtual bool lock(const Key& key);
+ virtual sp<Value> unlock(const Key& key);
+ virtual bool flush(const Key& key);
+ // fetch the sp<Value> with key from cache,
+ // make a new instance with fill() if it does not present currently.
+ virtual sp<Value> fetch(const Key& key);
+ virtual sp<HidlCacheLock> lockGuard(const Key& key) { return new HidlCacheLock(this, key); }
+
+ virtual ~HidlCache() {}
+
+ protected:
+ friend void HidlCacheWhiteBoxTest();
+ // This method shall be called with a lock held
+ virtual sp<Value> fillLocked(const Key& key) = 0;
+
+ // @return nullptr if it does not present currently.
+ // @note This method shall be called with a lock held
+ virtual sp<Value> getCachedLocked(const Key& key);
+ bool cached(Key key) const { return mCached.count(key) > 0; }
+ bool locked(Key key) const { return mLocked.count(key) > 0; }
+ Mutex mMutex;
+
+ std::map<Key, wp<Value>, Compare> mCached;
+ std::map<Key, sp<Value>, Compare> mLocked;
+};
+
+template <class Key, class Value, class Compare>
+bool HidlCache<Key, Value, Compare>::lock(const Key& key) {
+ {
+ Lock lock(mMutex);
+ if (cached(key)) {
+ sp<Value> im = mCached[key].promote();
+ if (im != nullptr) {
+ mLocked[key] = im;
+ return true;
+ } else {
+ mCached.erase(key);
+ }
+ }
+ }
+ sp<Value> value = fetch(key);
+ if (value == nullptr) {
+ return false;
+ } else {
+ Lock lock(mMutex);
+ mLocked[key] = value;
+ return true;
+ }
+}
+
+template <class Key, class Value, class Compare>
+sp<Value> HidlCache<Key, Value, Compare>::unlock(const Key& key) {
+ Lock lock(mMutex);
+ if (locked(key)) {
+ sp<Value> v = mLocked[key];
+ mLocked.erase(key);
+ return v;
+ }
+ return nullptr;
+}
+
+template <class Key, class Value, class Compare>
+bool HidlCache<Key, Value, Compare>::flush(const Key& key) {
+ Lock lock(mMutex);
+ bool contain = cached(key);
+ mCached.erase(key);
+ return contain;
+}
+
+template <class Key, class Value, class Compare>
+sp<Value> HidlCache<Key, Value, Compare>::getCachedLocked(const Key& key) {
+ if (cached(key)) {
+ wp<Value> cache = mCached[key];
+ sp<Value> mem = cache.promote();
+ if (mem != nullptr) {
+ return mem;
+ } else {
+ mCached.erase(key);
+ }
+ }
+ return nullptr;
+}
+
+template <class Key, class Value, class Compare>
+sp<Value> HidlCache<Key, Value, Compare>::fetch(const Key& key) {
+ Lock lock(mMutex);
+ sp<Value> value = getCachedLocked(key);
+
+ if (value == nullptr) {
+ value = fillLocked(key);
+ }
+ return value;
+}
+
+} // namespace hardware
+} // namespace android
+#endif
diff --git a/libhidlcache/HidlMemoryCache.cpp b/libhidlcache/HidlMemoryCache.cpp
new file mode 100644
index 0000000..a23c388
--- /dev/null
+++ b/libhidlcache/HidlMemoryCache.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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 "HidlMemoryCache"
+#include "HidlMemoryCache.h"
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hidl/memory/token/1.0/IMemoryToken.h>
+#include <hidlmemory/mapping.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+
+using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
+using IMemory = ::android::hidl::memory::V1_0::IMemory;
+
+class MemoryDecorator : public virtual IMemory {
+ public:
+ MemoryDecorator(const sp<IMemory>& heap) : mHeap(heap) {}
+ virtual ~MemoryDecorator() {}
+ Return<void> update() override { return mHeap->update(); }
+ Return<void> read() override { return mHeap->read(); }
+ Return<void> updateRange(uint64_t start, uint64_t length) override {
+ return mHeap->updateRange(start, length);
+ }
+ Return<void> readRange(uint64_t start, uint64_t length) override {
+ return mHeap->readRange(start, length);
+ }
+ Return<void> commit() override { return mHeap->commit(); }
+
+ Return<void*> getPointer() override { return mHeap->getPointer(); }
+ Return<uint64_t> getSize() override { return mHeap->getSize(); }
+
+ protected:
+ sp<IMemory> mHeap;
+};
+
+class MemoryCacheable : public virtual MemoryDecorator {
+ public:
+ MemoryCacheable(const sp<IMemory>& heap, sp<IMemoryToken> key)
+ : MemoryDecorator(heap), mKey(key) {}
+ virtual ~MemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
+
+ protected:
+ sp<IMemoryToken> mKey;
+};
+
+class MemoryBlockImpl : public virtual IMemory {
+ public:
+ MemoryBlockImpl(const sp<IMemory>& heap, uint64_t size, uint64_t offset)
+ : mHeap(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
+ bool validRange(uint64_t start, uint64_t length) {
+ return (start + length <= mSize) && (start + length >= start) &&
+ (mOffset + mSize <= mHeapSize);
+ }
+ Return<void> readRange(uint64_t start, uint64_t length) override {
+ if (!validRange(start, length)) {
+ ALOGE("IMemoryBlock::readRange: out of range");
+ return Void();
+ }
+ return mHeap->readRange(mOffset + start, length);
+ }
+ Return<void> updateRange(uint64_t start, uint64_t length) override {
+ if (!validRange(start, length)) {
+ ALOGE("IMemoryBlock::updateRange: out of range");
+ return Void();
+ }
+ return mHeap->updateRange(mOffset + start, length);
+ }
+ Return<void> read() override { return this->readRange(0, mSize); }
+ Return<void> update() override { return this->updateRange(0, mSize); }
+ Return<void> commit() override { return mHeap->commit(); }
+ Return<uint64_t> getSize() override { return mSize; }
+ Return<void*> getPointer() override {
+ void* p = mHeap->getPointer();
+ return (static_cast<char*>(p) + mOffset);
+ }
+
+ protected:
+ sp<IMemory> mHeap;
+ uint64_t mSize;
+ uint64_t mOffset;
+ uint64_t mHeapSize;
+};
+
+sp<HidlMemoryCache> HidlMemoryCache::getInstance() {
+ static sp<HidlMemoryCache> instance = new HidlMemoryCache();
+ return instance;
+}
+
+sp<IMemory> HidlMemoryCache::fillLocked(const sp<IMemoryToken>& key) {
+ sp<IMemory> memory = nullptr;
+ Return<void> ret = key->get(
+ [&](const hidl_memory& mem) { memory = new MemoryCacheable(mapMemory(mem), key); });
+ if (!ret.isOk()) {
+ ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get.");
+ return nullptr;
+ }
+ mCached[key] = memory;
+ return memory;
+}
+
+sp<IMemory> HidlMemoryCache::map(const MemoryBlock& memblk) {
+ sp<IMemoryToken> token = memblk.token;
+ sp<IMemory> heap = fetch(token);
+ if (heap == nullptr) {
+ return nullptr;
+ }
+ return new MemoryBlockImpl(heap, memblk.size, memblk.offset);
+}
+
+} // namespace hardware
+} // namespace android
diff --git a/libhidlcache/HidlMemoryCache.h b/libhidlcache/HidlMemoryCache.h
new file mode 100644
index 0000000..c9a533b
--- /dev/null
+++ b/libhidlcache/HidlMemoryCache.h
@@ -0,0 +1,62 @@
+/*
+ * 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_HARDWARD_HIDLMEMORY_CACHE_H
+#define ANDROID_HARDWARD_HIDLMEMORY_CACHE_H
+
+#include <android/hidl/memory/block/1.0/types.h>
+#include <android/hidl/memory/token/1.0/IMemoryToken.h>
+#include <hidl/HidlBinderSupport.h>
+#include <hwbinder/IBinder.h>
+#include <utils/RefBase.h>
+#include "HidlCache.h"
+
+namespace android {
+namespace hardware {
+
+struct IMemoryTokenCompare {
+ using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
+ bool operator()(const sp<IMemoryToken>& lhs, const sp<IMemoryToken>& rhs) const {
+ sp<IBinder> lb = toBinder<IMemoryToken>(lhs);
+ sp<IBinder> rb = toBinder<IMemoryToken>(rhs);
+ return lb < rb;
+ }
+};
+
+// The HidlMemoryCache is a singleton class to provides cache for
+// IMemoryToken => ::android::hidl::memory::V1_0::IMemory
+// It's an abstraction layer on top of the IMapper and supports, but is
+// not limited to, the Ashmem type HidlMemory.
+class HidlMemoryCache
+ : public virtual HidlCache<sp<::android::hidl::memory::token::V1_0::IMemoryToken>,
+ ::android::hidl::memory::V1_0::IMemory, IMemoryTokenCompare> {
+ using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
+ using IMemory = ::android::hidl::memory::V1_0::IMemory;
+ using MemoryBlock = ::android::hidl::memory::block::V1_0::MemoryBlock;
+
+ public:
+ virtual sp<IMemory> map(const MemoryBlock& block);
+ // get the singleton
+ static sp<HidlMemoryCache> getInstance();
+
+ protected:
+ HidlMemoryCache() {}
+ virtual sp<IMemory> fillLocked(const sp<IMemoryToken>& key) override;
+};
+
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/libhidlcache/MemoryDealer.cpp b/libhidlcache/MemoryDealer.cpp
new file mode 100644
index 0000000..e5686a7
--- /dev/null
+++ b/libhidlcache/MemoryDealer.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2007 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 "MemoryDealer"
+
+#include <hidlcache/MemoryDealer.h>
+#include <hidlmemory/HidlMemoryToken.h>
+#include <hidlmemory/mapping.h>
+
+#include <list>
+
+#include <log/log.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+using std::string;
+
+namespace android {
+namespace hardware {
+
+class SimpleBestFitAllocator {
+ enum { PAGE_ALIGNED = 0x00000001 };
+
+ public:
+ explicit SimpleBestFitAllocator(size_t size);
+ ~SimpleBestFitAllocator();
+
+ size_t allocate(size_t size, uint32_t flags = 0);
+ status_t deallocate(size_t offset);
+ size_t size() const;
+ void dump(const char* tag) const;
+ void dump(string& res, const char* tag) const;
+
+ static size_t getAllocationAlignment() { return kMemoryAlign; }
+
+ private:
+ struct chunk_t {
+ chunk_t(size_t start, size_t size) : start(start), size(size), free(1) {}
+ size_t start;
+ size_t size : 28;
+ int free : 4;
+ };
+ using List = std::list<chunk_t*>;
+ using Iterator = std::list<chunk_t*>::iterator;
+ using IteratorConst = std::list<chunk_t*>::const_iterator;
+ using Mutex = std::mutex;
+ using Lock = std::lock_guard<Mutex>;
+
+ ssize_t alloc(size_t size, uint32_t flags);
+ chunk_t* dealloc(size_t start);
+ void dump_l(const char* tag) const;
+ void dump_l(string& res, const char* tag) const;
+
+ static const int kMemoryAlign;
+ mutable Mutex mLock;
+ List mList;
+ size_t mHeapSize;
+};
+
+MemoryDealer::MemoryDealer(size_t size) : mAllocator(new SimpleBestFitAllocator(size)) {}
+
+MemoryDealer::~MemoryDealer() {
+ delete mAllocator;
+}
+
+ssize_t MemoryDealer::allocateOffset(size_t size) {
+ return mAllocator->allocate(size);
+}
+
+void MemoryDealer::deallocate(size_t offset) {
+ mAllocator->deallocate(offset);
+}
+
+void MemoryDealer::dump(const char* tag) const {
+ mAllocator->dump(tag);
+}
+
+size_t MemoryDealer::getAllocationAlignment() {
+ return SimpleBestFitAllocator::getAllocationAlignment();
+}
+
+// align all the memory blocks on a cache-line boundary
+const int SimpleBestFitAllocator::kMemoryAlign = 32;
+
+SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) {
+ size_t pagesize = getpagesize();
+ mHeapSize = ((size + pagesize - 1) & ~(pagesize - 1));
+
+ chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
+ mList.push_front(node);
+}
+
+SimpleBestFitAllocator::~SimpleBestFitAllocator() {
+ while (mList.size() != 0) {
+ chunk_t* removed = mList.front();
+ mList.pop_front();
+#ifdef __clang_analyzer__
+ // Clang static analyzer gets confused in this loop
+ // and generates a false positive warning about accessing
+ // memory that is already freed.
+ // Add an "assert" to avoid the confusion.
+ LOG_ALWAYS_FATAL_IF(mList.front() == removed);
+#endif
+ delete removed;
+ }
+}
+
+size_t SimpleBestFitAllocator::size() const {
+ return mHeapSize;
+}
+
+size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) {
+ Lock lock(mLock);
+ ssize_t offset = alloc(size, flags);
+ return offset;
+}
+
+status_t SimpleBestFitAllocator::deallocate(size_t offset) {
+ Lock lock(mLock);
+ chunk_t const* const freed = dealloc(offset);
+ if (freed) {
+ return NO_ERROR;
+ }
+ return NAME_NOT_FOUND;
+}
+
+ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) {
+ if (size == 0) {
+ return 0;
+ }
+ size = (size + kMemoryAlign - 1) / kMemoryAlign;
+ size_t pagesize = getpagesize();
+
+ Iterator free_chunk_p = mList.end();
+ for (Iterator p = mList.begin(); p != mList.end(); p++) {
+ chunk_t* cur = *p;
+ int extra = 0;
+ if (flags & PAGE_ALIGNED) extra = (-cur->start & ((pagesize / kMemoryAlign) - 1));
+
+ // best fit
+ if (cur->free && (cur->size >= (size + extra))) {
+ if ((free_chunk_p == mList.end()) || (cur->size < (*free_chunk_p)->size)) {
+ free_chunk_p = p;
+ }
+ if (cur->size == size) {
+ break;
+ }
+ }
+ }
+ if (free_chunk_p != mList.end()) {
+ chunk_t* free_chunk = *free_chunk_p;
+ const size_t free_size = free_chunk->size;
+ free_chunk->free = 0;
+ free_chunk->size = size;
+ if (free_size > size) {
+ int extra = 0;
+ if (flags & PAGE_ALIGNED)
+ extra = (-free_chunk->start & ((pagesize / kMemoryAlign) - 1));
+ if (extra) {
+ chunk_t* split = new chunk_t(free_chunk->start, extra);
+ free_chunk->start += extra;
+ mList.insert(free_chunk_p, split);
+ }
+
+ ALOGE_IF(
+ (flags & PAGE_ALIGNED) && ((free_chunk->start * kMemoryAlign) & (pagesize - 1)),
+ "PAGE_ALIGNED requested, but page is not aligned!!!");
+
+ const ssize_t tail_free = free_size - (size + extra);
+ if (tail_free > 0) {
+ chunk_t* split = new chunk_t(free_chunk->start + free_chunk->size, tail_free);
+ mList.insert(++free_chunk_p, split);
+ }
+ }
+ return (free_chunk->start) * kMemoryAlign;
+ }
+ return NO_MEMORY;
+}
+
+SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) {
+ start = start / kMemoryAlign;
+
+ for (Iterator pos = mList.begin(); pos != mList.end(); pos++) {
+ chunk_t* cur = *pos;
+ if (cur->start == start) {
+ LOG_FATAL_IF(cur->free, "block at offset 0x%08lX of size 0x%08lX already freed",
+ cur->start * kMemoryAlign, cur->size * kMemoryAlign);
+
+ // merge freed blocks together
+ chunk_t* freed = cur;
+ cur->free = 1;
+ do {
+ if (pos != mList.begin()) {
+ pos--;
+ chunk_t* const p = *pos;
+ pos++;
+ if (p->free || !cur->size) {
+ freed = p;
+ p->size += cur->size;
+ pos = mList.erase(pos);
+ delete cur;
+ if (pos == mList.end()) break;
+ }
+ }
+ if (++pos == mList.end()) break;
+ cur = *pos;
+ } while (cur && cur->free);
+
+#ifndef NDEBUG
+ if (!freed->free) {
+ dump_l("dealloc (!freed->free)");
+ }
+#endif
+ LOG_FATAL_IF(!freed->free, "freed block at offset 0x%08lX of size 0x%08lX is not free!",
+ freed->start * kMemoryAlign, freed->size * kMemoryAlign);
+
+ return freed;
+ }
+ }
+ return nullptr;
+}
+
+void SimpleBestFitAllocator::dump(const char* tag) const {
+ Lock lock(mLock);
+ dump_l(tag);
+}
+
+void SimpleBestFitAllocator::dump_l(const char* tag) const {
+ string result;
+ dump_l(result, tag);
+ ALOGD("%s", result.c_str());
+}
+
+void SimpleBestFitAllocator::dump(string& result, const char* tag) const {
+ Lock lock(mLock);
+ dump_l(result, tag);
+}
+
+void SimpleBestFitAllocator::dump_l(string& result, const char* tag) const {
+ size_t size = 0;
+ int32_t i = 0;
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ snprintf(buffer, SIZE, " %s (%p, size=%u)\n", tag, this, (unsigned int)mHeapSize);
+
+ result.append(buffer);
+
+ for (IteratorConst pos = mList.begin(); pos != mList.end(); pos++) {
+ chunk_t const* cur = *pos;
+
+ if (!cur->free) size += cur->size * kMemoryAlign;
+
+ i++;
+ }
+ snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size / 1024));
+ result.append(buffer);
+}
+
+bool HidlMemoryDealer::isOk(const MemoryBlock& memblk) {
+ return memblk.token != nullptr;
+}
+
+sp<::android::hidl::memory::V1_0::IMemory> HidlMemoryDealer::heap() {
+ return mHeap;
+}
+
+// The required heap size alignment is 4096 bytes
+static const uint64_t kHeapSizeAlignment = (0x1ULL << 12);
+
+sp<HidlMemoryDealer> HidlMemoryDealer::getInstance(const hidl_memory& mem) {
+ uint64_t msk = (kHeapSizeAlignment - 1);
+ if (mem.size() & msk || !(mem.size() & ~msk)) {
+ ALOGE("size is not aligned to %x", static_cast<uint32_t>(kHeapSizeAlignment));
+ return nullptr;
+ }
+ sp<IMemory> heap = mapMemory(mem);
+ if (heap == nullptr) {
+ ALOGE("fail to mapMemory");
+ return nullptr;
+ }
+ return new HidlMemoryDealer(heap, mem);
+}
+
+HidlMemoryDealer::HidlMemoryDealer(sp<IMemory> heap, const hidl_memory& mem)
+ : MemoryDealer(heap->getSize()),
+ mHeap(heap),
+ mToken(new HidlMemoryToken(HidlMemory::getInstance(mem))) {}
+
+::android::hidl::memory::block::V1_0::MemoryBlock HidlMemoryDealer::allocate(size_t size) {
+ MemoryBlock memblk = {nullptr, 0xFFFFFFFFULL, 0xFFFFFFFFULL};
+ ssize_t offset = allocateOffset(size);
+ if (offset >= 0) {
+ memblk.token = mToken;
+ memblk.size = size;
+ memblk.offset = offset;
+ }
+ return memblk;
+}
+
+}; // namespace hardware
+}; // namespace android
diff --git a/libhidlcache/include/hidlcache/MemoryDealer.h b/libhidlcache/include/hidlcache/MemoryDealer.h
new file mode 100644
index 0000000..fceed83
--- /dev/null
+++ b/libhidlcache/include/hidlcache/MemoryDealer.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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_MEMORY_DEALER_H
+#define ANDROID_HIDL_MEMORY_DEALER_H
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hidl/memory/block/1.0/types.h>
+#include <stdint.h>
+#include <sys/types.h>
+namespace android {
+namespace hardware {
+
+class SimpleBestFitAllocator;
+
+// MemoryDealer allocates/deallocates blocks from a continuous memory region.
+// It operates on size and offset and does not depend on any specific data types.
+class MemoryDealer : public RefBase {
+ public:
+ /// Allocate a block with size. The allocated block is identified with an
+ /// offset. For example:
+ /// ssize_t K = dealer->allocateOffset(size);
+ /// On success, K is positive and points to a subregion K ~ (K+size-1) in the heap.
+ /// It's negative if the allocation fails.
+ virtual ssize_t allocateOffset(size_t size);
+ /// @param offset It points to the block that allocated with allocateOffset previously.
+ virtual void deallocate(size_t offset);
+ /// @param tag a string tag used to mark the dump message
+ virtual void dump(const char* tag) const;
+
+ // allocations are aligned to some value. return that value so clients can account for it.
+ static size_t getAllocationAlignment();
+
+ MemoryDealer(size_t size);
+ virtual ~MemoryDealer();
+
+ protected:
+ SimpleBestFitAllocator* mAllocator;
+};
+
+// It extends the generic MemoryDealer and uses
+// - sp<IMemory> to represent the main memory region.
+// - MemoryBlock to represent the the block to allocate/deallocate
+class HidlMemoryDealer : public MemoryDealer {
+ using IMemory = ::android::hidl::memory::V1_0::IMemory;
+ using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
+ using MemoryBlock = ::android::hidl::memory::block::V1_0::MemoryBlock;
+
+ public:
+ static bool isOk(const MemoryBlock& memblk);
+ /// @param memory The memory size must align to 4096 bytes
+ static sp<HidlMemoryDealer> getInstance(const hidl_memory& memory);
+ virtual MemoryBlock allocate(size_t size);
+ virtual sp<IMemory> heap();
+
+ protected:
+ /// @param heap It must be acquired with mapMemory(memory) with its
+ /// argument corresponds to the 2nd argument passed to HidlMemoryDealer.
+ HidlMemoryDealer(sp<IMemory> heap, const hidl_memory& memory);
+ sp<IMemory> mHeap;
+ sp<IMemoryToken> mToken;
+};
+
+}; // namespace hardware
+}; // namespace android
+
+#endif // ANDROID_HIDL_MEMORY_DEALER_H
diff --git a/libhidlcache/include/hidlcache/mapping.h b/libhidlcache/include/hidlcache/mapping.h
new file mode 100644
index 0000000..972b7b5
--- /dev/null
+++ b/libhidlcache/include/hidlcache/mapping.h
@@ -0,0 +1,54 @@
+/*
+ * 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_HARDWARE_CACHE_MAPPING_H
+#define ANDROID_HARDWARE_CACHE_MAPPING_H
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hidl/memory/block/1.0/types.h>
+#include <android/hidl/memory/token/1.0/IMemoryToken.h>
+
+namespace android {
+namespace hardware {
+
+/**
+ * Returns the IMemory instance corresponding to a MemoryBlock. The heap that
+ * a MemoryBlock belongs to is stored in an internal cache to reduce the number
+ * of invocations to the mapMemory(hidl_memory)
+ *
+ * Note, a cache entry is maintained by reference count and may be flushed when
+ * the count decrease to zero. Performance critical part that does not want its
+ * caches to be flushed can use HidlMemoryCacheLock.
+ */
+sp<::android::hidl::memory::V1_0::IMemory> mapMemory(
+ const ::android::hidl::memory::block::V1_0::MemoryBlock& block);
+
+/**
+ * Internally, there's a cache pool to keep IMemory instances for heap regions
+ * that are referred by the MemoryBlock. During development, this
+ * lockMemoryCache(...) method helps to diagnosis whether the cache is effective
+ * for a specific key. It returns a RAII object used to lock an IMemory instance
+ * referred by the key and keep it alive even if the instance is not referred by
+ * any MemoryBlock. If the cache in interest is already effective. It won't differ
+ * much in performance w/ wo/ the lockMemoryCache()
+ *
+ * @note An IMemory instance that is returned from the mapMemory() is
+ * initialized in an unlocked state.
+ */
+sp<RefBase> lockMemoryCache(const sp<::android::hidl::memory::token::V1_0::IMemoryToken> key);
+
+} // namespace hardware
+} // namespace android
+#endif
diff --git a/libhidlcache/libhidlcache_test.cpp b/libhidlcache/libhidlcache_test.cpp
new file mode 100644
index 0000000..e514460
--- /dev/null
+++ b/libhidlcache/libhidlcache_test.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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 "hidl-cache-test"
+
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hidl/memory/token/1.0/IMemoryToken.h>
+#include <gtest/gtest.h>
+#include <hidlcache/MemoryDealer.h>
+#include <hidlcache/mapping.h>
+#include <hidlmemory/HidlMemoryToken.h>
+#include <hidlmemory/mapping.h>
+#include "HidlMemoryCache.h"
+
+#define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
+
+template <typename T>
+static inline ::testing::AssertionResult isOk(const ::android::hardware::Return<T>& ret) {
+ return ret.isOk() ? (::testing::AssertionSuccess() << ret.description())
+ : (::testing::AssertionFailure() << ret.description());
+}
+
+namespace android {
+
+namespace hardware {
+void HidlCacheWhiteBoxTest() {
+ using ::android::hardware::HidlMemoryCache;
+ using ::android::hardware::HidlMemoryToken;
+ using ::android::hidl::allocator::V1_0::IAllocator;
+ using ::android::hidl::memory::V1_0::IMemory;
+ using ::android::hidl::memory::token::V1_0::IMemoryToken;
+ using ::android::hidl::memory::block::V1_0::MemoryBlock;
+
+ sp<IAllocator> ashmemAllocator;
+
+ ashmemAllocator = IAllocator::getService("ashmem");
+ ASSERT_NE(nullptr, ashmemAllocator.get());
+ ASSERT_TRUE(ashmemAllocator->isRemote()); // allocator is always remote
+
+ sp<HidlMemory> mem;
+ EXPECT_OK(ashmemAllocator->allocate(1024, [&](bool success, const hidl_memory& _mem) {
+ ASSERT_TRUE(success);
+ mem = HidlMemory::getInstance(_mem);
+ }));
+
+ sp<IMemoryToken> token = new HidlMemoryToken(mem);
+
+ MemoryBlock blk = {token, 0x200 /* size */, 0x100 /* offset */};
+ sp<IMemoryToken> mtoken = blk.token;
+ mtoken->get([&](const hidl_memory& mem) { sp<IMemory> memory = mapMemory(mem); });
+
+ sp<HidlMemoryCache> cache = HidlMemoryCache::getInstance();
+ EXPECT_FALSE(cache->cached(token));
+
+ MemoryBlock blk2 = {token, 0x200 /* size */, 0x300 /* offset */};
+
+ EXPECT_FALSE(cache->cached(token));
+
+ {
+ sp<IMemory> mem1 = cache->fetch(token);
+ EXPECT_TRUE(cache->cached(token));
+ EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
+ sp<IMemory> mem2 = cache->fetch(token);
+ EXPECT_TRUE(cache->cached(token));
+ EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
+ }
+ EXPECT_FALSE(cache->cached(token));
+ {
+ sp<IMemory> mem1 = mapMemory(blk);
+ EXPECT_TRUE(cache->cached(token));
+ EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
+ uint8_t* data = static_cast<uint8_t*>(static_cast<void*>(mem1->getPointer()));
+ EXPECT_NE(nullptr, data);
+ }
+ {
+ sp<IMemory> mem2 = mapMemory(blk);
+ EXPECT_TRUE(cache->cached(token));
+ EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
+ }
+ EXPECT_FALSE(cache->cached(token));
+ EXPECT_TRUE(cache->lock(token));
+ EXPECT_TRUE(cache->cached(token));
+ EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
+ EXPECT_TRUE(cache->unlock(token));
+ EXPECT_FALSE(cache->cached(token));
+}
+} // namespace hardware
+
+class HidlCacheTest : public ::testing::Test {};
+
+TEST_F(HidlCacheTest, TestAll) {
+ hardware::HidlCacheWhiteBoxTest();
+}
+
+TEST_F(HidlCacheTest, MemoryDealer) {
+ using ::android::hardware::HidlMemory;
+ using ::android::hardware::hidl_memory;
+ using ::android::hardware::HidlMemoryDealer;
+ using ::android::hidl::allocator::V1_0::IAllocator;
+ using ::android::hidl::memory::block::V1_0::MemoryBlock;
+
+ sp<IAllocator> ashmemAllocator;
+
+ ashmemAllocator = IAllocator::getService("ashmem");
+ sp<HidlMemory> m1;
+ sp<HidlMemory> m2;
+ // test MemoryDealer
+ EXPECT_OK(ashmemAllocator->allocate(2048, [&m1](bool success, const hidl_memory& mem) {
+ ASSERT_TRUE(success);
+ m1 = HidlMemory::getInstance(mem);
+ }));
+
+ EXPECT_OK(ashmemAllocator->allocate(4096, [&m2](bool success, const hidl_memory& mem) {
+ ASSERT_TRUE(success);
+ m2 = HidlMemory::getInstance(mem);
+ }));
+
+ sp<HidlMemoryDealer> dealer;
+
+ // m1 does not statisfy the alignment requirement and should fail.
+ dealer = HidlMemoryDealer::getInstance(*m1);
+ EXPECT_EQ(nullptr, dealer.get());
+
+ dealer = HidlMemoryDealer::getInstance(*m2);
+ EXPECT_NE(nullptr, dealer.get());
+
+ EXPECT_EQ(dealer->heap()->getSize(), 4096ULL);
+ MemoryBlock blk = dealer->allocate(1024);
+ EXPECT_TRUE(HidlMemoryDealer::isOk(blk));
+ MemoryBlock blk2 = dealer->allocate(2048);
+ EXPECT_TRUE(HidlMemoryDealer::isOk(blk2));
+
+ MemoryBlock blk3 = dealer->allocate(2048);
+ EXPECT_FALSE(HidlMemoryDealer::isOk(blk3));
+ dealer->deallocate(blk2.offset);
+ blk3 = dealer->allocate(2048);
+ EXPECT_TRUE(HidlMemoryDealer::isOk(blk3));
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+} // namespace android \ No newline at end of file
diff --git a/libhidlcache/mapping.cpp b/libhidlcache/mapping.cpp
new file mode 100644
index 0000000..2a23e6f
--- /dev/null
+++ b/libhidlcache/mapping.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "libhidlmemory"
+
+#include <map>
+#include <mutex>
+#include <string>
+
+#include <hidlmemory/mapping.h>
+
+#include <android-base/logging.h>
+#include <hidl/HidlSupport.h>
+#include "HidlMemoryCache.h"
+
+using android::hardware::HidlMemoryCache;
+using android::hidl::memory::block::V1_0::MemoryBlock;
+using android::hidl::memory::token::V1_0::IMemoryToken;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+
+sp<IMemory> mapMemory(const ::android::hidl::memory::block::V1_0::MemoryBlock& block) {
+ sp<HidlMemoryCache> c = HidlMemoryCache::getInstance();
+ return c->map(block);
+}
+
+sp<RefBase> lockMemoryCache(const sp<::android::hidl::memory::token::V1_0::IMemoryToken> key) {
+ sp<HidlMemoryCache> c = HidlMemoryCache::getInstance();
+ return c->lockGuard(key);
+}
+
+} // namespace hardware
+} // namespace android
diff --git a/libhidlmemory/Android.bp b/libhidlmemory/Android.bp
index 2f97d5d..2135ef3 100644
--- a/libhidlmemory/Android.bp
+++ b/libhidlmemory/Android.bp
@@ -26,6 +26,7 @@ cc_library {
"libutils",
"libcutils",
"libhidlbase",
+ "libhidltransport",
"android.hidl.memory@1.0",
"android.hidl.memory.token@1.0",
],
diff --git a/test_main.cpp b/test_main.cpp
index e4cdd29..2b9f52c 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -16,16 +16,11 @@
#define LOG_TAG "LibHidlTest"
-#pragma clang diagnostic push
-#pragma clang diagnostic fatal "-Wpadded"
-#include <hidl/HidlInternal.h>
-#include <hidl/HidlSupport.h>
-#pragma clang diagnostic pop
-
#include <android-base/logging.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <hidl/TaskRunner.h>
@@ -33,12 +28,6 @@
#include <fstream>
#include <vector>
-#ifdef __ANDROID__
-static bool kAndroid = true;
-#else
-static bool kAndroid = false;
-#endif
-
#define EXPECT_ARRAYEQ(__a1__, __a2__, __size__) EXPECT_TRUE(isArrayEqual(__a1__, __a2__, __size__))
#define EXPECT_2DARRAYEQ(__a1__, __a2__, __size1__, __size2__) \
EXPECT_TRUE(is2dArrayEqual(__a1__, __a2__, __size1__, __size2__))
@@ -330,72 +319,6 @@ TEST_F(LibHidlTest, VecRangeCtorTest) {
EXPECT_EQ(sum, 1 + 2 + 3);
}
-struct FailsIfCopied {
- FailsIfCopied() {}
-
- // add failure if copied since in general this can be expensive
- FailsIfCopied(const FailsIfCopied& o) { *this = o; }
- FailsIfCopied& operator=(const FailsIfCopied&) {
- ADD_FAILURE() << "FailsIfCopied copied";
- return *this;
- }
-
- // fine to move this type since in general this is cheaper
- FailsIfCopied(FailsIfCopied&& o) = default;
- FailsIfCopied& operator=(FailsIfCopied&&) = default;
-};
-
-TEST_F(LibHidlTest, VecResizeNoCopy) {
- using android::hardware::hidl_vec;
-
- hidl_vec<FailsIfCopied> noCopies;
- noCopies.resize(3); // instantiates three elements
-
- FailsIfCopied* oldPointer = noCopies.data();
-
- noCopies.resize(6); // should move three elements, not copy
-
- // oldPointer should be invalidated at this point.
- // hidl_vec doesn't currently try to realloc but if it ever switches
- // to an implementation that does, this test wouldn't do anything.
- EXPECT_NE(oldPointer, noCopies.data());
-}
-
-TEST_F(LibHidlTest, VecFindTest) {
- using android::hardware::hidl_vec;
- hidl_vec<int32_t> hv1 = {10, 20, 30, 40};
- const hidl_vec<int32_t> hv2 = {1, 2, 3, 4};
-
- auto it = hv1.find(20);
- EXPECT_EQ(20, *it);
- *it = 21;
- EXPECT_EQ(21, *it);
- it = hv1.find(20);
- EXPECT_EQ(hv1.end(), it);
- it = hv1.find(21);
- EXPECT_EQ(21, *it);
-
- auto cit = hv2.find(4);
- EXPECT_EQ(4, *cit);
-}
-
-TEST_F(LibHidlTest, VecContainsTest) {
- using android::hardware::hidl_vec;
- hidl_vec<int32_t> hv1 = {10, 20, 30, 40};
- const hidl_vec<int32_t> hv2 = {0, 1, 2, 3, 4};
-
- EXPECT_TRUE(hv1.contains(10));
- EXPECT_TRUE(hv1.contains(40));
- EXPECT_FALSE(hv1.contains(1));
- EXPECT_FALSE(hv1.contains(0));
- EXPECT_TRUE(hv2.contains(0));
- EXPECT_FALSE(hv2.contains(10));
-
- hv1[0] = 11;
- EXPECT_FALSE(hv1.contains(10));
- EXPECT_TRUE(hv1.contains(11));
-}
-
TEST_F(LibHidlTest, ArrayTest) {
using android::hardware::hidl_array;
int32_t array[] = {5, 6, 7};
@@ -530,52 +453,6 @@ TEST_F(LibHidlTest, ReturnTest) {
EXPECT_EQ(three, ret.withDefault(three));
}
-TEST_F(LibHidlTest, ReturnDies) {
- using ::android::hardware::Return;
- using ::android::hardware::Status;
-
- EXPECT_DEATH({ Return<void>(Status::fromStatusT(-EBUSY)); }, "");
- EXPECT_DEATH({ Return<void>(Status::fromStatusT(-EBUSY)).isDeadObject(); }, "");
- EXPECT_DEATH(
- {
- Return<int> ret = Return<int>(Status::fromStatusT(-EBUSY));
- int foo = ret; // should crash here
- (void)foo;
- ret.isOk();
- },
- "");
-}
-
-TEST_F(LibHidlTest, DetectUncheckedReturn) {
- using ::android::hardware::HidlReturnRestriction;
- using ::android::hardware::Return;
- using ::android::hardware::setProcessHidlReturnRestriction;
- using ::android::hardware::Status;
-
- setProcessHidlReturnRestriction(HidlReturnRestriction::FATAL_IF_UNCHECKED);
-
- EXPECT_DEATH(
- {
- auto ret = Return<void>(Status::ok());
- (void)ret;
- },
- "");
- EXPECT_DEATH(
- {
- auto ret = Return<void>(Status::ok());
- ret = Return<void>(Status::ok());
- ret.isOk();
- },
- "");
-
- auto ret = Return<void>(Status::ok());
- (void)ret.isOk();
- ret = Return<void>(Status::ok());
- (void)ret.isOk();
-
- setProcessHidlReturnRestriction(HidlReturnRestriction::NONE);
-}
-
std::string toString(const ::android::hardware::Status &s) {
using ::android::hardware::operator<<;
std::ostringstream oss;
@@ -599,10 +476,6 @@ TEST_F(LibHidlTest, StatusStringTest) {
}
TEST_F(LibHidlTest, PreloadTest) {
- // HIDL doesn't have support to load passthrough implementations on host, but we
- // could do this by loading implementations from the output directory
- if (!kAndroid) GTEST_SKIP();
-
using ::android::hardware::preloadPassthroughService;
using ::android::hidl::memory::V1_0::IMemory;
@@ -615,51 +488,6 @@ TEST_F(LibHidlTest, PreloadTest) {
EXPECT_TRUE(isLibraryOpen(kLib));
}
-template <typename T, size_t start, size_t end>
-static void assertZeroInRange(const T* t) {
- static_assert(start < sizeof(T));
- static_assert(end <= sizeof(T));
-
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(t);
-
- for (size_t i = start; i < end; i++) {
- EXPECT_EQ(0, ptr[i]);
- }
-}
-
-template <typename T, size_t start, size_t end>
-static void uninitTest() {
- uint8_t buf[sizeof(T)];
- memset(buf, 0xFF, sizeof(T));
-
- T* type = new (buf) T;
- assertZeroInRange<T, start, end>(type);
- type->~T();
-}
-
-TEST_F(LibHidlTest, HidlVecUninit) {
- using ::android::hardware::hidl_vec;
- struct SomeType {};
- static_assert(sizeof(hidl_vec<SomeType>) == 16);
-
- // padding after mOwnsBuffer
- uninitTest<hidl_vec<SomeType>, 13, 16>();
-}
-TEST_F(LibHidlTest, HidlHandleUninit) {
- using ::android::hardware::hidl_handle;
- static_assert(sizeof(hidl_handle) == 16);
-
- // padding after mOwnsHandle
- uninitTest<hidl_handle, 9, 16>();
-}
-TEST_F(LibHidlTest, HidlStringUninit) {
- using ::android::hardware::hidl_string;
- static_assert(sizeof(hidl_string) == 16);
-
- // padding after mOwnsBuffer
- uninitTest<hidl_string, 13, 16>();
-}
-
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/transport/Android.bp b/transport/Android.bp
index 324dbde..50f277e 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -22,32 +22,23 @@ cc_defaults {
"libbase",
"liblog",
"libutils",
+ "libhwbinder",
"libcutils",
+ "libvndksupport"
],
export_shared_lib_headers: [
"libutils",
],
- static_libs: [
- "libhwbinder-impl-internal",
- ],
target: {
- android: {
- shared_libs: [
- "libvndksupport",
- ],
- },
recovery: {
- exclude_shared_libs: [
- "libvndksupport",
- ],
+ exclude_shared_libs: ["libvndksupport"],
},
},
}
cc_library_static {
name: "libhidltransport-impl-internal",
- host_supported: true,
vendor_available: true,
recovery_available: true,
@@ -103,6 +94,4 @@ cc_library_static {
cflags: ["-DENFORCE_VINTF_MANIFEST"]
},
},
-
- visibility: ["//system/libhidl:__subpackages__"],
}
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index 02d10d0..352ed78 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -163,6 +163,20 @@ status_t writeEmbeddedToParcel(const hidl_string &string,
parentOffset + hidl_string::kOffsetOfBuffer);
}
+android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) {
+ return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor());
+}
+
+hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
+ uint32_t version;
+ android::status_t status = parcel.readUint32(&version);
+ if (status != OK) {
+ return nullptr;
+ } else {
+ return new hidl_version(version >> 16, version & 0xFFFF);
+ }
+}
+
status_t readFromParcel(Status *s, const Parcel& parcel) {
int32_t exception;
status_t status = parcel.readInt32(&exception);
diff --git a/transport/HidlLazyUtils.cpp b/transport/HidlLazyUtils.cpp
index 08ed676..8e3fdf3 100644
--- a/transport/HidlLazyUtils.cpp
+++ b/transport/HidlLazyUtils.cpp
@@ -181,11 +181,6 @@ LazyServiceRegistrar::LazyServiceRegistrar() {
mImpl = std::make_shared<details::LazyServiceRegistrarImpl>();
}
-LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
- static auto registrarInstance = new LazyServiceRegistrar();
- return *registrarInstance;
-}
-
status_t LazyServiceRegistrar::registerService(
const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
return mImpl->registerService(service, name);
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
index e645cd0..b433b70 100644
--- a/transport/HidlTransportSupport.cpp
+++ b/transport/HidlTransportSupport.cpp
@@ -13,16 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <hidl/HidlTransportSupport.h>
-
#include <hidl/HidlBinderSupport.h>
-#include "InternalStatic.h"
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Static.h>
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <linux/sched.h>
-
namespace android {
namespace hardware {
@@ -95,10 +92,6 @@ bool setMinSchedulerPolicy(const sp<IBase>& service, int policy, int priority) {
return true;
}
-SchedPrio getMinSchedulerPolicy(const sp<IBase>& service) {
- return details::gServicePrioMap->get(service, {SCHED_NORMAL, 0});
-}
-
bool setRequestingSid(const sp<IBase>& service, bool requesting) {
if (service->isRemote()) {
LOG(ERROR) << "Can't set requesting sid on remote service.";
@@ -115,10 +108,6 @@ bool setRequestingSid(const sp<IBase>& service, bool requesting) {
return true;
}
-bool getRequestingSid(const sp<IBase>& service) {
- return details::gServiceSidMap->get(service.get(), false);
-}
-
bool interfacesEqual(const sp<IBase>& left, const sp<IBase>& right) {
if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
return left == right;
diff --git a/transport/InternalStatic.h b/transport/InternalStatic.h
index 666b2b6..1dfaae4 100644
--- a/transport/InternalStatic.h
+++ b/transport/InternalStatic.h
@@ -20,26 +20,19 @@
#ifndef ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
#define ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
-#include <hidl/HidlTransportSupport.h> // for SchedPrio
#include <hidl/Static.h>
namespace android {
namespace hardware {
namespace details {
-// TODO(b/69122224): remove this once no prebuilts reference it
+// TODO(b/69122224): remove this
// deprecated; use getBnConstructorMap instead.
extern DoNotDestruct<BnConstructorMap> gBnConstructorMap;
-// TODO(b/69122224): remove this once no prebuilts reference it
+// TODO(b/69122224): remove this
// deprecated; use getBsConstructorMap instead.
extern DoNotDestruct<BsConstructorMap> gBsConstructorMap;
-// TODO(b/69122224): remove this once no prebuilts reference it
-extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio>>
- gServicePrioMap;
-// TODO(b/69122224): remove this once no prebuilts reference it
-extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool>> gServiceSidMap;
-
} // namespace details
} // namespace hardware
} // namespace android
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 19d1d52..e7bec41 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -14,12 +14,9 @@
* limitations under the License.
*/
-#define LOG_TAG "HidlServiceManagement"
+#define LOG_TAG "ServiceManagement"
-#ifdef __ANDROID__
#include <android/dlext.h>
-#endif // __ANDROID__
-
#include <condition_variable>
#include <dlfcn.h>
#include <dirent.h>
@@ -46,7 +43,7 @@
#include <android-base/strings.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/Parcel.h>
-#if !defined(__ANDROID_RECOVERY__) && defined(__ANDROID__)
+#if !defined(__ANDROID_RECOVERY__)
#include <vndksupport/linker.h>
#endif
@@ -58,6 +55,8 @@
#define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
+using android::base::WaitForProperty;
+
using ::android::hidl::base::V1_0::IBase;
using IServiceManager1_0 = android::hidl::manager::V1_0::IServiceManager;
using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager;
@@ -67,6 +66,8 @@ using ::android::hidl::manager::V1_0::IServiceNotification;
namespace android {
namespace hardware {
+static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
+
#if defined(__ANDROID_RECOVERY__)
static constexpr bool kIsRecovery = true;
#else
@@ -74,18 +75,11 @@ static constexpr bool kIsRecovery = false;
#endif
static void waitForHwServiceManager() {
- // TODO(b/31559095): need bionic host so that we can use 'prop_info' returned
- // from WaitForProperty
-#ifdef __ANDROID__
- static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
-
using std::literals::chrono_literals::operator""s;
- using android::base::WaitForProperty;
while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
}
-#endif // __ANDROID__
}
static std::string binaryName() {
@@ -382,6 +376,13 @@ struct PassthroughServiceManager : IServiceManager1_1 {
} else if (!eachLib(handle, "SELF", sym)) {
return;
}
+
+ const char* vtsRootPath = std::getenv("VTS_ROOT_PATH");
+ if (vtsRootPath && strlen(vtsRootPath) > 0) {
+ const std::string halLibraryPathVtsOverride =
+ std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM;
+ paths.insert(paths.begin(), halLibraryPathVtsOverride);
+ }
}
#endif
@@ -394,7 +395,7 @@ struct PassthroughServiceManager : IServiceManager1_1 {
if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
handle = dlopen(fullPath.c_str(), dlMode);
} else {
-#if !defined(__ANDROID_RECOVERY__) && defined(__ANDROID__)
+#if !defined(__ANDROID_RECOVERY__)
handle = android_load_sphal_library(fullPath.c_str(), dlMode);
#endif
}
@@ -558,18 +559,6 @@ sp<IServiceManager1_1> getPassthroughServiceManager1_1() {
return manager;
}
-std::vector<std::string> getAllHalInstanceNames(const std::string& descriptor) {
- std::vector<std::string> ret;
- auto sm = defaultServiceManager1_2();
- sm->listManifestByInterface(descriptor, [&](const auto& instances) {
- ret.reserve(instances.size());
- for (const auto& i : instances) {
- ret.push_back(i);
- }
- });
- return ret;
-}
-
namespace details {
void preloadPassthroughService(const std::string &descriptor) {
@@ -734,32 +723,11 @@ bool handleCastError(const Return<bool>& castReturn, const std::string& descript
return false;
}
-#ifdef ENFORCE_VINTF_MANIFEST
-static constexpr bool kEnforceVintfManifest = true;
-#else
-static constexpr bool kEnforceVintfManifest = false;
-#endif
-
-#ifdef LIBHIDL_TARGET_DEBUGGABLE
-static constexpr bool kDebuggable = true;
-#else
-static constexpr bool kDebuggable = false;
-#endif
-
-static inline bool isTrebleTestingOverride() {
- if (kEnforceVintfManifest && !kDebuggable) {
- // don't allow testing override in production
- return false;
- }
-
- const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
- return env && !strcmp(env, "true");
-}
-
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
const std::string& instance,
bool retry, bool getStub) {
- using Transport = IServiceManager1_0::Transport;
+ using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
+ using ::android::hidl::manager::V1_0::IServiceManager;
sp<Waiter> waiter;
sp<IServiceManager1_1> sm;
@@ -785,19 +753,23 @@ sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string&
const bool vintfHwbinder = (transport == Transport::HWBINDER);
const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
- const bool trebleTestingOverride = isTrebleTestingOverride();
- const bool allowLegacy = !kEnforceVintfManifest || (trebleTestingOverride && kDebuggable);
- const bool vintfLegacy = (transport == Transport::EMPTY) && allowLegacy;
- if (!kEnforceVintfManifest) {
- ALOGE("getService: Potential race detected. The VINTF manifest is not being enforced. If "
- "a HAL server has a delay in starting and it is not in the manifest, it will not be "
- "retrieved. Please make sure all HALs on this device are in the VINTF manifest and "
- "enable PRODUCT_ENFORCE_VINTF_MANIFEST on this device (this is also enabled by "
- "PRODUCT_FULL_TREBLE). PRODUCT_ENFORCE_VINTF_MANIFEST will ensure that no race "
- "condition is possible here.");
- sleep(1);
- }
+#ifdef ENFORCE_VINTF_MANIFEST
+
+#ifdef LIBHIDL_TARGET_DEBUGGABLE
+ const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
+ const bool trebleTestingOverride = env && !strcmp(env, "true");
+ const bool vintfLegacy = (transport == Transport::EMPTY) && trebleTestingOverride;
+#else // ENFORCE_VINTF_MANIFEST but not LIBHIDL_TARGET_DEBUGGABLE
+ const bool trebleTestingOverride = false;
+ const bool vintfLegacy = false;
+#endif // LIBHIDL_TARGET_DEBUGGABLE
+
+#else // not ENFORCE_VINTF_MANIFEST
+ const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
+ const bool trebleTestingOverride = env && !strcmp(env, "true");
+ const bool vintfLegacy = (transport == Transport::EMPTY);
+#endif // ENFORCE_VINTF_MANIFEST
for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {
if (waiter == nullptr && tries > 0) {
@@ -841,7 +813,7 @@ sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string&
}
if (getStub || vintfPassthru || vintfLegacy) {
- const sp<IServiceManager1_0> pm = getPassthroughServiceManager();
+ const sp<IServiceManager> pm = getPassthroughServiceManager();
if (pm != nullptr) {
sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
if (!getStub || trebleTestingOverride) {
@@ -864,19 +836,6 @@ status_t registerAsServiceInternal(const sp<IBase>& service, const std::string&
return INVALID_OPERATION;
}
- const std::string descriptor = getDescriptor(service.get());
-
- if (kEnforceVintfManifest && !isTrebleTestingOverride()) {
- using Transport = IServiceManager1_0::Transport;
- Transport transport = sm->getTransport(descriptor, name);
-
- if (transport != Transport::HWBINDER) {
- LOG(ERROR) << "Service " << descriptor << "/" << name
- << " must be in VINTF manifest in order to register/get.";
- return UNKNOWN_ERROR;
- }
- }
-
bool registered = false;
Return<void> ret = service->interfaceChain([&](const auto& chain) {
registered = sm->addWithChain(name.c_str(), service, chain).withDefault(false);
@@ -887,7 +846,7 @@ status_t registerAsServiceInternal(const sp<IBase>& service, const std::string&
}
if (registered) {
- onRegistrationImpl(descriptor, name);
+ onRegistrationImpl(getDescriptor(service.get()), name);
}
return registered ? OK : UNKNOWN_ERROR;
diff --git a/transport/allocator/1.0/Android.bp b/transport/allocator/1.0/Android.bp
index 80364a7..a3d885a 100644
--- a/transport/allocator/1.0/Android.bp
+++ b/transport/allocator/1.0/Android.bp
@@ -14,3 +14,4 @@ hidl_interface {
],
gen_java: false,
}
+
diff --git a/transport/allocator/1.0/default/Android.bp b/transport/allocator/1.0/default/Android.bp
index 1116f1d..1fdfb26 100644
--- a/transport/allocator/1.0/default/Android.bp
+++ b/transport/allocator/1.0/default/Android.bp
@@ -26,6 +26,8 @@ cc_binary {
shared_libs: [
"android.hidl.allocator@1.0",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"libbase",
"liblog",
"libutils",
diff --git a/transport/allocator/1.0/utils/Android.bp b/transport/allocator/1.0/utils/Android.bp
index b324ef1..9f70963 100644
--- a/transport/allocator/1.0/utils/Android.bp
+++ b/transport/allocator/1.0/utils/Android.bp
@@ -24,6 +24,7 @@ cc_library {
"libbinder",
"libcutils",
"libhidlbase",
+ "libhidltransport",
"android.hidl.memory@1.0"
],
export_include_dirs: ["include"],
diff --git a/transport/base/1.0/Android.bp b/transport/base/1.0/Android.bp
index f90831e..cebb01b 100644
--- a/transport/base/1.0/Android.bp
+++ b/transport/base/1.0/Android.bp
@@ -12,3 +12,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/transport/base/1.0/vts/functional/Android.bp b/transport/base/1.0/vts/functional/Android.bp
index 38b03f7..f0bd45c 100644
--- a/transport/base/1.0/vts/functional/Android.bp
+++ b/transport/base/1.0/vts/functional/Android.bp
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+
cc_test {
name: "vts_ibase_test",
srcs: [
@@ -24,12 +25,10 @@ cc_test {
shared_libs: [
"libbase",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libutils",
- "libprotobuf-cpp-lite",
- "libhidl-gen-utils",
- ],
- static_libs: [
- "libinit_test_utils",
],
}
+
diff --git a/transport/base/1.0/vts/functional/vts_ibase_test.cpp b/transport/base/1.0/vts/functional/vts_ibase_test.cpp
index b77b2ad..6d66042 100644
--- a/transport/base/1.0/vts/functional/vts_ibase_test.cpp
+++ b/transport/base/1.0/vts/functional/vts_ibase_test.cpp
@@ -13,32 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "vts_ibase_test"
-#include <algorithm>
#include <functional>
#include <map>
-#include <mutex>
#include <string>
-#include <thread>
-#include <vector>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
#include <android/hidl/base/1.0/IBase.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <gtest/gtest.h>
-#include <hidl-util/FqInstance.h>
#include <hidl/HidlBinderSupport.h>
#include <hidl/ServiceManagement.h>
-#include <init-test-utils/service_utils.h>
-using android::FqInstance;
-using android::FQName;
-using android::sp;
-using android::wp;
-using android::base::Result;
using android::hardware::hidl_array;
using android::hardware::hidl_death_recipient;
using android::hardware::hidl_handle;
@@ -48,8 +33,8 @@ using android::hardware::IBinder;
using android::hardware::toBinder;
using android::hidl::base::V1_0::IBase;
using android::hidl::manager::V1_0::IServiceManager;
-using android::init::ServiceInterfacesMap;
-using PidInterfacesMap = std::map<pid_t, std::set<FqInstance>>;
+using android::sp;
+using android::wp;
template <typename T>
static inline ::testing::AssertionResult isOk(const ::android::hardware::Return<T>& ret) {
@@ -62,40 +47,8 @@ static inline ::testing::AssertionResult isOk(const ::android::hardware::Return<
struct Hal {
sp<IBase> service;
std::string name; // space separated list of android.hidl.foo@1.0::IFoo/instance-name
- FqInstance fq_instance;
};
-template <typename T>
-std::string FqInstancesToString(const T& instances) {
- std::set<std::string> instance_strings;
- for (const FqInstance& instance : instances) {
- instance_strings.insert(instance.string());
- }
- return android::base::Join(instance_strings, "\n");
-}
-
-pid_t GetServiceDebugPid(const std::string& service) {
- return android::base::GetIntProperty("init.svc_debug_pid." + service, 0);
-}
-
-std::map<std::string, std::vector<Hal>> gDeclaredServiceHalMap;
-std::mutex gDeclaredServiceHalMapMutex;
-
-void GetHal(const std::string& service, const FqInstance& instance) {
- if (instance.getFqName() == android::gIBaseFqName) {
- return;
- }
-
- sp<IBase> hal = android::hardware::details::getRawServiceInternal(
- instance.getFqName().string(), instance.getInstance(), true /*retry*/,
- false /*getStub*/);
- // Add to gDeclaredServiceHalMap if getRawServiceInternal() returns (even if
- // the returned HAL is null). getRawServiceInternal() won't return if the
- // HAL is in the VINTF but unable to start.
- std::lock_guard<std::mutex> guard(gDeclaredServiceHalMapMutex);
- gDeclaredServiceHalMap[service].push_back(Hal{.service = hal, .fq_instance = instance});
-}
-
class VtsHalBaseV1_0TargetTest : public ::testing::Test {
public:
virtual void SetUp() override {
@@ -133,7 +86,7 @@ class VtsHalBaseV1_0TargetTest : public ::testing::Test {
// include all the names this is registered as for error messages
iter->second.name += " " + strName;
} else {
- all_hals_.insert(iter, {binder, Hal{.service = service, .name = strName}});
+ all_hals_.insert(iter, {binder, Hal{service, strName}});
}
}
}));
@@ -147,25 +100,6 @@ class VtsHalBaseV1_0TargetTest : public ::testing::Test {
}
}
- PidInterfacesMap GetPidInterfacesMap() {
- PidInterfacesMap result;
- EXPECT_OK(default_manager_->debugDump([&result](const auto& list) {
- for (const auto& debug_info : list) {
- if (debug_info.pid != static_cast<int32_t>(IServiceManager::PidConstant::NO_PID)) {
- FQName fqName;
- ASSERT_TRUE(fqName.setTo(debug_info.interfaceName.c_str()))
- << "Unable to parse interface: '" << debug_info.interfaceName.c_str();
- FqInstance fqInstance;
- ASSERT_TRUE(fqInstance.setTo(fqName, debug_info.instanceName.c_str()));
- if (fqInstance.getFqName() != android::gIBaseFqName) {
- result[debug_info.pid].insert(fqInstance);
- }
- }
- }
- }));
- return result;
- }
-
// default service manager
sp<IServiceManager> default_manager_;
@@ -231,76 +165,6 @@ TEST_F(VtsHalBaseV1_0TargetTest, HashChain) {
});
}
-TEST_F(VtsHalBaseV1_0TargetTest, ServiceProvidesAndDeclaresTheSameInterfaces) {
- Result<ServiceInterfacesMap> service_interfaces_map =
- android::init::GetOnDeviceServiceInterfacesMap();
- ASSERT_TRUE(service_interfaces_map) << service_interfaces_map.error();
-
- // Attempt to get handles to all known declared interfaces. This will cause
- // any non-running lazy HALs to start up.
- // Results are saved in gDeclaredServiceHalMap.
- for (const auto& [service, declared_interfaces] : *service_interfaces_map) {
- if (declared_interfaces.empty()) {
- LOG(INFO) << "Service '" << service << "' does not declare any interfaces.";
- }
- for (const auto& instance : declared_interfaces) {
- std::thread(GetHal, service, instance).detach();
- }
- }
- // Allow the threads 5 seconds to attempt to get each HAL. Any HAL whose
- // thread is stuck during retrieval is excluded from this test.
- sleep(5);
-
- std::lock_guard<std::mutex> guard(gDeclaredServiceHalMapMutex);
- PidInterfacesMap pid_interfaces_map = GetPidInterfacesMap();
-
- // For each service that had at least one thread return from attempting to
- // retrieve a HAL:
- for (const auto& [service, hals] : gDeclaredServiceHalMap) {
- // Assert that the service is running.
- pid_t pid = GetServiceDebugPid(service);
- ASSERT_NE(pid, 0) << "Service '" << service << "' is not running.";
-
- std::set<FqInstance> declared_interfaces;
- for (const auto& hal : hals) {
- declared_interfaces.insert(hal.fq_instance);
- }
-
- // Warn for any threads that were stuck when attempting to retrieve a
- // HAL.
- std::vector<FqInstance> missing_declared_interfaces;
- std::set_difference((*service_interfaces_map)[service].begin(),
- (*service_interfaces_map)[service].end(), declared_interfaces.begin(),
- declared_interfaces.end(),
- std::back_inserter(missing_declared_interfaces));
- if (!missing_declared_interfaces.empty()) {
- LOG(WARNING)
- << "Service '" << service
- << "' declares interfaces that are present in the VINTF but unable to start:"
- << std::endl
- << FqInstancesToString(missing_declared_interfaces);
- }
-
- // Expect that the set of interfaces running at this PID is the same as
- // the set of interfaces declared by this service.
- std::set<FqInstance> served_interfaces = pid_interfaces_map[pid];
- std::vector<FqInstance> served_declared_diff;
- std::set_symmetric_difference(declared_interfaces.begin(), declared_interfaces.end(),
- served_interfaces.begin(), served_interfaces.end(),
- std::back_inserter(served_declared_diff));
-
- EXPECT_TRUE(served_declared_diff.empty())
- << "Service '" << service << "' serves and declares different interfaces."
- << std::endl
- << " Served:" << std::endl
- << FqInstancesToString(served_interfaces) << std::endl
- << " Declared: " << std::endl
- << FqInstancesToString(declared_interfaces) << std::endl
- << " Difference: " << std::endl
- << FqInstancesToString(served_declared_diff);
- }
-}
-
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 5dec5cd..a098805 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -28,7 +28,7 @@
#include <hwbinder/Parcel.h>
#include <log/log.h> // TODO(b/65843592): remove. Too many users depending on this transitively.
-// Defines functions for hidl_string, Status, hidl_vec, MQDescriptor,
+// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
// etc. to interact with Parcel.
namespace android {
@@ -72,6 +72,13 @@ status_t readEmbeddedFromParcel(const hidl_string &string,
status_t writeEmbeddedToParcel(const hidl_string &string,
Parcel *parcel, size_t parentHandle, size_t parentOffset);
+// ---------------------- hidl_version
+
+status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
+
+// Caller is responsible for freeing the returned object.
+hidl_version* readFromParcel(const android::hardware::Parcel& parcel);
+
// ---------------------- Status
// Bear in mind that if the client or service is a Java endpoint, this
@@ -178,6 +185,127 @@ template<typename T, MQFlavor flavor>
return _hidl_err;
}
+// ---------------------- pointers for HIDL
+
+template <typename T>
+static status_t readEmbeddedReferenceFromParcel(
+ T const* * /* bufptr */,
+ const Parcel & parcel,
+ size_t parentHandle,
+ size_t parentOffset,
+ size_t *handle,
+ bool *shouldResolveRefInBuffer
+ ) {
+ // *bufptr is ignored because, if I am embedded in some
+ // other buffer, the kernel should have fixed me up already.
+ bool isPreviouslyWritten;
+ status_t result = parcel.readEmbeddedReference(
+ nullptr, // ignored, not written to bufptr.
+ handle,
+ parentHandle,
+ parentOffset,
+ &isPreviouslyWritten);
+ // tell caller to run T::readEmbeddedToParcel and
+ // T::readEmbeddedReferenceToParcel if necessary.
+ // It is not called here because we don't know if these two are valid methods.
+ *shouldResolveRefInBuffer = !isPreviouslyWritten;
+ return result;
+}
+
+template <typename T>
+static status_t writeEmbeddedReferenceToParcel(
+ T const* buf,
+ Parcel *parcel, size_t parentHandle, size_t parentOffset,
+ size_t *handle,
+ bool *shouldResolveRefInBuffer
+ ) {
+
+ if(buf == nullptr) {
+ *shouldResolveRefInBuffer = false;
+ return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
+ }
+
+ // find whether the buffer exists
+ size_t childHandle, childOffset;
+ status_t result;
+ bool found;
+
+ result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
+
+ // tell caller to run T::writeEmbeddedToParcel and
+ // T::writeEmbeddedReferenceToParcel if necessary.
+ // It is not called here because we don't know if these two are valid methods.
+ *shouldResolveRefInBuffer = !found;
+
+ if(result != OK) {
+ return result; // bad pointers and length given
+ }
+ if(!found) { // did not find it.
+ return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
+ parentHandle, parentOffset);
+ }
+ // found the buffer. easy case.
+ return parcel->writeEmbeddedReference(
+ handle,
+ childHandle,
+ childOffset,
+ parentHandle,
+ parentOffset);
+}
+
+template <typename T>
+static status_t readReferenceFromParcel(
+ T const* *bufptr,
+ const Parcel & parcel,
+ size_t *handle,
+ bool *shouldResolveRefInBuffer
+ ) {
+ bool isPreviouslyWritten;
+ status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
+ handle, &isPreviouslyWritten);
+ // tell caller to run T::readEmbeddedToParcel and
+ // T::readEmbeddedReferenceToParcel if necessary.
+ // It is not called here because we don't know if these two are valid methods.
+ *shouldResolveRefInBuffer = !isPreviouslyWritten;
+ return result;
+}
+
+template <typename T>
+static status_t writeReferenceToParcel(
+ T const *buf,
+ Parcel * parcel,
+ size_t *handle,
+ bool *shouldResolveRefInBuffer
+ ) {
+
+ if(buf == nullptr) {
+ *shouldResolveRefInBuffer = false;
+ return parcel->writeNullReference(handle);
+ }
+
+ // find whether the buffer exists
+ size_t childHandle, childOffset;
+ status_t result;
+ bool found;
+
+ result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
+
+ // tell caller to run T::writeEmbeddedToParcel and
+ // T::writeEmbeddedReferenceToParcel if necessary.
+ // It is not called here because we don't know if these two are valid methods.
+ *shouldResolveRefInBuffer = !found;
+
+ if(result != OK) {
+ return result; // bad pointers and length given
+ }
+ if(!found) { // did not find it.
+ return parcel->writeBuffer(buf, sizeof(T), handle);
+ }
+ // found the buffer. easy case.
+ return parcel->writeReference(handle,
+ childHandle, childOffset);
+}
+
// ---------------------- support for casting interfaces
// Constructs a binder for this interface and caches it. If it has already been created
diff --git a/transport/include/hidl/HidlLazyUtils.h b/transport/include/hidl/HidlLazyUtils.h
index 257de98..2205daa 100644
--- a/transport/include/hidl/HidlLazyUtils.h
+++ b/transport/include/hidl/HidlLazyUtils.h
@@ -29,13 +29,12 @@ class LazyServiceRegistrarImpl;
/** Exits when all HALs registered through this object have 0 clients */
class LazyServiceRegistrar {
public:
- LazyServiceRegistrar();
- static LazyServiceRegistrar& getInstance();
- status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
- const std::string& name = "default");
+ LazyServiceRegistrar();
+ status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
+ const std::string& name = "default");
private:
- std::shared_ptr<details::LazyServiceRegistrarImpl> mImpl;
+ std::shared_ptr<details::LazyServiceRegistrarImpl> mImpl;
};
} // namespace hardware
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 454a4e5..a132bfa 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -84,13 +84,6 @@ status_t handleTransportPoll(int fd);
bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
int policy, int priority);
-struct SchedPrio {
- int sched_policy;
- int prio;
-};
-
-SchedPrio getMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service);
-
/**
* Sets whether or not this object should request security contexts to be populatd for incoming
* calls (e.g. with getCallingSid).
@@ -104,12 +97,6 @@ SchedPrio getMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& se
bool setRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service, bool requesting);
/**
- * Says whether or not this service is requesting a SID. If this was set after the service was
- * sent to another process, then it will not take effect.
- */
-bool getRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service);
-
-/**
* Returns whether two interfaces represent the same interface. References to interfaces in the same
* process will always be equivalent. However, in order to compare a service that is a proxy to a
* different process, its underlying structure may have to be checked.
diff --git a/transport/include/hidl/LegacySupport.h b/transport/include/hidl/LegacySupport.h
index 7cb72a9..1e983eb 100644
--- a/transport/include/hidl/LegacySupport.h
+++ b/transport/include/hidl/LegacySupport.h
@@ -26,12 +26,9 @@
namespace android {
namespace hardware {
namespace details {
-template <typename Interface>
-using RegisterServiceCb = std::function<status_t(const sp<Interface>&, const std::string&)>;
-
-template <class Interface, class ExpectInterface = Interface>
+template <class Interface, typename Func>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
- RegisterServiceCb<Interface> registerServiceCb, const std::string& name = "default") {
+ Func registerServiceCb, const std::string& name = "default") {
sp<Interface> service = Interface::getService(name, true /* getStub */);
if (service == nullptr) {
@@ -43,10 +40,6 @@ __attribute__((warn_unused_result)) status_t registerPassthroughServiceImplement
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
- sp<ExpectInterface> expected = ExpectInterface::castFrom(service);
- LOG_FATAL_IF(expected == nullptr, "Implementation of %s/%s is not a %s!", Interface::descriptor,
- name.c_str(), ExpectInterface::descriptor);
-
status_t status = registerServiceCb(service, name);
if (status == OK) {
@@ -64,14 +57,14 @@ __attribute__((warn_unused_result)) status_t registerPassthroughServiceImplement
/**
* Registers passthrough service implementation.
*/
-template <class Interface, class ExpectInterface = Interface>
+template <class Interface>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
- const std::string& name = "default") {
- return details::registerPassthroughServiceImplementation<Interface, ExpectInterface>(
- [](const sp<Interface>& service, const std::string& name) {
- return service->registerAsService(name);
- },
- name);
+ const std::string& name = "default") {
+ return details::registerPassthroughServiceImplementation<Interface>(
+ [](const sp<Interface>& service, const std::string& name) {
+ return service->registerAsService(name);
+ },
+ name);
}
/**
@@ -79,11 +72,11 @@ __attribute__((warn_unused_result)) status_t registerPassthroughServiceImplement
*
* Return value is exit status.
*/
-template <class Interface, class ExpectInterface = Interface>
+template <class Interface>
__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(
- const std::string& name, size_t maxThreads = 1) {
+ const std::string& name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true);
- status_t result = registerPassthroughServiceImplementation<Interface, ExpectInterface>(name);
+ status_t result = registerPassthroughServiceImplementation<Interface>(name);
if (result != OK) {
return result;
@@ -92,11 +85,10 @@ __attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementa
joinRpcThreadpool();
return UNKNOWN_ERROR;
}
-template <class Interface, class ExpectInterface = Interface>
-__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(
- size_t maxThreads = 1) {
- return defaultPassthroughServiceImplementation<Interface, ExpectInterface>("default",
- maxThreads);
+template<class Interface>
+__attribute__((warn_unused_result))
+status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) {
+ return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);
}
/**
@@ -107,15 +99,20 @@ __attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementa
* through registerPassthroughServiceImplementation, so if that function is used in conjunction with
* this one, the process may exit while a client is still using the HAL.
*/
-template <class Interface, class ExpectInterface = Interface>
+template <class Interface>
__attribute__((warn_unused_result)) status_t registerLazyPassthroughServiceImplementation(
- const std::string& name = "default") {
- return details::registerPassthroughServiceImplementation<Interface, ExpectInterface>(
- [](const sp<Interface>& service, const std::string& name) {
- using android::hardware::LazyServiceRegistrar;
- return LazyServiceRegistrar::getInstance().registerService(service, name);
- },
- name);
+ const std::string& name = "default") {
+ // Make LazyServiceRegistrar static so that multiple calls to
+ // registerLazyPassthroughServiceImplementation work as expected: each HAL is registered and the
+ // process only exits once all HALs have 0 clients.
+ using android::hardware::LazyServiceRegistrar;
+ static auto serviceCounter(std::make_shared<LazyServiceRegistrar>());
+
+ return details::registerPassthroughServiceImplementation<Interface>(
+ [](const sp<Interface>& service, const std::string& name) {
+ return serviceCounter->registerService(service, name);
+ },
+ name);
}
/**
@@ -124,12 +121,11 @@ __attribute__((warn_unused_result)) status_t registerLazyPassthroughServiceImple
*
* Return value is exit status.
*/
-template <class Interface, class ExpectInterface = Interface>
+template <class Interface>
__attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplementation(
- const std::string& name, size_t maxThreads = 1) {
+ const std::string& name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true);
- status_t result =
- registerLazyPassthroughServiceImplementation<Interface, ExpectInterface>(name);
+ status_t result = registerLazyPassthroughServiceImplementation<Interface>(name);
if (result != OK) {
return result;
@@ -138,11 +134,10 @@ __attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplem
joinRpcThreadpool();
return UNKNOWN_ERROR;
}
-template <class Interface, class ExpectInterface = Interface>
+template <class Interface>
__attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplementation(
- size_t maxThreads = 1) {
- return defaultLazyPassthroughServiceImplementation<Interface, ExpectInterface>("default",
- maxThreads);
+ size_t maxThreads = 1) {
+ return defaultLazyPassthroughServiceImplementation<Interface>("default", maxThreads);
}
} // namespace hardware
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 4573a25..a962034 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -18,7 +18,6 @@
#define ANDROID_HARDWARE_ISERVICE_MANAGER_H
#include <string>
-#include <vector>
#include <android/hidl/base/1.0/IBase.h>
#include <utils/StrongPointer.h>
@@ -72,14 +71,6 @@ sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager
sp<::android::hidl::manager::V1_1::IServiceManager> getPassthroughServiceManager1_1();
/**
- * Given a descriptor (e.g. from IFoo::descriptor), return a list of all instance names
- * on a device (e.g. the VINTF manifest). These HALs may not be currently running, but
- * the expectation is that if they aren't running, they should start as lazy HALs.
- * So, getService should return for each of these instance names.
- */
-std::vector<std::string> getAllHalInstanceNames(const std::string& descriptor);
-
-/**
* Given a service that is in passthrough mode, this function will go ahead and load the
* required passthrough module library (but not call HIDL_FETCH_I* functions to instantiate it).
*
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 3f6203c..be74bae 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -32,6 +32,17 @@ namespace android {
namespace hardware {
namespace details {
+struct SchedPrio {
+ int sched_policy;
+ int prio;
+};
+
+// TODO(b/69122224): remove this
+extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio>>
+ gServicePrioMap;
+// TODO(b/69122224): remove this
+extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool>> gServiceSidMap;
+
// TODO(b/69122224): remove this
// For HidlBinderSupport and autogenerated code
extern DoNotDestruct<ConcurrentMap<const ::android::hidl::base::V1_0::IBase*,
diff --git a/transport/manager/1.0/Android.bp b/transport/manager/1.0/Android.bp
index c91dcd2..869c58e 100644
--- a/transport/manager/1.0/Android.bp
+++ b/transport/manager/1.0/Android.bp
@@ -15,3 +15,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/transport/manager/1.1/Android.bp b/transport/manager/1.1/Android.bp
index 82545e5..407dfa3 100644
--- a/transport/manager/1.1/Android.bp
+++ b/transport/manager/1.1/Android.bp
@@ -15,3 +15,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/transport/manager/1.2/Android.bp b/transport/manager/1.2/Android.bp
index e7ee143..3f02f78 100644
--- a/transport/manager/1.2/Android.bp
+++ b/transport/manager/1.2/Android.bp
@@ -17,3 +17,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/transport/memory/1.0/Android.bp b/transport/memory/1.0/Android.bp
index dd76889..eaa3037 100644
--- a/transport/memory/1.0/Android.bp
+++ b/transport/memory/1.0/Android.bp
@@ -16,3 +16,4 @@ hidl_interface {
],
gen_java: false,
}
+
diff --git a/transport/memory/1.0/default/Android.bp b/transport/memory/1.0/default/Android.bp
index f56ee95..d242ddf 100644
--- a/transport/memory/1.0/default/Android.bp
+++ b/transport/memory/1.0/default/Android.bp
@@ -29,10 +29,12 @@ cc_library_shared {
],
shared_libs: [
"libcutils",
+ "libhwbinder",
"libbase",
"liblog",
"libutils",
"libhidlbase",
+ "libhidltransport",
"android.hidl.memory@1.0",
],
}
diff --git a/transport/memory/1.0/default/HidlFetch.cpp b/transport/memory/1.0/default/HidlFetch.cpp
index a636e03..d47cf97 100644
--- a/transport/memory/1.0/default/HidlFetch.cpp
+++ b/transport/memory/1.0/default/HidlFetch.cpp
@@ -16,11 +16,9 @@
#include "HidlFetch.h"
-#include <string_view>
-
#include "AshmemMapper.h"
-static constexpr std::string_view kAshmemMemoryName = "ashmem";
+static std::string kAshmemMemoryName = "ashmem";
namespace android {
namespace hidl {
diff --git a/transport/safe_union/1.0/Android.bp b/transport/safe_union/1.0/Android.bp
index 2760863..88c7d5d 100644
--- a/transport/safe_union/1.0/Android.bp
+++ b/transport/safe_union/1.0/Android.bp
@@ -12,3 +12,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/transport/token/1.0/Android.bp b/transport/token/1.0/Android.bp
index 28f16f7..c0988cb 100644
--- a/transport/token/1.0/Android.bp
+++ b/transport/token/1.0/Android.bp
@@ -14,3 +14,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
index 8e23c62..cdbdd97 100644
--- a/transport/token/1.0/utils/Android.bp
+++ b/transport/token/1.0/utils/Android.bp
@@ -25,22 +25,16 @@ cc_library {
"HybridInterface.cpp",
],
- header_libs: [
- "libbinder_headers",
- ],
-
shared_libs: [
"android.hidl.token@1.0",
+ "libbinder",
"libhidlbase",
"liblog",
"libutils",
],
- export_header_lib_headers: [
- "libbinder_headers",
- ],
-
export_shared_lib_headers: [
+ "libbinder",
"libhidlbase",
],
diff --git a/transport/token/1.0/utils/HybridInterface.cpp b/transport/token/1.0/utils/HybridInterface.cpp
index 675db8f..106ad4e 100644
--- a/transport/token/1.0/utils/HybridInterface.cpp
+++ b/transport/token/1.0/utils/HybridInterface.cpp
@@ -117,4 +117,5 @@ bool deleteHalToken(const HalToken& token) {
return static_cast<bool>(transaction);
}
-} // namespace android
+}; // namespace android
+
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
index d00a0a1..125d5e8 100644
--- a/transport/token/1.0/utils/include/hidl/HybridInterface.h
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -389,10 +389,7 @@ public: \
return getHalVariant().index(); \
} \
constexpr uint32_t I##INTERFACE::sGetHalTokenTransactionCode; \
- static const ::android::StaticString16 I##INTERFACE##_desc_str16( \
- u##NAME); \
- const ::android::String16 I##INTERFACE::descriptor( \
- I##INTERFACE##_desc_str16); \
+ const ::android::String16 I##INTERFACE::descriptor(NAME); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
@@ -560,6 +557,6 @@ HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...>::HpInterface(
// ----------------------------------------------------------------------
-} // namespace android
+}; // namespace android
#endif // ANDROID_HYBRIDINTERFACE_H