[automerger skipped] Add gServiceSidMap. am: 3faf64b2dc am: 3ab619c3a6 -s ours
am: c833a506ce -s ours
am skip reason: change_id I4e5821d91ea694f86911218c23e68fcb987daaf9 with SHA1 d7f8d2226f is in history
Change-Id: Ifa555969449dfa7a36f91f33611ac272d37d1776
diff --git a/Android.bp b/Android.bp
index ae04548..032a61a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,23 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-subdirs = [
- "base", // libhidlbase
- "libhidlmemory", // libhidlmemory
- "transport", // libhidltransport
-]
-
-libhidl_flags = [
- "-Wall",
- "-Werror",
-]
+cc_defaults {
+ name: "libhidl-defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
cc_test {
name: "libhidl_test",
+ defaults: ["libhidl-defaults"],
gtest: false,
srcs: ["test_main.cpp"],
shared_libs: [
+ "android.hardware.tests.inheritance@1.0",
"libbase",
"libhidlbase",
"libhidltransport",
@@ -39,8 +38,12 @@
],
static_libs: ["libgtest", "libgmock"],
+ required: [
+ "android.hardware.tests.inheritance@1.0-impl",
+ ],
+
cflags: [
"-O0",
"-g",
- ] + libhidl_flags,
+ ],
}
diff --git a/adapter/Android.bp b/adapter/Android.bp
new file mode 100644
index 0000000..eb322bc
--- /dev/null
+++ b/adapter/Android.bp
@@ -0,0 +1,37 @@
+// Copyright (C) 2017 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: "libhidladapter",
+ defaults: ["libhidl-defaults"],
+ vendor_available: true,
+ srcs: [
+ "HidlBinderAdapter.cpp"
+ ],
+ export_include_dirs: ["include"],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+ export_shared_lib_headers: [
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ ],
+}
+
diff --git a/adapter/HidlBinderAdapter.cpp b/adapter/HidlBinderAdapter.cpp
new file mode 100644
index 0000000..b6aa58e
--- /dev/null
+++ b/adapter/HidlBinderAdapter.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2017 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 <hidladapter/HidlBinderAdapter.h>
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <unistd.h>
+#include <iostream>
+#include <map>
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace details {
+
+using android::base::SetProperty;
+using android::base::WaitForProperty;
+
+const static std::string kDeactivateProp = "test.hidl.adapters.deactivated";
+
+void usage(const std::string& me) {
+ std::cerr << "usage: " << me << " [-p] interface-name instance-name number-of-threads."
+ << std::endl;
+ std::cerr << " -p: stop based on property " << kDeactivateProp << "and reset it."
+ << std::endl;
+}
+
+bool processArguments(int* argc, char*** argv, bool* propertyStop) {
+ int c;
+ while ((c = getopt(*argc, *argv, "p")) != -1) {
+ switch (c) {
+ case 'p': {
+ *propertyStop = true;
+ break;
+ }
+ default: { return false; }
+ }
+ }
+
+ *argc -= optind;
+ *argv += optind;
+ return true;
+}
+
+// only applies for -p argument
+void waitForAdaptersDeactivated() {
+ using std::literals::chrono_literals::operator""s;
+
+ while (!WaitForProperty(kDeactivateProp, "true", 30s)) {
+ // Log this so that when using this option on testing devices, there is
+ // a clear indication if adapters are not properly stopped
+ LOG(WARNING) << "Adapter use in progress. Waiting for stop based on 'true' "
+ << kDeactivateProp;
+ }
+
+ SetProperty(kDeactivateProp, "false");
+}
+
+int adapterMain(const std::string& package, int argc, char** argv,
+ const AdaptersFactory& adapters) {
+ using android::hardware::configureRpcThreadpool;
+ using android::hidl::base::V1_0::IBase;
+ using android::hidl::manager::V1_0::IServiceManager;
+
+ const std::string& me = argc > 0 ? argv[0] : "(error)";
+
+ bool propertyStop = false;
+ if (!processArguments(&argc, &argv, &propertyStop)) {
+ usage(me);
+ return EINVAL;
+ }
+
+ if (argc != 3) {
+ usage(me);
+ return EINVAL;
+ }
+
+ std::string interfaceName = package + "::" + argv[0];
+ std::string instanceName = argv[1];
+ int threadNumber = std::stoi(argv[2]);
+
+ if (threadNumber <= 0) {
+ std::cerr << "ERROR: invalid thread number " << threadNumber
+ << " must be a positive integer.";
+ }
+
+ auto it = adapters.find(interfaceName);
+ if (it == adapters.end()) {
+ std::cerr << "ERROR: could not resolve " << interfaceName << "." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Trying to adapt down " << interfaceName << "/" << instanceName << std::endl;
+
+ configureRpcThreadpool(threadNumber, false /* callerWillJoin */);
+
+ sp<IServiceManager> manager = IServiceManager::getService();
+ if (manager == nullptr) {
+ std::cerr << "ERROR: could not retrieve service manager." << std::endl;
+ return 1;
+ }
+
+ sp<IBase> implementation = manager->get(interfaceName, instanceName).withDefault(nullptr);
+ if (implementation == nullptr) {
+ std::cerr << "ERROR: could not retrieve desired implementation" << std::endl;
+ return 1;
+ }
+
+ sp<IBase> adapter = it->second(implementation);
+ if (adapter == nullptr) {
+ std::cerr << "ERROR: could not create adapter." << std::endl;
+ return 1;
+ }
+
+ bool replaced = manager->add(instanceName, adapter).withDefault(false);
+ if (!replaced) {
+ std::cerr << "ERROR: could not register the service with the service manager." << std::endl;
+ return 1;
+ }
+
+ if (propertyStop) {
+ std::cout << "Set " << kDeactivateProp << " to true to deactivate." << std::endl;
+ waitForAdaptersDeactivated();
+ } else {
+ std::cout << "Press any key to disassociate adapter." << std::endl;
+ getchar();
+ }
+
+ bool restored = manager->add(instanceName, implementation).withDefault(false);
+ if (!restored) {
+ std::cerr << "ERROR: could not re-register interface with the service manager."
+ << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success." << std::endl;
+
+ return 0;
+}
+
+// If an interface is adapted to 1.0, it can then not be adapted to 1.1 in the same process.
+// This poses a problem in the following scenario:
+// auto interface = new V1_1::implementation::IFoo;
+// hidlObject1_0->foo(interface) // adaptation set at 1.0
+// hidlObject1_1->bar(interface) // adaptation still is 1.0
+// This could be solved by keeping a map of IBase,fqName -> IBase, but then you end up
+// with multiple names for the same interface.
+sp<IBase> adaptWithDefault(const sp<IBase>& something,
+ const std::function<sp<IBase>()>& makeDefault) {
+ static std::map<sp<IBase>, sp<IBase>> sAdapterMap;
+
+ if (something == nullptr) {
+ return something;
+ }
+
+ auto it = sAdapterMap.find(something);
+ if (it == sAdapterMap.end()) {
+ it = sAdapterMap.insert(it, {something, makeDefault()});
+ }
+
+ return it->second;
+}
+
+} // namespace details
+} // namespace hardware
+} // namespace android
diff --git a/adapter/include/hidladapter/HidlBinderAdapter.h b/adapter/include/hidladapter/HidlBinderAdapter.h
new file mode 100644
index 0000000..46df554
--- /dev/null
+++ b/adapter/include/hidladapter/HidlBinderAdapter.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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 <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+
+#include <map>
+
+namespace android {
+namespace hardware {
+
+namespace details {
+
+using IBase = ::android::hidl::base::V1_0::IBase;
+
+// AdapterFactory(impl) -> adapter
+using AdapterFactory = std::function<sp<IBase>(sp<IBase>)>;
+// AdaptersFactory(package@interface)(impl) -> adapter
+using AdaptersFactory = std::map<std::string, AdapterFactory>;
+
+int adapterMain(const std::string& package, int argc, char** argv, const AdaptersFactory& adapters);
+
+sp<IBase> adaptWithDefault(const sp<IBase>& something,
+ const std::function<sp<IBase>()>& makeDefault);
+
+} // namespace details
+
+template <typename... Adapters>
+int adapterMain(const std::string& package, int argc, char** argv) {
+ return details::adapterMain(
+ package, argc, argv,
+ {{Adapters::Pure::descriptor, [](sp<::android::hidl::base::V1_0::IBase> base) {
+ return details::adaptWithDefault(
+ base, [&] { return new Adapters(Adapters::Pure::castFrom(base)); });
+ }}...});
+}
+
+} // namespace hardware
+} // namespace android
\ No newline at end of file
diff --git a/base/Android.bp b/base/Android.bp
index 5a38ed8..22f5ee1 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_shared {
+cc_library {
name: "libhidlbase",
vendor_available: true,
vndk: {
enabled: true,
support_system_process: true,
},
- cflags: libhidl_flags,
+ defaults: ["libhidl-defaults"],
shared_libs: [
"libbase",
"libcutils",
@@ -33,7 +33,6 @@
local_include_dirs: ["include"],
export_include_dirs: ["include"],
- clang: true,
sanitize: {
misc_undefined: ["integer"],
},
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index c534a4c..babdac1 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -19,50 +19,119 @@
#include <hidl/HidlInternal.h>
#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>
#include <dlfcn.h>
+#include <link.h>
+#include <utils/misc.h>
#include <regex>
+
+extern "C" __attribute__((weak)) void __sanitizer_cov_dump();
+const char* kGcovPrefixEnvVar = "GCOV_PREFIX";
+const char* kGcovPrefixOverrideEnvVar = "GCOV_PREFIX_OVERRIDE";
+const char* kGcovPrefixPath = "/data/misc/trace/";
+const char* kSysPropHalCoverage = "hal.coverage.enable";
+#if defined(__LP64__)
+const char* kSysPropInstrumentationPath = "hal.instrumentation.lib.path.64";
+#else
+const char* kSysPropInstrumentationPath = "hal.instrumentation.lib.path.32";
+#endif
#endif
namespace android {
namespace hardware {
namespace details {
-void logAlwaysFatal(const char *message) {
+void logAlwaysFatal(const char* message) {
LOG(FATAL) << message;
}
+std::string getVndkVersionStr() {
+ static std::string vndkVersion("0");
+ // "0" means the vndkVersion must be initialized with the property value.
+ // Otherwise, return the value.
+ if (vndkVersion == "0") {
+ vndkVersion = android::base::GetProperty("ro.vndk.version", "");
+ if (vndkVersion != "" && vndkVersion != "current") {
+ vndkVersion = "-" + vndkVersion;
+ } else {
+ vndkVersion = "";
+ }
+ }
+ return vndkVersion;
+}
+
// ----------------------------------------------------------------------
// HidlInstrumentor implementation.
HidlInstrumentor::HidlInstrumentor(const std::string& package, const std::string& interface)
: mEnableInstrumentation(false),
mInstrumentationLibPackage(package),
mInterfaceName(interface) {
+#ifdef LIBHIDL_TARGET_DEBUGGABLE
configureInstrumentation(false);
+ if (__sanitizer_cov_dump != nullptr) {
+ ::android::add_sysprop_change_callback(
+ []() {
+ bool enableCoverage = property_get_bool(kSysPropHalCoverage, false);
+ if (enableCoverage) {
+ __sanitizer_cov_dump();
+ }
+ },
+ 0);
+ }
+ 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 = 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
}
-HidlInstrumentor:: ~HidlInstrumentor() {}
+HidlInstrumentor::~HidlInstrumentor() {}
void HidlInstrumentor::configureInstrumentation(bool log) {
- bool enableInstrumentation = property_get_bool(
- "hal.instrumentation.enable",
- false);
- if (enableInstrumentation != mEnableInstrumentation) {
- mEnableInstrumentation = enableInstrumentation;
- if (mEnableInstrumentation) {
- if (log) {
- LOG(INFO) << "Enable instrumentation.";
- }
- registerInstrumentationCallbacks (&mInstrumentationCallbacks);
- } else {
- if (log) {
- LOG(INFO) << "Disable instrumentation.";
- }
- mInstrumentationCallbacks.clear();
+ mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
+ if (mEnableInstrumentation) {
+ if (log) {
+ LOG(INFO) << "Enable instrumentation.";
}
+ mInstrumentationCallbacks.clear();
+ registerInstrumentationCallbacks(&mInstrumentationCallbacks);
+ } else {
+ if (log) {
+ LOG(INFO) << "Disable instrumentation.";
+ }
+ mInstrumentationCallbacks.clear();
}
}
@@ -71,18 +140,18 @@
#ifdef LIBHIDL_TARGET_DEBUGGABLE
std::vector<std::string> instrumentationLibPaths;
char instrumentationLibPath[PROPERTY_VALUE_MAX];
- if (property_get("hal.instrumentation.lib.path",
- instrumentationLibPath,
- "") > 0) {
+ if (property_get(kSysPropInstrumentationPath, instrumentationLibPath, "") > 0) {
instrumentationLibPaths.push_back(instrumentationLibPath);
} else {
+ static std::string halLibPathVndkSp = android::base::StringPrintf(
+ HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, getVndkVersionStr().c_str());
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
- instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VNDK_SP);
+ instrumentationLibPaths.push_back(halLibPathVndkSp);
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
}
- for (auto path : instrumentationLibPaths) {
+ for (const auto& path : instrumentationLibPaths) {
DIR *dir = opendir(path.c_str());
if (dir == 0) {
LOG(WARNING) << path << " does not exist. ";
@@ -90,7 +159,7 @@
}
struct dirent *file;
- while ((file = readdir(dir)) != NULL) {
+ while ((file = readdir(dir)) != nullptr) {
if (!isInstrumentationLib(file))
continue;
@@ -126,7 +195,7 @@
}
auto cb = (cbFun)dlsym(handle, ("HIDL_INSTRUMENTATION_FUNCTION_"
+ package + "_" + mInterfaceName).c_str());
- if ((error = dlerror()) != NULL) {
+ if ((error = dlerror()) != nullptr) {
LOG(WARNING)
<< "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_"
<< package << "_" << mInterfaceName << ", error: " << error;
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index 4de7f7c..8f3c057 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -217,7 +217,7 @@
void hidl_string::copyFrom(const char *data, size_t size) {
// assume my resources are freed.
- if (size > UINT32_MAX) {
+ if (size >= UINT32_MAX) {
LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size;
}
char *buf = (char *)malloc(size + 1);
@@ -273,6 +273,44 @@
return mSize == 0;
}
+sp<HidlMemory> HidlMemory::getInstance(const hidl_memory& mem) {
+ sp<HidlMemory> instance = new HidlMemory();
+ instance->hidl_memory::operator=(mem);
+ return instance;
+}
+
+sp<HidlMemory> HidlMemory::getInstance(hidl_memory&& mem) {
+ sp<HidlMemory> instance = new HidlMemory();
+ instance->hidl_memory::operator=(std::move(mem));
+ return instance;
+}
+
+sp<HidlMemory> HidlMemory::getInstance(const hidl_string& name, int fd, uint64_t size) {
+ native_handle_t* handle = native_handle_create(1, 0);
+ if (!handle) {
+ close(fd);
+ LOG(ERROR) << "native_handle_create fails";
+ return new HidlMemory();
+ }
+ handle->data[0] = fd;
+
+ hidl_handle hidlHandle;
+ hidlHandle.setTo(handle, true /* shouldOwn */);
+
+ sp<HidlMemory> instance = new HidlMemory(name, std::move(hidlHandle), size);
+ return instance;
+}
+
+HidlMemory::HidlMemory() : hidl_memory() {}
+
+HidlMemory::HidlMemory(const hidl_string& name, hidl_handle&& handle, size_t size)
+ : hidl_memory(name, std::move(handle), size) {}
+
+// it's required to have at least one out-of-line method to avoid weak vtable
+HidlMemory::~HidlMemory() {
+ hidl_memory::~hidl_memory();
+}
+
} // namespace hardware
} // namespace android
diff --git a/base/Status.cpp b/base/Status.cpp
index 3b31ee6..1ba91c3 100644
--- a/base/Status.cpp
+++ b/base/Status.cpp
@@ -53,7 +53,7 @@
}
std::string str = std::to_string(s);
char *err = strerror(-s);
- if (err != NULL) {
+ if (err != nullptr) {
str.append(1, ' ').append(err);
}
return str;
diff --git a/base/include/hidl/SynchronizedQueue.h b/base/SynchronizedQueue.h
similarity index 88%
rename from base/include/hidl/SynchronizedQueue.h
rename to base/SynchronizedQueue.h
index efb04e0..356c72c 100644
--- a/base/include/hidl/SynchronizedQueue.h
+++ b/base/SynchronizedQueue.h
@@ -45,11 +45,23 @@
*/
size_t size();
+ std::unique_lock<std::mutex> lock() {
+ return std::unique_lock<std::mutex>(mMutex);
+ }
+
+ bool isInitializedLocked() {
+ return mInitialized;
+ }
+ void setInitializedLocked(bool isInitialized) {
+ mInitialized = isInitialized;
+ }
+
private:
std::condition_variable mCondition;
std::mutex mMutex;
std::queue<T> mQueue;
const size_t mQueueLimit;
+ bool mInitialized = false;
};
template <typename T>
diff --git a/base/TaskRunner.cpp b/base/TaskRunner.cpp
index 782b40b..bd42240 100644
--- a/base/TaskRunner.cpp
+++ b/base/TaskRunner.cpp
@@ -15,6 +15,10 @@
*/
#include <hidl/TaskRunner.h>
+
+#include <utils/AndroidThreads.h>
+#include "SynchronizedQueue.h"
+
#include <thread>
namespace android {
@@ -26,15 +30,6 @@
void TaskRunner::start(size_t limit) {
mQueue = std::make_shared<SynchronizedQueue<Task>>(limit);
-
- // Allow the thread to continue running in background;
- // TaskRunner do not care about the std::thread object.
- std::thread{[q = mQueue] {
- Task nextTask;
- while (!!(nextTask = q->wait_pop())) {
- nextTask();
- }
- }}.detach();
}
TaskRunner::~TaskRunner() {
@@ -44,7 +39,30 @@
}
bool TaskRunner::push(const Task &t) {
- return (mQueue != nullptr) && (!!t) && this->mQueue->push(t);
+ if (mQueue == nullptr || !t) {
+ return false;
+ }
+
+ {
+ std::unique_lock<std::mutex> lock = mQueue->lock();
+
+ if (!mQueue->isInitializedLocked()) {
+ // Allow the thread to continue running in background;
+ // TaskRunner do not care about the std::thread object.
+ std::thread{[q = mQueue] {
+ androidSetThreadName("HIDL TaskRunner");
+
+ Task nextTask;
+ while (!!(nextTask = q->wait_pop())) {
+ nextTask();
+ }
+ }}.detach();
+
+ mQueue->setInitializedLocked(true);
+ }
+ }
+
+ return this->mQueue->push(t);
}
} // namespace details
diff --git a/base/include/hidl/HidlInternal.h b/base/include/hidl/HidlInternal.h
index 7a24cd5..5a08bc3 100644
--- a/base/include/hidl/HidlInternal.h
+++ b/base/include/hidl/HidlInternal.h
@@ -28,10 +28,26 @@
namespace hardware {
namespace details {
+// tag for pure interfaces (e.x. IFoo)
+struct i_tag {};
+
+// tag for server interfaces (e.x. BnHwFoo)
+struct bnhw_tag {};
+
+// tag for proxy interfaces (e.x. BpHwFoo)
+struct bphw_tag {};
+
+// tag for passthrough interfaces (e.x. BsFoo)
+struct bs_tag {};
+
//Templated classes can use the below method
//to avoid creating dependencies on liblog.
void logAlwaysFatal(const char *message);
+// Returns vndk version from "ro.vndk.version" with '-' as a prefix.
+// If "ro.vndk.version" is not set or set to "current", it returns empty string.
+std::string getVndkVersionStr();
+
// HIDL client/server code should *NOT* use this class.
//
// hidl_pointer wraps a pointer without taking ownership,
@@ -89,22 +105,22 @@
};
#define HAL_LIBRARY_PATH_SYSTEM_64BIT "/system/lib64/hw/"
-#define HAL_LIBRARY_PATH_VNDK_SP_64BIT "/system/lib64/vndk-sp/hw/"
+#define HAL_LIBRARY_PATH_VNDK_SP_64BIT_FOR_VERSION "/system/lib64/vndk-sp%s/hw/"
#define HAL_LIBRARY_PATH_VENDOR_64BIT "/vendor/lib64/hw/"
#define HAL_LIBRARY_PATH_ODM_64BIT "/odm/lib64/hw/"
#define HAL_LIBRARY_PATH_SYSTEM_32BIT "/system/lib/hw/"
-#define HAL_LIBRARY_PATH_VNDK_SP_32BIT "/system/lib/vndk-sp/hw/"
+#define HAL_LIBRARY_PATH_VNDK_SP_32BIT_FOR_VERSION "/system/lib/vndk-sp%s/hw/"
#define HAL_LIBRARY_PATH_VENDOR_32BIT "/vendor/lib/hw/"
#define HAL_LIBRARY_PATH_ODM_32BIT "/odm/lib/hw/"
#if defined(__LP64__)
#define HAL_LIBRARY_PATH_SYSTEM HAL_LIBRARY_PATH_SYSTEM_64BIT
-#define HAL_LIBRARY_PATH_VNDK_SP HAL_LIBRARY_PATH_VNDK_SP_64BIT
+#define HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION HAL_LIBRARY_PATH_VNDK_SP_64BIT_FOR_VERSION
#define HAL_LIBRARY_PATH_VENDOR HAL_LIBRARY_PATH_VENDOR_64BIT
#define HAL_LIBRARY_PATH_ODM HAL_LIBRARY_PATH_ODM_64BIT
#else
#define HAL_LIBRARY_PATH_SYSTEM HAL_LIBRARY_PATH_SYSTEM_32BIT
-#define HAL_LIBRARY_PATH_VNDK_SP HAL_LIBRARY_PATH_VNDK_SP_32BIT
+#define HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION HAL_LIBRARY_PATH_VNDK_SP_32BIT_FOR_VERSION
#define HAL_LIBRARY_PATH_VENDOR HAL_LIBRARY_PATH_VENDOR_32BIT
#define HAL_LIBRARY_PATH_ODM HAL_LIBRARY_PATH_ODM_32BIT
#endif
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index f25cdc4..f09eb63 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -172,15 +172,16 @@
void moveFrom(hidl_string &&);
};
-#define HIDL_STRING_OPERATOR(OP) \
- inline bool operator OP(const hidl_string &hs1, const hidl_string &hs2) { \
- return strcmp(hs1.c_str(), hs2.c_str()) OP 0; \
- } \
- inline bool operator OP(const hidl_string &hs, const char *s) { \
- return strcmp(hs.c_str(), s) OP 0; \
- } \
- inline bool operator OP(const char *s, const hidl_string &hs) { \
- return strcmp(hs.c_str(), s) OP 0; \
+// Use NOLINT to suppress missing parentheses warnings around OP.
+#define HIDL_STRING_OPERATOR(OP) \
+ inline bool operator OP(const hidl_string& hs1, const hidl_string& hs2) { \
+ return strcmp(hs1.c_str(), hs2.c_str()) OP 0; /* NOLINT */ \
+ } \
+ inline bool operator OP(const hidl_string& hs, const char* s) { \
+ return strcmp(hs.c_str(), s) OP 0; /* NOLINT */ \
+ } \
+ inline bool operator OP(const char* s, const hidl_string& hs) { \
+ return strcmp(s, hs.c_str()) OP 0; /* NOLINT */ \
}
HIDL_STRING_OPERATOR(==)
@@ -207,6 +208,13 @@
}
/**
+ * Creates a hidl_memory object whose handle has the same lifetime
+ * as the handle moved into it.
+ */
+ hidl_memory(const hidl_string& name, hidl_handle&& handle, size_t size)
+ : mHandle(std::move(handle)), mSize(size), mName(name) {}
+
+ /**
* Creates a hidl_memory object, but doesn't take ownership of
* the passed in native_handle_t; callers are responsible for
* making sure the handle remains valid while this object is
@@ -267,6 +275,9 @@
return mSize;
}
+ // @return true if it's valid
+ inline bool valid() const { return handle() != nullptr; }
+
// offsetof(hidl_memory, mHandle) exposed since mHandle is private.
static const size_t kOffsetOfHandle;
// offsetof(hidl_memory, mName) exposed since mHandle is private.
@@ -278,17 +289,43 @@
hidl_string mName __attribute__ ((aligned(8)));
};
+// HidlMemory is a wrapper class to support sp<> for hidl_memory. It also
+// provides factory methods to create an instance from hidl_memory or
+// from a opened file descriptor. The number of factory methods can be increase
+// to support other type of hidl_memory without break the ABI.
+class HidlMemory : public virtual hidl_memory, public virtual ::android::RefBase {
+public:
+ static sp<HidlMemory> getInstance(const hidl_memory& mem);
+
+ static sp<HidlMemory> getInstance(hidl_memory&& mem);
+
+ static sp<HidlMemory> getInstance(const hidl_string& name, hidl_handle&& handle, uint64_t size);
+ // @param fd, shall be opened and points to the resource.
+ // @note this method takes the ownership of the fd and will close it in
+ // destructor
+ // @return nullptr in failure with the fd closed
+ static sp<HidlMemory> getInstance(const hidl_string& name, int fd, uint64_t size);
+
+ virtual ~HidlMemory();
+
+protected:
+ HidlMemory();
+ HidlMemory(const hidl_string& name, hidl_handle&& handle, size_t size);
+};
////////////////////////////////////////////////////////////////////////////////
template<typename T>
struct hidl_vec {
hidl_vec()
- : mBuffer(NULL),
+ : mBuffer(nullptr),
mSize(0),
mOwnsBuffer(true) {
static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
}
+ // Note, does not initialize primitive types.
+ hidl_vec(size_t size) : hidl_vec() { resize(size); }
+
hidl_vec(const hidl_vec<T> &other) : hidl_vec() {
*this = other;
}
@@ -341,7 +378,7 @@
if (mOwnsBuffer) {
delete[] mBuffer;
}
- mBuffer = NULL;
+ mBuffer = nullptr;
}
// Reference an existing array, optionally taking ownership. It is the
@@ -445,6 +482,7 @@
return mBuffer[index];
}
+ // Does not initialize primitive types if new size > old size.
void resize(size_t size) {
if (size > UINT32_MAX) {
details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
@@ -530,7 +568,7 @@
mBuffer[i] = data[i];
}
} else {
- mBuffer = NULL;
+ mBuffer = nullptr;
}
}
};
@@ -945,6 +983,19 @@
+ details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
}
+/**
+ * Every HIDL generated enum generates an implementation of this function.
+ * E.x.: for(const auto v : hidl_enum_iterator<Enum>) { ... }
+ */
+template <typename>
+struct hidl_enum_iterator;
+
+/**
+ * Bitfields in HIDL are the underlying type of the enumeration.
+ */
+template <typename Enum>
+using hidl_bitfield = typename std::underlying_type<Enum>::type;
+
} // namespace hardware
} // namespace android
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index f812ebb..1a2ef6d 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -143,7 +143,7 @@
void assertOk() const;
public:
return_status() {}
- return_status(Status s) : mStatus(s) {}
+ return_status(const Status& s) : mStatus(s) {}
return_status(const return_status &) = delete;
return_status &operator=(const return_status &) = delete;
@@ -155,6 +155,11 @@
~return_status();
+ bool isOkUnchecked() const {
+ // someone else will have to check
+ return mStatus.isOk();
+ }
+
bool isOk() const {
mCheckedStatus = true;
return mStatus.isOk();
@@ -240,7 +245,7 @@
template<> class Return<void> : public details::return_status {
public:
Return() : details::return_status() {}
- Return(Status s) : details::return_status(s) {}
+ Return(const Status& s) : details::return_status(s) {}
// move-able.
// precondition: "this" has checked status
diff --git a/base/include/hidl/TaskRunner.h b/base/include/hidl/TaskRunner.h
index 28ea01c..6a79ebf 100644
--- a/base/include/hidl/TaskRunner.h
+++ b/base/include/hidl/TaskRunner.h
@@ -16,7 +16,6 @@
#ifndef ANDROID_HIDL_TASK_RUNNER_H
#define ANDROID_HIDL_TASK_RUNNER_H
-#include "SynchronizedQueue.h"
#include <memory>
#include <thread>
@@ -24,13 +23,17 @@
namespace hardware {
namespace details {
+using Task = std::function<void(void)>;
+
+template <typename T>
+struct SynchronizedQueue;
+
/*
* A background infinite loop that runs the Tasks push()'ed.
* Equivalent to a simple single-threaded Looper.
*/
class TaskRunner {
public:
- using Task = std::function<void(void)>;
/* Create an empty task runner. Nothing will be done until start() is called. */
TaskRunner();
@@ -44,7 +47,9 @@
/*
* Sets the queue limit. Fails the push operation once the limit is reached.
- * Then kicks off the loop.
+ * This function is named start for legacy reasons and to maintain ABI
+ * stability, but the underlying thread running tasks isn't started until
+ * the first task is pushed.
*/
void start(size_t limit);
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..db778d3
--- /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) > 0) {
+ 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..6f9c25c
--- /dev/null
+++ b/libhidlcache/HidlMemoryCache.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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 IMemoryDecorator : public virtual IMemory {
+ public:
+ IMemoryDecorator(sp<IMemory> heap) : mHeap(heap) {}
+ virtual ~IMemoryDecorator(){};
+ 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 IMemoryCacheable : public virtual IMemoryDecorator {
+ public:
+ IMemoryCacheable(sp<IMemory> heap, sp<IMemoryToken> key) : IMemoryDecorator(heap), mKey(key) {}
+ virtual ~IMemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
+
+ protected:
+ sp<IMemoryToken> mKey;
+};
+
+class IMemoryBlock : public virtual IMemoryDecorator {
+ public:
+ IMemoryBlock(sp<IMemory> heap, uint64_t size, uint64_t offset)
+ : IMemoryDecorator(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) {
+ if (!validRange(start, length)) {
+ ALOGE("IMemoryBlock::readRange: out of range");
+ Status status;
+ status.setException(Status::EX_ILLEGAL_ARGUMENT, "out of range");
+ return Return<void>(status);
+ }
+ 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<uint64_t> getSize() override { return mSize; }
+ Return<void*> getPointer() override {
+ void* p = mHeap->getPointer();
+ return (static_cast<char*>(p) + mOffset);
+ }
+
+ protected:
+ 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 IMemoryCacheable(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 IMemoryBlock(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..e9196a1
--- /dev/null
+++ b/libhidlcache/MemoryDealer.cpp
@@ -0,0 +1,324 @@
+/*
+ * 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.head() == 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;
+ mList.erase(pos);
+ delete cur;
+ }
+ }
+ 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 0;
+}
+
+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 59ce7a8..2135ef3 100644
--- a/libhidlmemory/Android.bp
+++ b/libhidlmemory/Android.bp
@@ -19,7 +19,7 @@
enabled: true,
support_system_process: true,
},
- cflags: libhidl_flags,
+ defaults: ["libhidl-defaults"],
shared_libs: [
"libbase",
"liblog",
@@ -27,17 +27,20 @@
"libcutils",
"libhidlbase",
"libhidltransport",
- "android.hidl.memory@1.0"
+ "android.hidl.memory@1.0",
+ "android.hidl.memory.token@1.0",
],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
export_shared_lib_headers: [
"android.hidl.memory@1.0",
+ "android.hidl.memory.token@1.0",
"libhidlbase"
],
srcs: [
+ "HidlMemoryToken.cpp",
"mapping.cpp"
],
diff --git a/libhidlmemory/HidlMemoryToken.cpp b/libhidlmemory/HidlMemoryToken.cpp
new file mode 100644
index 0000000..3840183
--- /dev/null
+++ b/libhidlmemory/HidlMemoryToken.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <hidlmemory/HidlMemoryToken.h>
+
+namespace android {
+namespace hardware {
+
+HidlMemoryToken::HidlMemoryToken(sp<HidlMemory> memory) : mMemory(memory) {}
+
+Return<void> HidlMemoryToken::get(get_cb _hidl_cb) {
+ _hidl_cb(*mMemory);
+ return Void();
+}
+
+} // namespace hardware
+} // namespace android
diff --git a/libhidlmemory/include/hidlmemory/HidlMemoryToken.h b/libhidlmemory/include/hidlmemory/HidlMemoryToken.h
new file mode 100644
index 0000000..4020377
--- /dev/null
+++ b/libhidlmemory/include/hidlmemory/HidlMemoryToken.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 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_HIDLMEMORYTOKEN_H
+#define ANDROID_HARDWARE_HIDLMEMORYTOKEN_H
+
+#include <android/hidl/memory/token/1.0/IMemoryToken.h>
+
+namespace android {
+namespace hardware {
+
+class HidlMemoryToken : public virtual ::android::hidl::memory::token::V1_0::IMemoryToken {
+ public:
+ Return<void> get(get_cb _hidl_cb) override;
+
+ HidlMemoryToken(sp<HidlMemory> memory);
+
+ protected:
+ sp<HidlMemory> mMemory;
+};
+
+} // namespace hardware
+} // namespace android
+#endif
diff --git a/libhidlmemory/include/hidlmemory/mapping.h b/libhidlmemory/include/hidlmemory/mapping.h
index 5e1dab3..352cbaf 100644
--- a/libhidlmemory/include/hidlmemory/mapping.h
+++ b/libhidlmemory/include/hidlmemory/mapping.h
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef ANDROID_HARDWARE_MAPPING_H
+#define ANDROID_HARDWARE_MAPPING_H
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidl/HidlSupport.h>
@@ -22,8 +24,12 @@
/**
* Returns the IMemory instance corresponding to a hidl_memory object.
* If the shared memory cannot be fetched, this returns nullptr.
+ *
+ * Note, this method call is relatively expensive and does not cache conversions.
+ * It should only be done when initializing a buffer and not on every buffer read.
*/
sp<android::hidl::memory::V1_0::IMemory> mapMemory(const hidl_memory &memory);
} // namespace hardware
} // namespace android
+#endif
diff --git a/minijail/Android.bp b/minijail/Android.bp
new file mode 100644
index 0000000..c01a12b
--- /dev/null
+++ b/minijail/Android.bp
@@ -0,0 +1,13 @@
+cc_library_shared {
+ name: "libhwminijail",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ export_include_dirs: ["include"],
+
+ srcs: ["HardwareMinijail.cpp"],
+
+ shared_libs: [
+ "libbase",
+ "libminijail",
+ ],
+}
diff --git a/minijail/HardwareMinijail.cpp b/minijail/HardwareMinijail.cpp
new file mode 100644
index 0000000..e6b1144
--- /dev/null
+++ b/minijail/HardwareMinijail.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2017 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 <android-base/logging.h>
+#include <libminijail.h>
+
+#include <hwminijail/HardwareMinijail.h>
+
+namespace android {
+namespace hardware {
+
+void SetupMinijail(const std::string& seccomp_policy_path) {
+ if (access(seccomp_policy_path.c_str(), R_OK) == -1) {
+ LOG(WARNING) << "Could not find seccomp policy file at: " << seccomp_policy_path;
+ return;
+ }
+
+ struct minijail* jail = minijail_new();
+ if (jail == NULL) {
+ LOG(FATAL) << "Failed to create minijail.";
+ }
+
+ minijail_no_new_privs(jail);
+ minijail_log_seccomp_filter_failures(jail);
+ minijail_use_seccomp_filter(jail);
+ minijail_parse_seccomp_filters(jail, seccomp_policy_path.c_str());
+ minijail_enter(jail);
+ minijail_destroy(jail);
+}
+
+} // namespace hardware
+} // namespace android
diff --git a/minijail/include/hwminijail/HardwareMinijail.h b/minijail/include/hwminijail/HardwareMinijail.h
new file mode 100644
index 0000000..8fcf007
--- /dev/null
+++ b/minijail/include/hwminijail/HardwareMinijail.h
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2017 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_CONFIGSTORE_MINIJAIL_H
+#define ANDROID_HARDWARE_CONFIGSTORE_MINIJAIL_H
+
+#include <string>
+
+namespace android {
+namespace hardware {
+
+void SetupMinijail(const std::string& seccomp_policy_path);
+
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
diff --git a/test_main.cpp b/test_main.cpp
index 1f2f845..0de46ec 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -17,11 +17,15 @@
#define LOG_TAG "LibHidlTest"
#include <android-base/logging.h>
+#include <android/hardware/tests/inheritance/1.0/IParent.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>
+#include <condition_variable>
+#include <fstream>
#include <vector>
#define EXPECT_ARRAYEQ(__a1__, __a2__, __size__) EXPECT_TRUE(isArrayEqual(__a1__, __a2__, __size__))
@@ -45,6 +49,17 @@
return true;
}
+bool isLibraryOpen(const std::string& lib) {
+ std::ifstream ifs("/proc/self/maps");
+ for (std::string line; std::getline(ifs, line);) {
+ if (line.size() >= lib.size() && line.substr(line.size() - lib.size()) == lib) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
class LibHidlTest : public ::testing::Test {
public:
virtual void SetUp() override {
@@ -75,9 +90,9 @@
EXPECT_STREQ(s6.c_str(), "s6");
hidl_string s7 = std::string("s7"); // copy = from std::string
EXPECT_STREQ(s7.c_str(), "s7");
- hidl_string s8(s7); // copy constructor
+ hidl_string s8(s7); // copy constructor // NOLINT, test the copy constructor
EXPECT_STREQ(s8.c_str(), "s7");
- hidl_string s9 = s8; // copy =
+ hidl_string s9 = s8; // copy = // NOLINT, test the copy operator
EXPECT_STREQ(s9.c_str(), "s7");
char myCString[20] = "myCString";
s.setToExternal(&myCString[0], strlen(myCString));
@@ -153,14 +168,14 @@
using android::hardware::hidl_memory;
hidl_memory mem1 = hidl_memory(); // default constructor
- hidl_memory mem2 = mem1; // copy constructor (nullptr)
+ hidl_memory mem2 = mem1; // copy constructor (nullptr), NOLINT
EXPECT_EQ(nullptr, mem2.handle());
native_handle_t* testHandle = native_handle_create(0 /* numInts */, 0 /* numFds */);
hidl_memory mem3 = hidl_memory("foo", testHandle, 42 /* size */); // owns testHandle
- hidl_memory mem4 = mem3; // copy constructor (regular handle)
+ hidl_memory mem4 = mem3; // copy constructor (regular handle), NOLINT
EXPECT_EQ(mem3.name(), mem4.name());
EXPECT_EQ(mem3.size(), mem4.size());
@@ -168,7 +183,7 @@
EXPECT_NE(mem3.handle(), mem4.handle()); // check handle cloned
hidl_memory mem5 = hidl_memory("foo", nullptr, 0); // hidl memory works with nullptr handle
- hidl_memory mem6 = mem5;
+ hidl_memory mem6 = mem5; // NOLINT, test copying
EXPECT_EQ(nullptr, mem5.handle());
EXPECT_EQ(nullptr, mem6.handle());
}
@@ -179,6 +194,9 @@
int32_t array[] = {5, 6, 7};
vector<int32_t> v(array, array + 3);
+ hidl_vec<int32_t> hv0(3); // size
+ EXPECT_EQ(hv0.size(), 3ul); // cannot say anything about its contents
+
hidl_vec<int32_t> hv1 = v; // copy =
EXPECT_ARRAYEQ(hv1, array, 3);
EXPECT_ARRAYEQ(hv1, v, 3);
@@ -296,16 +314,23 @@
TEST_F(LibHidlTest, TaskRunnerTest) {
using android::hardware::details::TaskRunner;
+ using namespace std::chrono_literals;
+
+ std::condition_variable cv;
+ std::mutex m;
+
TaskRunner tr;
tr.start(1 /* limit */);
bool flag = false;
tr.push([&] {
- usleep(1000);
flag = true;
+ cv.notify_all();
});
- usleep(500);
- EXPECT_FALSE(flag);
- usleep(1000);
+
+ std::unique_lock<std::mutex> lock(m);
+
+ // 1s so this doesn't deadlock. This isn't a performance test.
+ EXPECT_TRUE(cv.wait_for(lock, 1s, [&]{return flag;}));
EXPECT_TRUE(flag);
}
@@ -430,7 +455,17 @@
EXPECT_THAT(toString(Status::fromExceptionCode(Status::EX_NULL_POINTER)),
HasSubstr("EX_NULL_POINTER"));
+}
+TEST_F(LibHidlTest, PreloadTest) {
+ using ::android::hardware::preloadPassthroughService;
+ using ::android::hardware::tests::inheritance::V1_0::IParent;
+
+ static const std::string kLib = "android.hardware.tests.inheritance@1.0-impl.so";
+
+ EXPECT_FALSE(isLibraryOpen(kLib));
+ preloadPassthroughService<IParent>();
+ EXPECT_TRUE(isLibraryOpen(kLib));
}
int main(int argc, char **argv) {
diff --git a/transport/Android.bp b/transport/Android.bp
index cf499ef..5b0c11c 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -12,27 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-subdirs = [
- "allocator/1.0",
- "allocator/1.0/default",
- "base/1.0",
- "manager/1.0",
- "manager/1.1",
- "memory/1.0",
- "memory/1.0/default",
- "token/1.0",
- "token/1.0/utils",
-]
+hidl_package_root {
+ name: "android.hidl",
+ path: "system/libhidl/transport",
+}
-cc_library_shared {
+cc_library {
name: "libhidltransport",
vendor_available: true,
vndk: {
enabled: true,
support_system_process: true,
},
- defaults: ["hidl-module-defaults"],
- cflags: libhidl_flags,
+ defaults: [
+ "libhidl-defaults",
+ "hidl-module-defaults",
+ ],
shared_libs: [
"libbase",
"liblog",
@@ -43,7 +38,6 @@
"libvndksupport",
],
export_shared_lib_headers: [
- "libbase",
"libutils",
"libhidlbase",
],
@@ -68,6 +62,7 @@
srcs: [
"HidlBinderSupport.cpp",
+ "HidlPassthroughSupport.cpp",
"HidlTransportSupport.cpp",
"HidlTransportUtils.cpp",
"ServiceManagement.cpp",
@@ -78,5 +73,8 @@
debuggable: {
cflags: ["-DLIBHIDL_TARGET_DEBUGGABLE"],
},
+ enforce_vintf_manifest: {
+ cflags: ["-DENFORCE_VINTF_MANIFEST"]
+ },
},
}
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index 31e3be8..4f8d7c5 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -214,5 +214,20 @@
IPCThreadState::self()->joinThreadPool();
}
+int setupBinderPolling() {
+ int fd;
+ int err = IPCThreadState::self()->setupPolling(&fd);
+
+ if (err != OK) {
+ ALOGE("Failed to setup binder polling: %d (%s)", err, strerror(err));
+ }
+
+ return err == OK ? fd : -1;
+}
+
+status_t handleBinderPoll() {
+ return IPCThreadState::self()->handlePolledCommands();
+}
+
} // namespace hardware
} // namespace android
diff --git a/transport/HidlPassthroughSupport.cpp b/transport/HidlPassthroughSupport.cpp
new file mode 100644
index 0000000..e5eb164
--- /dev/null
+++ b/transport/HidlPassthroughSupport.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hidl/HidlPassthroughSupport.h>
+
+#include <hidl/HidlTransportUtils.h>
+#include <hidl/Static.h>
+
+using ::android::hidl::base::V1_0::IBase;
+
+namespace android {
+namespace hardware {
+namespace details {
+
+static sp<IBase> tryWrap(const std::string& descriptor, sp<IBase> iface) {
+ auto func = getBsConstructorMap().get(descriptor, nullptr);
+ if (!func) {
+ func = gBsConstructorMap.get(descriptor, nullptr);
+ }
+ if (func) {
+ return func(static_cast<void*>(iface.get()));
+ }
+ return nullptr;
+}
+
+sp<IBase> wrapPassthroughInternal(sp<IBase> iface) {
+ if (iface == nullptr || iface->isRemote()) {
+ // doesn't know how to handle it.
+ return iface;
+ }
+
+ // Consider the case when an AOSP interface is extended by partners.
+ // Then the partner's HAL interface library is loaded only in the vndk
+ // linker namespace, but not in the default linker namespace, where
+ // this code runs. As a result, BsConstructorMap in the latter does not
+ // have the entry for the descriptor name.
+ //
+ // Therefore, we try to wrap using the descript names of the parent
+ // types along the interface chain, instead of always using the descriptor
+ // name of the current interface.
+ sp<IBase> base;
+ auto ret = iface->interfaceChain([&](const auto& types) {
+ for (const std::string& descriptor : types) {
+ base = tryWrap(descriptor, iface);
+ if (base != nullptr) {
+ break; // wrap is successful. no need to lookup further.
+ }
+ }
+ });
+
+ if (!ret.isOk()) {
+ return nullptr;
+ }
+
+ // It is ensured that if this function is called with an instance of IType
+ // then the corresponding descriptor would be in the BsConstructorMap.
+ // This is because referencing IType implies that the interface library
+ // defining the type has already been loaded into the current linker
+ // namespace, and thus the library should have added an entry into the
+ // BsConstructorMap while executing the library's constructor.
+ return base;
+}
+
+} // namespace details
+} // namespace hardware
+} // namespace android
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
index a47ead9..c3a3031 100644
--- a/transport/HidlTransportSupport.cpp
+++ b/transport/HidlTransportSupport.cpp
@@ -16,6 +16,8 @@
#include <hidl/HidlTransportSupport.h>
#include <hidl/HidlBinderSupport.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+
namespace android {
namespace hardware {
@@ -28,6 +30,14 @@
joinBinderRpcThreadpool();
}
+int setupTransportPolling() {
+ return setupBinderPolling();
+}
+
+status_t handleTransportPoll(int /*fd*/) {
+ return handleBinderPoll();
+}
+
// TODO(b/122472540): only store one data item per object
template <typename V>
static void pruneMapLocked(ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, V>& map) {
@@ -85,5 +95,16 @@
return true;
}
+namespace details {
+int32_t getPidIfSharable() {
+#if LIBHIDL_TARGET_DEBUGGABLE
+ return getpid();
+#else
+ using android::hidl::manager::V1_0::IServiceManager;
+ return static_cast<int32_t>(IServiceManager::PidConstant::NO_PID);
+#endif
}
-}
+} // namespace details
+
+} // namespace hardware
+} // namespace android
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 72ac53a..01f83bd 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -29,11 +29,14 @@
#include <set>
#include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlInternal.h>
+#include <hidl/HidlTransportUtils.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/Parcel.h>
#include <vndksupport/linker.h>
@@ -90,7 +93,7 @@
}
ifs >> cmdline;
- size_t idx = cmdline.rfind("/");
+ size_t idx = cmdline.rfind('/');
if (idx != std::string::npos) {
cmdline = cmdline.substr(idx + 1);
}
@@ -98,29 +101,55 @@
return cmdline;
}
-void tryShortenProcessName(const std::string &packageName) {
+std::string packageWithoutVersion(const std::string& packageAndVersion) {
+ size_t at = packageAndVersion.find('@');
+ if (at == std::string::npos) return packageAndVersion;
+ return packageAndVersion.substr(0, at);
+}
+
+void tryShortenProcessName(const std::string& packageAndVersion) {
+ const static std::string kTasks = "/proc/self/task/";
+
+ // make sure that this binary name is in the same package
std::string processName = binaryName();
- if (!startsWith(processName, packageName)) {
+ // e.x. android.hardware.foo is this package
+ if (!startsWith(packageWithoutVersion(processName), packageWithoutVersion(packageAndVersion))) {
return;
}
- // e.x. android.hardware.module.foo@1.0 -> foo@1.0
- size_t lastDot = packageName.rfind('.');
- size_t secondDot = packageName.rfind('.', lastDot - 1);
+ // e.x. android.hardware.module.foo@1.2 -> foo@1.2
+ size_t lastDot = packageAndVersion.rfind('.');
+ if (lastDot == std::string::npos) return;
+ size_t secondDot = packageAndVersion.rfind('.', lastDot - 1);
+ if (secondDot == std::string::npos) return;
- if (secondDot == std::string::npos) {
- return;
+ std::string newName = processName.substr(secondDot + 1, std::string::npos);
+ ALOGI("Removing namespace from process name %s to %s.", processName.c_str(), newName.c_str());
+
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kTasks.c_str()), closedir);
+ if (dir == nullptr) return;
+
+ dirent* dp;
+ while ((dp = readdir(dir.get())) != nullptr) {
+ if (dp->d_type != DT_DIR) continue;
+ if (dp->d_name[0] == '.') continue;
+
+ std::fstream fs(kTasks + dp->d_name + "/comm");
+ if (!fs.is_open()) {
+ ALOGI("Could not rename process, failed read comm for %s.", dp->d_name);
+ continue;
+ }
+
+ std::string oldComm;
+ fs >> oldComm;
+
+ // don't rename if it already has an explicit name
+ if (startsWith(packageAndVersion, oldComm)) {
+ fs.seekg(0, fs.beg);
+ fs << newName;
+ }
}
-
- std::string newName = processName.substr(secondDot + 1,
- 16 /* TASK_COMM_LEN */ - 1);
- ALOGI("Removing namespace from process name %s to %s.",
- processName.c_str(), newName.c_str());
-
- int rc = pthread_setname_np(pthread_self(), newName.c_str());
- ALOGI_IF(rc != 0, "Removing namespace from process name %s failed.",
- processName.c_str());
}
namespace details {
@@ -139,7 +168,7 @@
sp<IServiceManager1_1> defaultServiceManager1_1() {
{
AutoMutex _l(details::gDefaultServiceManagerLock);
- if (details::gDefaultServiceManager != NULL) {
+ if (details::gDefaultServiceManager != nullptr) {
return details::gDefaultServiceManager;
}
@@ -151,11 +180,11 @@
waitForHwServiceManager();
- while (details::gDefaultServiceManager == NULL) {
+ while (details::gDefaultServiceManager == nullptr) {
details::gDefaultServiceManager =
fromBinder<IServiceManager1_1, BpHwServiceManager, BnHwServiceManager>(
- ProcessState::self()->getContextObject(NULL));
- if (details::gDefaultServiceManager == NULL) {
+ ProcessState::self()->getContextObject(nullptr));
+ if (details::gDefaultServiceManager == nullptr) {
LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
sleep(1);
}
@@ -225,7 +254,7 @@
if (!dir) return;
dirent* dp;
while ((dp = readdir(dir.get())) != nullptr) {
- pid_t pid = strtoll(dp->d_name, NULL, 0);
+ pid_t pid = strtoll(dp->d_name, nullptr, 0);
if (pid == 0) continue;
std::string mapsPath = proc + dp->d_name + "/maps";
std::ifstream ifs{mapsPath};
@@ -254,9 +283,10 @@
}
struct PassthroughServiceManager : IServiceManager1_1 {
- static void openLibs(const std::string& fqName,
- std::function<bool /* continue */(void* /* handle */,
- const std::string& /* lib */, const std::string& /* sym */)> eachLib) {
+ static void openLibs(
+ const std::string& fqName,
+ const std::function<bool /* continue */ (void* /* handle */, const std::string& /* lib */,
+ const std::string& /* sym */)>& eachLib) {
//fqName looks like android.hardware.foo@1.0::IFoo
size_t idx = fqName.find("::");
@@ -272,35 +302,49 @@
const std::string prefix = packageAndVersion + "-impl";
const std::string sym = "HIDL_FETCH_" + ifaceName;
- const int dlMode = RTLD_LAZY;
- void *handle = nullptr;
+ constexpr int dlMode = RTLD_LAZY;
+ void* handle = nullptr;
dlerror(); // clear
+ static std::string halLibPathVndkSp = android::base::StringPrintf(
+ HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, details::getVndkVersionStr().c_str());
std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
- HAL_LIBRARY_PATH_VNDK_SP, HAL_LIBRARY_PATH_SYSTEM};
+ halLibPathVndkSp, HAL_LIBRARY_PATH_SYSTEM};
+
#ifdef LIBHIDL_TARGET_DEBUGGABLE
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
if (trebleTestingOverride) {
+ // Load HAL implementations that are statically linked
+ handle = dlopen(nullptr, dlMode);
+ if (handle == nullptr) {
+ const char* error = dlerror();
+ LOG(ERROR) << "Failed to dlopen self: "
+ << (error == nullptr ? "unknown error" : error);
+ } 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.push_back(halLibraryPathVtsOverride);
+ paths.insert(paths.begin(), halLibraryPathVtsOverride);
}
}
#endif
+
for (const std::string& path : paths) {
std::vector<std::string> libs = search(path, prefix, ".so");
for (const std::string &lib : libs) {
const std::string fullPath = path + lib;
- if (path != HAL_LIBRARY_PATH_SYSTEM) {
- handle = android_load_sphal_library(fullPath.c_str(), dlMode);
- } else {
+ if (path == HAL_LIBRARY_PATH_SYSTEM) {
handle = dlopen(fullPath.c_str(), dlMode);
+ } else {
+ handle = android_load_sphal_library(fullPath.c_str(), dlMode);
}
if (handle == nullptr) {
@@ -340,7 +384,12 @@
return true; // this module doesn't provide this instance name
}
- registerReference(fqName, name);
+ // Actual fqname might be a subclass.
+ // This assumption is tested in vts_treble_vintf_test
+ using ::android::hardware::details::getDescriptor;
+ std::string actualFqName = getDescriptor(ret.get());
+ CHECK(actualFqName.size() > 0);
+ registerReference(actualFqName, name);
return false;
});
@@ -381,13 +430,17 @@
Return<void> debugDump(debugDump_cb _hidl_cb) override {
using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture;
using std::literals::string_literals::operator""s;
+ static std::string halLibPathVndkSp64 = android::base::StringPrintf(
+ HAL_LIBRARY_PATH_VNDK_SP_64BIT_FOR_VERSION, details::getVndkVersionStr().c_str());
+ static std::string halLibPathVndkSp32 = android::base::StringPrintf(
+ HAL_LIBRARY_PATH_VNDK_SP_32BIT_FOR_VERSION, details::getVndkVersionStr().c_str());
static std::vector<std::pair<Arch, std::vector<const char*>>> sAllPaths{
{Arch::IS_64BIT,
{HAL_LIBRARY_PATH_ODM_64BIT, HAL_LIBRARY_PATH_VENDOR_64BIT,
- HAL_LIBRARY_PATH_VNDK_SP_64BIT, HAL_LIBRARY_PATH_SYSTEM_64BIT}},
+ halLibPathVndkSp64.c_str(), HAL_LIBRARY_PATH_SYSTEM_64BIT}},
{Arch::IS_32BIT,
{HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT,
- HAL_LIBRARY_PATH_VNDK_SP_32BIT, HAL_LIBRARY_PATH_SYSTEM_32BIT}}};
+ halLibPathVndkSp32.c_str(), HAL_LIBRARY_PATH_SYSTEM_32BIT}}};
std::map<std::string, InstanceDebugInfo> map;
for (const auto &pair : sAllPaths) {
Arch arch = pair.first;
@@ -454,6 +507,48 @@
}
struct Waiter : IServiceNotification {
+ Waiter(const std::string& interface, const std::string& instanceName,
+ const sp<IServiceManager1_1>& sm) : mInterfaceName(interface),
+ mInstanceName(instanceName), mSm(sm) {
+ }
+
+ void onFirstRef() override {
+ // If this process only has one binder thread, and we're calling wait() from
+ // that thread, it will block forever because we hung up the one and only
+ // binder thread on a condition variable that can only be notified by an
+ // incoming binder call.
+ if (IPCThreadState::self()->isOnlyBinderThread()) {
+ LOG(WARNING) << "Can't efficiently wait for " << mInterfaceName << "/"
+ << mInstanceName << ", because we are called from "
+ << "the only binder thread in this process.";
+ return;
+ }
+
+ Return<bool> ret = mSm->registerForNotifications(mInterfaceName, mInstanceName, this);
+
+ if (!ret.isOk()) {
+ LOG(ERROR) << "Transport error, " << ret.description()
+ << ", during notification registration for " << mInterfaceName << "/"
+ << mInstanceName << ".";
+ return;
+ }
+
+ if (!ret) {
+ LOG(ERROR) << "Could not register for notifications for " << mInterfaceName << "/"
+ << mInstanceName << ".";
+ return;
+ }
+
+ mRegisteredForNotifications = true;
+ }
+
+ ~Waiter() {
+ if (!mDoneCalled) {
+ LOG(FATAL)
+ << "Waiter still registered for notifications, call done() before dropping ref!";
+ }
+ }
+
Return<void> onRegistration(const hidl_string& /* fqName */,
const hidl_string& /* name */,
bool /* preexisting */) override {
@@ -468,9 +563,16 @@
return Void();
}
- void wait(const std::string &interface, const std::string &instanceName) {
+ void wait() {
using std::literals::chrono_literals::operator""s;
+ if (!mRegisteredForNotifications) {
+ // As an alternative, just sleep for a second and return
+ LOG(WARNING) << "Waiting one second for " << mInterfaceName << "/" << mInstanceName;
+ sleep(1);
+ return;
+ }
+
std::unique_lock<std::mutex> lock(mMutex);
while(true) {
mCondition.wait_for(lock, 1s, [this]{
@@ -481,49 +583,179 @@
break;
}
- LOG(WARNING) << "Waited one second for "
- << interface << "/" << instanceName
+ LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName
<< ". Waiting another...";
}
}
-private:
+ // Be careful when using this; after calling reset(), you must always try to retrieve
+ // the corresponding service before blocking on the waiter; otherwise, you might run
+ // into a race-condition where the service has just (re-)registered, you clear the state
+ // here, and subsequently calling waiter->wait() will block forever.
+ void reset() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mRegistered = false;
+ }
+
+ // done() must be called before dropping the last strong ref to the Waiter, to make
+ // sure we can properly unregister with hwservicemanager.
+ void done() {
+ if (mRegisteredForNotifications) {
+ if (!mSm->unregisterForNotifications(mInterfaceName, mInstanceName, this)
+ .withDefault(false)) {
+ LOG(ERROR) << "Could not unregister service notification for " << mInterfaceName
+ << "/" << mInstanceName << ".";
+ } else {
+ mRegisteredForNotifications = false;
+ }
+ }
+ mDoneCalled = true;
+ }
+
+ private:
+ const std::string mInterfaceName;
+ const std::string mInstanceName;
+ const sp<IServiceManager1_1>& mSm;
std::mutex mMutex;
std::condition_variable mCondition;
bool mRegistered = false;
+ bool mRegisteredForNotifications = false;
+ bool mDoneCalled = false;
};
void waitForHwService(
const std::string &interface, const std::string &instanceName) {
- const sp<IServiceManager1_1> manager = defaultServiceManager1_1();
+ sp<Waiter> waiter = new Waiter(interface, instanceName, defaultServiceManager1_1());
+ waiter->wait();
+ waiter->done();
+}
- if (manager == nullptr) {
- LOG(ERROR) << "Could not get default service manager.";
- return;
+// Prints relevant error/warning messages for error return values from
+// details::canCastInterface(), both transaction errors (!castReturn.isOk())
+// as well as actual cast failures (castReturn.isOk() && castReturn = false).
+// Returns 'true' if the error is non-fatal and it's useful to retry
+bool handleCastError(const Return<bool>& castReturn, const std::string& descriptor,
+ const std::string& instance) {
+ if (castReturn.isOk()) {
+ if (castReturn) {
+ details::logAlwaysFatal("Successful cast value passed into handleCastError.");
+ }
+ // This should never happen, and there's not really a point in retrying.
+ ALOGE("getService: received incompatible service (bug in hwservicemanager?) for "
+ "%s/%s.", descriptor.c_str(), instance.c_str());
+ return false;
+ }
+ if (castReturn.isDeadObject()) {
+ ALOGW("getService: found dead hwbinder service for %s/%s.", descriptor.c_str(),
+ instance.c_str());
+ return true;
+ }
+ // This can happen due to:
+ // 1) No SELinux permissions
+ // 2) Other transaction failure (no buffer space, kernel error)
+ // The first isn't recoverable, but the second is.
+ // Since we can't yet differentiate between the two, and clients depend
+ // on us not blocking in case 1), treat this as a fatal error for now.
+ ALOGW("getService: unable to call into hwbinder service for %s/%s.",
+ descriptor.c_str(), instance.c_str());
+ return false;
+}
+
+sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
+ const std::string& instance,
+ bool retry, bool getStub) {
+ using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
+ using ::android::hidl::base::V1_0::IBase;
+ using ::android::hidl::manager::V1_0::IServiceManager;
+ sp<Waiter> waiter;
+
+ const sp<IServiceManager1_1> sm = defaultServiceManager1_1();
+ if (sm == nullptr) {
+ ALOGE("getService: defaultServiceManager() is null");
+ return nullptr;
}
- sp<Waiter> waiter = new Waiter();
- Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter);
+ Return<Transport> transportRet = sm->getTransport(descriptor, instance);
- if (!ret.isOk()) {
- LOG(ERROR) << "Transport error, " << ret.description()
- << ", during notification registration for "
- << interface << "/" << instanceName << ".";
- return;
+ if (!transportRet.isOk()) {
+ ALOGE("getService: defaultServiceManager()->getTransport returns %s",
+ transportRet.description().c_str());
+ return nullptr;
+ }
+ Transport transport = transportRet;
+ const bool vintfHwbinder = (transport == Transport::HWBINDER);
+ const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
+
+#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) {
+ waiter = new Waiter(descriptor, instance, sm);
+ }
+ if (waiter != nullptr) {
+ waiter->reset(); // don't reorder this -- see comments on reset()
+ }
+ Return<sp<IBase>> ret = sm->get(descriptor, instance);
+ if (!ret.isOk()) {
+ ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",
+ ret.description().c_str(), descriptor.c_str(), instance.c_str());
+ break;
+ }
+ sp<IBase> base = ret;
+ if (base != nullptr) {
+ Return<bool> canCastRet =
+ details::canCastInterface(base.get(), descriptor.c_str(), true /* emitError */);
+
+ if (canCastRet.isOk() && canCastRet) {
+ if (waiter != nullptr) {
+ waiter->done();
+ }
+ return base; // still needs to be wrapped by Bp class.
+ }
+
+ if (!handleCastError(canCastRet, descriptor, instance)) break;
+ }
+
+ // In case of legacy or we were not asked to retry, don't.
+ if (vintfLegacy || !retry) break;
+
+ if (waiter != nullptr) {
+ ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
+ waiter->wait();
+ }
}
- if (!ret) {
- LOG(ERROR) << "Could not register for notifications for "
- << interface << "/" << instanceName << ".";
- return;
+ if (waiter != nullptr) {
+ waiter->done();
}
- waiter->wait(interface, instanceName);
-
- if (!manager->unregisterForNotifications(interface, instanceName, waiter).withDefault(false)) {
- LOG(ERROR) << "Could not unregister service notification for "
- << interface << "/" << instanceName << ".";
+ if (getStub || vintfPassthru || vintfLegacy) {
+ const sp<IServiceManager> pm = getPassthroughServiceManager();
+ if (pm != nullptr) {
+ sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
+ if (!getStub || trebleTestingOverride) {
+ base = wrapPassthrough(base);
+ }
+ return base;
+ }
}
+
+ return nullptr;
}
}; // namespace details
diff --git a/transport/Static.cpp b/transport/Static.cpp
index b599c5c..a506644 100644
--- a/transport/Static.cpp
+++ b/transport/Static.cpp
@@ -29,8 +29,8 @@
Mutex gDefaultServiceManagerLock;
sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
-ConcurrentMap<std::string, std::function<sp<IBinder>(void *)>>
- gBnConstructorMap{};
+// Deprecated; kept for ABI compatibility. Use getBnConstructorMap.
+BnConstructorMap gBnConstructorMap{};
ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>
gBnMap{};
@@ -39,8 +39,20 @@
ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap{};
ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool> gServiceSidMap{};
-ConcurrentMap<std::string, std::function<sp<::android::hidl::base::V1_0::IBase>(void *)>>
- gBsConstructorMap;
+// Deprecated; kept for ABI compatibility. Use getBsConstructorMap.
+BsConstructorMap gBsConstructorMap{};
+
+// For static executables, it is not guaranteed that gBnConstructorMap are initialized before
+// used in HAL definition libraries.
+BnConstructorMap& getBnConstructorMap() {
+ static BnConstructorMap map{};
+ return map;
+}
+
+BsConstructorMap& getBsConstructorMap() {
+ static BsConstructorMap map{};
+ return map;
+}
} // namespace details
} // namespace hardware
diff --git a/transport/allocator/1.0/Android.bp b/transport/allocator/1.0/Android.bp
index c64a039..a3d885a 100644
--- a/transport/allocator/1.0/Android.bp
+++ b/transport/allocator/1.0/Android.bp
@@ -1,62 +1,17 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
+// This file is autogenerated by hidl-gen -Landroidbp.
-filegroup {
- name: "android.hidl.allocator@1.0_hal",
- srcs: [
- "IAllocator.hal",
- ],
-}
-
-genrule {
- name: "android.hidl.allocator@1.0_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hidl:system/libhidl/transport android.hidl.allocator@1.0",
- srcs: [
- ":android.hidl.allocator@1.0_hal",
- ],
- out: [
- "android/hidl/allocator/1.0/AllocatorAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hidl.allocator@1.0_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hidl:system/libhidl/transport android.hidl.allocator@1.0",
- srcs: [
- ":android.hidl.allocator@1.0_hal",
- ],
- out: [
- "android/hidl/allocator/1.0/IAllocator.h",
- "android/hidl/allocator/1.0/IHwAllocator.h",
- "android/hidl/allocator/1.0/BnHwAllocator.h",
- "android/hidl/allocator/1.0/BpHwAllocator.h",
- "android/hidl/allocator/1.0/BsAllocator.h",
- ],
-}
-
-cc_library {
+hidl_interface {
name: "android.hidl.allocator@1.0",
- defaults: ["hidl-module-defaults"],
- generated_sources: ["android.hidl.allocator@1.0_genc++"],
- generated_headers: ["android.hidl.allocator@1.0_genc++_headers"],
- export_generated_headers: ["android.hidl.allocator@1.0_genc++_headers"],
- vendor_available: true,
+ root: "android.hidl",
vndk: {
enabled: true,
},
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
+ srcs: [
+ "IAllocator.hal",
],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
+ interfaces: [
+ "android.hidl.base@1.0",
],
+ gen_java: false,
}
+
diff --git a/transport/allocator/1.0/default/Android.bp b/transport/allocator/1.0/default/Android.bp
index 7d5fd8b..fc352c3 100644
--- a/transport/allocator/1.0/default/Android.bp
+++ b/transport/allocator/1.0/default/Android.bp
@@ -15,7 +15,7 @@
cc_binary {
name: "android.hidl.allocator@1.0-service",
relative_install_path: "hw",
- cflags: libhidl_flags,
+ defaults: ["libhidl-defaults"],
srcs: [
"AshmemAllocator.cpp",
"service.cpp"
diff --git a/transport/allocator/1.0/utils/Android.bp b/transport/allocator/1.0/utils/Android.bp
new file mode 100644
index 0000000..b1a3f41
--- /dev/null
+++ b/transport/allocator/1.0/utils/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 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: "libhidlallocatorutils",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ defaults: ["libhidl-defaults"],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "android.hidl.memory@1.0"
+ ],
+ export_include_dirs: ["include"],
+
+ export_shared_lib_headers: [
+ "libbinder",
+ "libhidlbase"
+ ],
+
+ srcs: [
+ "FrameworkUtils.cpp"
+ ],
+}
diff --git a/transport/allocator/1.0/utils/FrameworkUtils.cpp b/transport/allocator/1.0/utils/FrameworkUtils.cpp
new file mode 100644
index 0000000..fec83ac
--- /dev/null
+++ b/transport/allocator/1.0/utils/FrameworkUtils.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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 <unistd.h>
+
+#include <hidlmemory/FrameworkUtils.h>
+
+namespace android {
+
+namespace hardware {
+
+sp<HidlMemory> fromHeap(const sp<IMemoryHeap>& heap) {
+ int fd = dup(heap->getHeapID());
+
+ if (fd < 0) {
+ return HidlMemory::getInstance(hidl_memory());
+ }
+
+ // Only being used because this library is paired with the IAllocator
+ // ashmem. Other places should not make assumptions about the contents
+ // of this memory.
+ return HidlMemory::getInstance("ashmem", fd, heap->getSize());
+}
+
+} // namespace hardware
+} // namespace android
diff --git a/transport/allocator/1.0/utils/include/hidlmemory/FrameworkUtils.h b/transport/allocator/1.0/utils/include/hidlmemory/FrameworkUtils.h
new file mode 100644
index 0000000..0a62575
--- /dev/null
+++ b/transport/allocator/1.0/utils/include/hidlmemory/FrameworkUtils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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 <binder/IMemory.h>
+#include <hidl/HidlSupport.h>
+
+namespace android {
+
+namespace hardware {
+
+/**
+ * Returns a new IMemory instance corresponding to a framework IMemoryHeap object.
+ * This encapsulates the idea that IMemoryHeap and the ashmem instance of hidl
+ * IMemory are backed by the same object.
+ *
+ * Return is never nullptr. May be an invalid hidl_memory object.
+ */
+sp<HidlMemory> fromHeap(const sp<IMemoryHeap>& heap);
+
+} // namespace hardware
+} // namespace android
diff --git a/transport/base/1.0/Android.bp b/transport/base/1.0/Android.bp
index 8382824..bd2ae49 100644
--- a/transport/base/1.0/Android.bp
+++ b/transport/base/1.0/Android.bp
@@ -1,42 +1,19 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
+// This file is autogenerated by hidl-gen -Landroidbp.
-filegroup {
- name: "android.hidl.base@1.0_hal",
+hidl_interface {
+ name: "android.hidl.base@1.0",
+ root: "android.hidl",
+ core_interface: true,
+ vndk: {
+ enabled: true,
+ },
srcs: [
"types.hal",
"IBase.hal",
],
+ types: [
+ "DebugInfo",
+ ],
+ gen_java: true,
}
-genrule {
- name: "android.hidl.base@1.0_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hidl:system/libhidl/transport android.hidl.base@1.0",
- srcs: [
- ":android.hidl.base@1.0_hal",
- ],
- out: [
- "android/hidl/base/1.0/types.cpp",
- "android/hidl/base/1.0/BaseAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hidl.base@1.0_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hidl:system/libhidl/transport android.hidl.base@1.0",
- srcs: [
- ":android.hidl.base@1.0_hal",
- ],
- out: [
- "android/hidl/base/1.0/types.h",
- "android/hidl/base/1.0/hwtypes.h",
- "android/hidl/base/1.0/IBase.h",
- "android/hidl/base/1.0/IHwBase.h",
- "android/hidl/base/1.0/BnHwBase.h",
- "android/hidl/base/1.0/BpHwBase.h",
- "android/hidl/base/1.0/BsBase.h",
- ],
-}
-
-// android.hidl.base@1.0 is exported from libhidltransport
diff --git a/transport/base/1.0/Android.mk b/transport/base/1.0/Android.mk
deleted file mode 100644
index 2031a92..0000000
--- a/transport/base/1.0/Android.mk
+++ /dev/null
@@ -1,106 +0,0 @@
-# This file is autogenerated by hidl-gen. Do not edit manually.
-
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.base-V1.0-java
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-#
-# Build types.hal (DebugInfo)
-#
-GEN := $(intermediates)/android/hidl/base/V1_0/DebugInfo.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.base@1.0::types.DebugInfo
-
-$(GEN): $(LOCAL_PATH)/types.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IBase.hal
-#
-GEN := $(intermediates)/android/hidl/base/V1_0/IBase.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IBase.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
-$(GEN): $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.base@1.0::IBase
-
-$(GEN): $(LOCAL_PATH)/IBase.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_JAVA_LIBRARY)
-
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.base-V1.0-java-static
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-#
-# Build types.hal (DebugInfo)
-#
-GEN := $(intermediates)/android/hidl/base/V1_0/DebugInfo.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.base@1.0::types.DebugInfo
-
-$(GEN): $(LOCAL_PATH)/types.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IBase.hal
-#
-GEN := $(intermediates)/android/hidl/base/V1_0/IBase.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IBase.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
-$(GEN): $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.base@1.0::IBase
-
-$(GEN): $(LOCAL_PATH)/IBase.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/transport/base/1.0/vts/functional/Android.bp b/transport/base/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..f0bd45c
--- /dev/null
+++ b/transport/base/1.0/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 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_test {
+ name: "vts_ibase_test",
+ srcs: [
+ "vts_ibase_test.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+}
+
diff --git a/transport/base/1.0/vts/functional/Android.mk b/transport/base/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..61c6e31
--- /dev/null
+++ b/transport/base/1.0/vts/functional/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsHalBaseV1_0TargetTest
+-include test/vts/tools/build/Android.host_config.mk
diff --git a/transport/base/1.0/vts/functional/AndroidTest.xml b/transport/base/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..80154f2
--- /dev/null
+++ b/transport/base/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsHalBaseV1_0TargetTest test cases">
+ <option name="config-descriptor:metadata" key="plan" value="vts-treble" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="abort-on-push-failure" value="false"/>
+ <option name="push-group" value="HalHidlTargetTest.push"/>
+ </target_preparer>
+ <multi_target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsHalBaseV1_0TargetTest"/>
+ <option name="binary-test-working-directory" value="_32bit::/data/nativetest/" />
+ <option name="binary-test-working-directory" value="_64bit::/data/nativetest64/" />
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_ibase_test/vts_ibase_test" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_ibase_test/vts_ibase_test" />
+ <option name="binary-test-type" value="gtest"/>
+ <option name="test-timeout" value="5m"/>
+ </test>
+</configuration>
diff --git a/transport/base/1.0/vts/functional/vts_ibase_test.cpp b/transport/base/1.0/vts/functional/vts_ibase_test.cpp
new file mode 100644
index 0000000..6d66042
--- /dev/null
+++ b/transport/base/1.0/vts/functional/vts_ibase_test.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2017 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 <functional>
+#include <map>
+#include <string>
+
+#include <android/hidl/base/1.0/IBase.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlBinderSupport.h>
+#include <hidl/ServiceManagement.h>
+
+using android::hardware::hidl_array;
+using android::hardware::hidl_death_recipient;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::IBinder;
+using android::hardware::toBinder;
+using android::hidl::base::V1_0::IBase;
+using android::hidl::manager::V1_0::IServiceManager;
+using android::sp;
+using android::wp;
+
+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());
+}
+#define ASSERT_OK(__ret__) ASSERT_TRUE(isOk(__ret__))
+#define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
+
+struct Hal {
+ sp<IBase> service;
+ std::string name; // space separated list of android.hidl.foo@1.0::IFoo/instance-name
+};
+
+class VtsHalBaseV1_0TargetTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ default_manager_ = ::android::hardware::defaultServiceManager();
+
+ ASSERT_NE(default_manager_, nullptr)
+ << "Failed to get default service manager." << std::endl;
+
+ ASSERT_OK(default_manager_->list([&](const auto& list) {
+ for (const auto& name : list) {
+ const std::string strName = name;
+ auto loc = strName.find_first_of('/');
+ if (loc == std::string::npos) {
+ ADD_FAILURE() << "Invalid FQName: " << strName;
+ continue;
+ }
+ const std::string fqName = strName.substr(0, loc);
+ const std::string instance = strName.substr(loc + 1);
+
+ sp<IBase> service = default_manager_->get(fqName, instance);
+ if (service == nullptr) {
+ ADD_FAILURE() << "Null service for " << name << " " << fqName << " "
+ << instance;
+ continue;
+ }
+
+ sp<IBinder> binder = toBinder(service);
+ if (binder == nullptr) {
+ ADD_FAILURE() << "Null binder for " << name;
+ continue;
+ }
+
+ auto iter = all_hals_.find(binder);
+ if (iter != all_hals_.end()) {
+ // include all the names this is registered as for error messages
+ iter->second.name += " " + strName;
+ } else {
+ all_hals_.insert(iter, {binder, Hal{service, strName}});
+ }
+ }
+ }));
+
+ ASSERT_FALSE(all_hals_.empty()); // sanity
+ }
+
+ void EachHal(const std::function<void(const Hal&)>& check) {
+ for (auto iter = all_hals_.begin(); iter != all_hals_.end(); ++iter) {
+ check(iter->second);
+ }
+ }
+
+ // default service manager
+ sp<IServiceManager> default_manager_;
+
+ // map from underlying instance to actual instance
+ //
+ // this prevents calling the same service twice since the same service
+ // will get registered multiple times for its entire inheritance
+ // hierarchy (or perhaps as different instance names)
+ std::map<sp<IBinder>, Hal> all_hals_;
+};
+
+TEST_F(VtsHalBaseV1_0TargetTest, CanPing) {
+ EachHal(
+ [&](const Hal& base) { EXPECT_OK(base.service->ping()) << "Cannot ping " << base.name; });
+}
+
+TEST_F(VtsHalBaseV1_0TargetTest, InterfaceChain) {
+ EachHal([&](const Hal& base) {
+ EXPECT_OK(base.service->interfaceChain([&](const auto& interfaceChain) {
+ // must include IBase + subclasses
+ EXPECT_GT(interfaceChain.size(), 1u) << "Invalid instance name " << base.name;
+ })) << base.name;
+ });
+}
+
+TEST_F(VtsHalBaseV1_0TargetTest, Descriptor) {
+ EachHal([&](const Hal& base) {
+ EXPECT_OK(base.service->interfaceDescriptor([&](const auto& descriptor) {
+ // must include IBase + subclasses
+ EXPECT_GT(descriptor.size(), 0u) << base.name;
+ EXPECT_NE(IBase::descriptor, descriptor) << base.name;
+ })) << base.name;
+ });
+}
+
+TEST_F(VtsHalBaseV1_0TargetTest, Death) {
+ struct HidlDeathRecipient : hidl_death_recipient {
+ virtual void serviceDied(uint64_t /* cookie */, const wp<IBase>& /* who */){};
+ };
+ sp<hidl_death_recipient> recipient = new HidlDeathRecipient;
+
+ EachHal([&](const Hal& base) {
+ EXPECT_OK(base.service->linkToDeath(recipient, 0 /* cookie */))
+ << "Register death recipient " << base.name;
+ EXPECT_OK(base.service->unlinkToDeath(recipient)) << "Unlink death recipient " << base.name;
+ });
+}
+
+TEST_F(VtsHalBaseV1_0TargetTest, Debug) {
+ EachHal([&](const Hal& base) {
+ // normally one is passed, but this is tested by dumpstate
+ EXPECT_OK(base.service->debug(hidl_handle(), {}))
+ << "Handle empty debug handle " << base.name;
+ });
+}
+
+TEST_F(VtsHalBaseV1_0TargetTest, HashChain) {
+ EachHal([&](const Hal& base) {
+ EXPECT_OK(base.service->getHashChain([&](const auto& hashChain) {
+ // must include IBase + subclasses
+ EXPECT_NE(0u, hashChain.size()) << "Invalid hash chain " << base.name;
+ })) << base.name;
+ });
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/transport/current.txt b/transport/current.txt
index 958d679..a48233c 100644
--- a/transport/current.txt
+++ b/transport/current.txt
@@ -15,3 +15,10 @@
# HALs released in Android O-MR1
0b94dc876f749ed24a98f61c41d46ad75a27511163f1968a084213a33c684ef6 android.hidl.manager@1.1::IServiceManager
+
+# HALs released in Android P
+445da29052612c57db3a8504f6395814277dc3826ee0f166cc732031b35af496 android.hidl.memory.block@1.0::types
+2e19301ceb87fb0696cd8268fab9c41f95d23c7392d35bc575daaa6eb32807eb android.hidl.memory.token@1.0::IMemoryToken
+
+# ABI preserving changes to HALs during Android Q
+fcde1d0788066a62d5766f4dc19d4c1ec76967d5ddb636f59ccc66603460bcf8 android.hidl.manager@1.0::IServiceNotification
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 47ff581..9759af1 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -306,7 +306,8 @@
// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
// and iface is of class IChild. BnChild will be used to wrapped the given iface.
// Return nullptr if iface is null or any failure.
-template <typename IType>
+template <typename IType,
+ typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>>
sp<IBinder> toBinder(sp<IType> iface) {
IType *ifacePtr = iface.get();
if (ifacePtr == nullptr) {
@@ -329,9 +330,12 @@
sp<IBinder> sBnObj = wBnObj.promote();
if (sBnObj == nullptr) {
- auto func = details::gBnConstructorMap.get(myDescriptor, nullptr);
+ auto func = details::getBnConstructorMap().get(myDescriptor, nullptr);
if (!func) {
- return nullptr;
+ func = details::gBnConstructorMap.get(myDescriptor, nullptr);
+ if (!func) {
+ return nullptr;
+ }
}
sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
@@ -367,6 +371,8 @@
void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin);
void joinBinderRpcThreadpool();
+int setupBinderPolling();
+status_t handleBinderPoll();
} // namespace hardware
} // namespace android
diff --git a/transport/include/hidl/HidlPassthroughSupport.h b/transport/include/hidl/HidlPassthroughSupport.h
index 4fb1ae4..a0f10f3 100644
--- a/transport/include/hidl/HidlPassthroughSupport.h
+++ b/transport/include/hidl/HidlPassthroughSupport.h
@@ -24,26 +24,25 @@
namespace details {
/*
- * Wrap the given interface with the smallest BsChild possible. Will return the
+ * Wrap the given interface with the lowest BsChild possible. Will return the
* argument directly if nullptr or isRemote().
+ *
+ * Note that 'static_cast<IFoo*>(wrapPassthrough(foo).get()) is guaranteed to work'
+ * assuming that foo is an instance of IFoo.
+ *
+ * TODO(b/33754152): calling this method multiple times should not re-wrap.
*/
-template<typename IType>
-sp<::android::hidl::base::V1_0::IBase> wrapPassthrough(
- sp<IType> iface) {
- if (iface.get() == nullptr || iface->isRemote()) {
- // doesn't know how to handle it.
- return iface;
- }
- std::string myDescriptor = getDescriptor(iface.get());
- if (myDescriptor.empty()) {
- // interfaceDescriptor fails
- return nullptr;
- }
- auto func = gBsConstructorMap.get(myDescriptor, nullptr);
- if (!func) {
- return nullptr;
- }
- return func(static_cast<void *>(iface.get()));
+sp<::android::hidl::base::V1_0::IBase> wrapPassthroughInternal(
+ sp<::android::hidl::base::V1_0::IBase> iface);
+
+/**
+ * Helper method which provides reasonable code to wrapPassthroughInternal
+ * which can be used to call wrapPassthrough.
+ */
+template <typename IType,
+ typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>>
+sp<IType> wrapPassthrough(sp<IType> iface) {
+ return static_cast<IType*>(wrapPassthroughInternal(iface).get());
}
} // namespace details
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 6a243f9..cdcb03e 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -19,8 +19,10 @@
#include <android/hidl/base/1.0/IBase.h>
#include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlPassthroughSupport.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportUtils.h>
+#include <hidl/ServiceManagement.h>
namespace android {
namespace hardware {
@@ -49,6 +51,26 @@
void joinRpcThreadpool();
/**
+ * Sets up the transport for use with (e)poll.
+ *
+ * Note that all currently supported transports can only be polled
+ * from a single thread. When poll() on the returned fd returns,
+ * the caller must call handleTransportPoll() to handle the result.
+ *
+ * @return the file descriptor to be used with (e)poll, or -1 in case of error.
+ */
+int setupTransportPolling();
+
+/**
+ * Handles transport work after poll() returns.
+ *
+ * @param fd returned from setupTransportPolling()
+ *
+ * @return OK when successful
+ */
+status_t handleTransportPoll(int fd);
+
+/**
* Sets a minimum scheduler policy for all transactions coming into this
* service.
*
@@ -62,7 +84,10 @@
bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
int policy, int priority);
-template <typename ILeft, typename IRight>
+template <typename ILeft,
+ typename IRight,
+ typename = std::enable_if_t<std::is_same<details::i_tag, typename ILeft::_hidl_tag>::value>,
+ typename = std::enable_if_t<std::is_same<details::i_tag, typename IRight::_hidl_tag>::value>>
bool interfacesEqual(sp<ILeft> left, sp<IRight> right) {
if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
return left == right;
@@ -85,6 +110,9 @@
namespace details {
+// Return PID on userdebug / eng builds and IServiceManager::PidConstant::NO_PID on user builds.
+int32_t getPidIfSharable();
+
// cast the interface IParent to IChild.
// Return nonnull if cast successful.
// Return nullptr if:
@@ -115,10 +143,30 @@
// binderized mode. Got BpChild. grab the remote and wrap it.
return sp<IChild>(new BpChild(toBinder<IParent>(parent)));
}
- // Passthrough mode. Got BnChild and BsChild.
+ // Passthrough mode. Got BnChild or BsChild.
return sp<IChild>(static_cast<IChild *>(parent.get()));
}
+template <typename BpType, typename IType = typename BpType::Pure,
+ typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>,
+ typename = std::enable_if_t<std::is_same<bphw_tag, typename BpType::_hidl_tag>::value>>
+sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getStub) {
+ using ::android::hidl::base::V1_0::IBase;
+
+ sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub);
+
+ if (base == nullptr) {
+ return nullptr;
+ }
+
+ if (base->isRemote()) {
+ // getRawServiceInternal guarantees we get the proper class
+ return sp<IType>(new BpType(toBinder<IBase>(base)));
+ }
+
+ return IType::castFrom(base);
+}
+
} // namespace details
} // namespace hardware
diff --git a/transport/include/hidl/LegacySupport.h b/transport/include/hidl/LegacySupport.h
index 2f0c3f3..f03d34d 100644
--- a/transport/include/hidl/LegacySupport.h
+++ b/transport/include/hidl/LegacySupport.h
@@ -74,7 +74,7 @@
}
joinRpcThreadpool();
- return 0;
+ return UNKNOWN_ERROR;
}
template<class Interface>
__attribute__((warn_unused_result))
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index d53cd7e..4df156b 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -18,6 +18,8 @@
#define ANDROID_HARDWARE_ISERVICE_MANAGER_H
#include <string>
+
+#include <android/hidl/base/1.0/IBase.h>
#include <utils/StrongPointer.h>
namespace android {
@@ -45,6 +47,16 @@
void waitForHwService(const std::string &interface, const std::string &instanceName);
void preloadPassthroughService(const std::string &descriptor);
+
+// Returns a service with the following constraints:
+// - retry => service is waited for and returned if available in this process
+// - getStub => internal only. Forces to get the unwrapped (no BsFoo) if available.
+// TODO(b/65843592)
+// If the service is a remote service, this function returns BpBase. If the service is
+// a passthrough service, this function returns the appropriately wrapped Bs child object.
+sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
+ const std::string& instance,
+ bool retry, bool getStub);
};
// These functions are for internal use by hidl. If you want to get ahold
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 17db3d1..b15be68 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -41,18 +41,22 @@
extern ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>
gBnMap;
+using BnConstructorMap = ConcurrentMap<std::string, std::function<sp<IBinder>(void*)>>;
// For HidlBinderSupport and autogenerated code
// value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
// returns sp<IBinder>
-extern ConcurrentMap<std::string,
- std::function<sp<IBinder>(void *)>> gBnConstructorMap;
+// deprecated; use getBnConstructorMap instead.
+extern BnConstructorMap gBnConstructorMap;
+BnConstructorMap& getBnConstructorMap();
+using BsConstructorMap = ConcurrentMap<std::string,
+ std::function<sp<::android::hidl::base::V1_0::IBase>(void*)>>;
// For HidlPassthroughSupport and autogenerated code
// value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
// returns sp<IBase>
-extern ConcurrentMap<std::string,
- std::function<sp<::android::hidl::base::V1_0::IBase>(void *)>> gBsConstructorMap;
-
+// deprecated; use getBsConstructorMap instead.
+extern BsConstructorMap gBsConstructorMap;
+BsConstructorMap& getBsConstructorMap();
} // namespace details
} // namespace hardware
} // namespace android
diff --git a/transport/manager/1.0/Android.bp b/transport/manager/1.0/Android.bp
index 8bdbfa5..e4a120b 100644
--- a/transport/manager/1.0/Android.bp
+++ b/transport/manager/1.0/Android.bp
@@ -1,45 +1,19 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
+// This file is autogenerated by hidl-gen -Landroidbp.
-filegroup {
- name: "android.hidl.manager@1.0_hal",
+hidl_interface {
+ name: "android.hidl.manager@1.0",
+ root: "android.hidl",
+ core_interface: true,
+ vndk: {
+ enabled: true,
+ },
srcs: [
"IServiceManager.hal",
"IServiceNotification.hal",
],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
}
-genrule {
- name: "android.hidl.manager@1.0_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hidl:system/libhidl/transport android.hidl.manager@1.0",
- srcs: [
- ":android.hidl.manager@1.0_hal",
- ],
- out: [
- "android/hidl/manager/1.0/ServiceManagerAll.cpp",
- "android/hidl/manager/1.0/ServiceNotificationAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hidl.manager@1.0_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hidl:system/libhidl/transport android.hidl.manager@1.0",
- srcs: [
- ":android.hidl.manager@1.0_hal",
- ],
- out: [
- "android/hidl/manager/1.0/IServiceManager.h",
- "android/hidl/manager/1.0/IHwServiceManager.h",
- "android/hidl/manager/1.0/BnHwServiceManager.h",
- "android/hidl/manager/1.0/BpHwServiceManager.h",
- "android/hidl/manager/1.0/BsServiceManager.h",
- "android/hidl/manager/1.0/IServiceNotification.h",
- "android/hidl/manager/1.0/IHwServiceNotification.h",
- "android/hidl/manager/1.0/BnHwServiceNotification.h",
- "android/hidl/manager/1.0/BpHwServiceNotification.h",
- "android/hidl/manager/1.0/BsServiceNotification.h",
- ],
-}
-
-// android.hidl.manager@1.0 is exported from libhidltransport
diff --git a/transport/manager/1.0/Android.mk b/transport/manager/1.0/Android.mk
deleted file mode 100644
index 8b20827..0000000
--- a/transport/manager/1.0/Android.mk
+++ /dev/null
@@ -1,114 +0,0 @@
-# This file is autogenerated by hidl-gen. Do not edit manually.
-
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.manager-V1.0-java
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_JAVA_LIBRARIES := \
- android.hidl.base-V1.0-java \
-
-
-#
-# Build IServiceManager.hal
-#
-GEN := $(intermediates)/android/hidl/manager/V1_0/IServiceManager.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IServiceManager.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IServiceNotification.hal
-$(GEN): $(LOCAL_PATH)/IServiceNotification.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.manager@1.0::IServiceManager
-
-$(GEN): $(LOCAL_PATH)/IServiceManager.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IServiceNotification.hal
-#
-GEN := $(intermediates)/android/hidl/manager/V1_0/IServiceNotification.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IServiceNotification.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.manager@1.0::IServiceNotification
-
-$(GEN): $(LOCAL_PATH)/IServiceNotification.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_JAVA_LIBRARY)
-
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.manager-V1.0-java-static
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- android.hidl.base-V1.0-java-static \
-
-
-#
-# Build IServiceManager.hal
-#
-GEN := $(intermediates)/android/hidl/manager/V1_0/IServiceManager.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IServiceManager.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IServiceNotification.hal
-$(GEN): $(LOCAL_PATH)/IServiceNotification.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.manager@1.0::IServiceManager
-
-$(GEN): $(LOCAL_PATH)/IServiceManager.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IServiceNotification.hal
-#
-GEN := $(intermediates)/android/hidl/manager/V1_0/IServiceNotification.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IServiceNotification.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.manager@1.0::IServiceNotification
-
-$(GEN): $(LOCAL_PATH)/IServiceNotification.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/transport/manager/1.0/IServiceNotification.hal b/transport/manager/1.0/IServiceNotification.hal
index a6151e3..208f774 100644
--- a/transport/manager/1.0/IServiceNotification.hal
+++ b/transport/manager/1.0/IServiceNotification.hal
@@ -21,7 +21,7 @@
/**
* Must be called when a service is registered.
*
- * @param fqInstanceName Fully-qualified instance name (see IServiceManager)
+ * @param fqName Fully-qualified instance name (see IServiceManager)
* @param preexisting If true, this means the registration was
* pre-existing at the time this IServiceNotification
* object is itself registered. Otherwise, this means
diff --git a/transport/manager/1.1/Android.bp b/transport/manager/1.1/Android.bp
index 5a1bf00..cde68a7 100644
--- a/transport/manager/1.1/Android.bp
+++ b/transport/manager/1.1/Android.bp
@@ -1,38 +1,19 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
+// This file is autogenerated by hidl-gen -Landroidbp.
-filegroup {
- name: "android.hidl.manager@1.1_hal",
+hidl_interface {
+ name: "android.hidl.manager@1.1",
+ root: "android.hidl",
+ core_interface: true,
+ vndk: {
+ enabled: true,
+ },
srcs: [
"IServiceManager.hal",
],
+ interfaces: [
+ "android.hidl.base@1.0",
+ "android.hidl.manager@1.0",
+ ],
+ gen_java: true,
}
-genrule {
- name: "android.hidl.manager@1.1_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hidl:system/libhidl/transport android.hidl.manager@1.1",
- srcs: [
- ":android.hidl.manager@1.1_hal",
- ],
- out: [
- "android/hidl/manager/1.1/ServiceManagerAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hidl.manager@1.1_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hidl:system/libhidl/transport android.hidl.manager@1.1",
- srcs: [
- ":android.hidl.manager@1.1_hal",
- ],
- out: [
- "android/hidl/manager/1.1/IServiceManager.h",
- "android/hidl/manager/1.1/IHwServiceManager.h",
- "android/hidl/manager/1.1/BnHwServiceManager.h",
- "android/hidl/manager/1.1/BpHwServiceManager.h",
- "android/hidl/manager/1.1/BsServiceManager.h",
- ],
-}
-
-// android.hidl.manager@1.1 is exported from libhidltransport
diff --git a/transport/manager/1.1/Android.mk b/transport/manager/1.1/Android.mk
deleted file mode 100644
index 20c9504..0000000
--- a/transport/manager/1.1/Android.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-# This file is autogenerated by hidl-gen. Do not edit manually.
-
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.manager-V1.1-java
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_JAVA_LIBRARIES := \
- android.hidl.base-V1.0-java \
- android.hidl.manager-V1.0-java \
-
-
-#
-# Build IServiceManager.hal
-#
-GEN := $(intermediates)/android/hidl/manager/V1_1/IServiceManager.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IServiceManager.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.manager@1.1::IServiceManager
-
-$(GEN): $(LOCAL_PATH)/IServiceManager.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_JAVA_LIBRARY)
-
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.manager-V1.1-java-static
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- android.hidl.base-V1.0-java-static \
- android.hidl.manager-V1.0-java-static \
-
-
-#
-# Build IServiceManager.hal
-#
-GEN := $(intermediates)/android/hidl/manager/V1_1/IServiceManager.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IServiceManager.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.manager@1.1::IServiceManager
-
-$(GEN): $(LOCAL_PATH)/IServiceManager.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/transport/memory/1.0/Android.bp b/transport/memory/1.0/Android.bp
index b6044c2..eaa3037 100644
--- a/transport/memory/1.0/Android.bp
+++ b/transport/memory/1.0/Android.bp
@@ -1,70 +1,19 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
+// This file is autogenerated by hidl-gen -Landroidbp.
-filegroup {
- name: "android.hidl.memory@1.0_hal",
- srcs: [
- "IMapper.hal",
- "IMemory.hal",
- ],
-}
-
-genrule {
- name: "android.hidl.memory@1.0_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hidl:system/libhidl/transport android.hidl.memory@1.0",
- srcs: [
- ":android.hidl.memory@1.0_hal",
- ],
- out: [
- "android/hidl/memory/1.0/MapperAll.cpp",
- "android/hidl/memory/1.0/MemoryAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hidl.memory@1.0_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hidl:system/libhidl/transport android.hidl.memory@1.0",
- srcs: [
- ":android.hidl.memory@1.0_hal",
- ],
- out: [
- "android/hidl/memory/1.0/IMapper.h",
- "android/hidl/memory/1.0/IHwMapper.h",
- "android/hidl/memory/1.0/BnHwMapper.h",
- "android/hidl/memory/1.0/BpHwMapper.h",
- "android/hidl/memory/1.0/BsMapper.h",
- "android/hidl/memory/1.0/IMemory.h",
- "android/hidl/memory/1.0/IHwMemory.h",
- "android/hidl/memory/1.0/BnHwMemory.h",
- "android/hidl/memory/1.0/BpHwMemory.h",
- "android/hidl/memory/1.0/BsMemory.h",
- ],
-}
-
-cc_library {
+hidl_interface {
name: "android.hidl.memory@1.0",
- defaults: ["hidl-module-defaults"],
- generated_sources: ["android.hidl.memory@1.0_genc++"],
- generated_headers: ["android.hidl.memory@1.0_genc++_headers"],
- export_generated_headers: ["android.hidl.memory@1.0_genc++_headers"],
- vendor_available: true,
+ root: "android.hidl",
vndk: {
enabled: true,
support_system_process: true,
},
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
+ srcs: [
+ "IMapper.hal",
+ "IMemory.hal",
],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
+ interfaces: [
+ "android.hidl.base@1.0",
],
+ gen_java: false,
}
+
diff --git a/transport/memory/1.0/default/Android.bp b/transport/memory/1.0/default/Android.bp
index 470d3b8..d242ddf 100644
--- a/transport/memory/1.0/default/Android.bp
+++ b/transport/memory/1.0/default/Android.bp
@@ -21,7 +21,7 @@
},
compile_multilib: "both",
relative_install_path: "hw",
- cflags: libhidl_flags,
+ defaults: ["libhidl-defaults"],
srcs: [
"AshmemMapper.cpp",
"AshmemMemory.cpp",
@@ -29,7 +29,6 @@
],
shared_libs: [
"libcutils",
- "libhardware",
"libhwbinder",
"libbase",
"liblog",
diff --git a/transport/memory/block/1.0/Android.bp b/transport/memory/block/1.0/Android.bp
new file mode 100644
index 0000000..0bb8a27
--- /dev/null
+++ b/transport/memory/block/1.0/Android.bp
@@ -0,0 +1,16 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hidl.memory.block@1.0",
+ root: "android.hidl",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ ],
+ interfaces: [
+ "android.hidl.memory.token@1.0",
+ ],
+ gen_java: false,
+}
diff --git a/transport/memory/block/1.0/types.hal b/transport/memory/block/1.0/types.hal
new file mode 100644
index 0000000..e6a95ac
--- /dev/null
+++ b/transport/memory/block/1.0/types.hal
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package android.hidl.memory.block@1.0;
+
+import android.hidl.memory.token@1.0::IMemoryToken;
+
+struct MemoryBlock {
+ IMemoryToken token;
+ uint64_t size;
+ uint64_t offset;
+};
diff --git a/transport/memory/token/1.0/Android.bp b/transport/memory/token/1.0/Android.bp
new file mode 100644
index 0000000..e6797d4
--- /dev/null
+++ b/transport/memory/token/1.0/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hidl.memory.token@1.0",
+ root: "android.hidl",
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ srcs: [
+ "IMemoryToken.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/transport/memory/token/1.0/IMemoryToken.hal b/transport/memory/token/1.0/IMemoryToken.hal
new file mode 100644
index 0000000..6507cee
--- /dev/null
+++ b/transport/memory/token/1.0/IMemoryToken.hal
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package android.hidl.memory.token@1.0;
+
+/**
+ * Interface which composes shared memory
+ */
+interface IMemoryToken {
+ /**
+ * The returned instance of memory must always be a reference to the same memory.
+ * @return mem Memory referenced by this token.
+ */
+ get() generates (memory mem);
+};
diff --git a/transport/token/1.0/Android.bp b/transport/token/1.0/Android.bp
index 957d1f9..c0988cb 100644
--- a/transport/token/1.0/Android.bp
+++ b/transport/token/1.0/Android.bp
@@ -1,62 +1,17 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
+// This file is autogenerated by hidl-gen -Landroidbp.
-filegroup {
- name: "android.hidl.token@1.0_hal",
- srcs: [
- "ITokenManager.hal",
- ],
-}
-
-genrule {
- name: "android.hidl.token@1.0_genc++",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hidl:system/libhidl/transport android.hidl.token@1.0",
- srcs: [
- ":android.hidl.token@1.0_hal",
- ],
- out: [
- "android/hidl/token/1.0/TokenManagerAll.cpp",
- ],
-}
-
-genrule {
- name: "android.hidl.token@1.0_genc++_headers",
- tools: ["hidl-gen"],
- cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hidl:system/libhidl/transport android.hidl.token@1.0",
- srcs: [
- ":android.hidl.token@1.0_hal",
- ],
- out: [
- "android/hidl/token/1.0/ITokenManager.h",
- "android/hidl/token/1.0/IHwTokenManager.h",
- "android/hidl/token/1.0/BnHwTokenManager.h",
- "android/hidl/token/1.0/BpHwTokenManager.h",
- "android/hidl/token/1.0/BsTokenManager.h",
- ],
-}
-
-cc_library {
+hidl_interface {
name: "android.hidl.token@1.0",
- defaults: ["hidl-module-defaults"],
- generated_sources: ["android.hidl.token@1.0_genc++"],
- generated_headers: ["android.hidl.token@1.0_genc++_headers"],
- export_generated_headers: ["android.hidl.token@1.0_genc++_headers"],
- vendor_available: true,
+ root: "android.hidl",
vndk: {
enabled: true,
},
- shared_libs: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- "libcutils",
+ srcs: [
+ "ITokenManager.hal",
],
- export_shared_lib_headers: [
- "libhidlbase",
- "libhidltransport",
- "libhwbinder",
- "libutils",
+ interfaces: [
+ "android.hidl.base@1.0",
],
+ gen_java: true,
}
+
diff --git a/transport/token/1.0/Android.mk b/transport/token/1.0/Android.mk
deleted file mode 100644
index ea86d57..0000000
--- a/transport/token/1.0/Android.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-# This file is autogenerated by hidl-gen. Do not edit manually.
-
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.token-V1.0-java
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_JAVA_LIBRARIES := \
- android.hidl.base-V1.0-java \
-
-
-#
-# Build ITokenManager.hal
-#
-GEN := $(intermediates)/android/hidl/token/V1_0/ITokenManager.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ITokenManager.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.token@1.0::ITokenManager
-
-$(GEN): $(LOCAL_PATH)/ITokenManager.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_JAVA_LIBRARY)
-
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hidl.token-V1.0-java-static
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- android.hidl.base-V1.0-java-static \
-
-
-#
-# Build ITokenManager.hal
-#
-GEN := $(intermediates)/android/hidl/token/V1_0/ITokenManager.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ITokenManager.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
- $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
- -Ljava \
- -randroid.hidl:system/libhidl/transport \
- android.hidl.token@1.0::ITokenManager
-
-$(GEN): $(LOCAL_PATH)/ITokenManager.hal
- $(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
index 101f3b4..fcb1613 100644
--- a/transport/token/1.0/utils/Android.bp
+++ b/transport/token/1.0/utils/Android.bp
@@ -14,6 +14,7 @@
cc_library {
name: "android.hidl.token@1.0-utils",
+ defaults: ["libhidl-defaults"],
vendor_available: true,
vndk: {
enabled: true,
@@ -39,7 +40,5 @@
export_include_dirs: [
"include"
],
-
- clang: true,
}
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
index 8c3e742..984555e 100644
--- a/transport/token/1.0/utils/include/hidl/HybridInterface.h
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -125,13 +125,13 @@
HalInterface* getBaseInterface() { return mBase.get(); }
virtual status_t linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0);
virtual status_t unlinkToDeath(
const wp<IBinder::DeathRecipient>& recipient,
- void* cookie = NULL,
+ void* cookie = nullptr,
uint32_t flags = 0,
- wp<IBinder::DeathRecipient>* outRecipient = NULL);
+ wp<IBinder::DeathRecipient>* outRecipient = nullptr);
protected:
sp<HalInterface> mBase;
@@ -215,11 +215,11 @@
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
- if (obj != NULL) { \
+ if (obj != nullptr) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
- if (intr == NULL) { \
+ if (intr == nullptr) { \
intr = new Hp##INTERFACE(obj); \
} \
} \
@@ -262,8 +262,8 @@
linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
- LOG_ALWAYS_FATAL_IF(recipient == NULL,
- "linkToDeath(): recipient must be non-NULL");
+ LOG_ALWAYS_FATAL_IF(recipient == nullptr,
+ "linkToDeath(): recipient must be non-nullptr");
{
std::lock_guard<std::mutex> lock(mObituariesLock);
mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
diff --git a/update-makefiles.sh b/update-makefiles.sh
index df3d4b1..fd0a23c 100755
--- a/update-makefiles.sh
+++ b/update-makefiles.sh
@@ -11,6 +11,5 @@
for package in "${packages[@]}"; do
echo "Updating $package."
- hidl-gen -Lmakefile -r android.hidl:system/libhidl/transport $package
hidl-gen -Landroidbp -r android.hidl:system/libhidl/transport $package
done
diff --git a/vintfdata/Android.mk b/vintfdata/Android.mk
new file mode 100644
index 0000000..bc7a55a
--- /dev/null
+++ b/vintfdata/Android.mk
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2018 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+FRAMEWORK_MANIFEST_INPUT_FILES := $(LOCAL_PATH)/manifest.xml
+ifdef DEVICE_FRAMEWORK_MANIFEST_FILE
+ FRAMEWORK_MANIFEST_INPUT_FILES += $(DEVICE_FRAMEWORK_MANIFEST_FILE)
+endif
+
+# VNDK Version in device compatibility matrix and framework manifest
+ifeq ($(BOARD_VNDK_VERSION),current)
+VINTF_VNDK_VERSION := $(PLATFORM_VNDK_VERSION)
+else
+VINTF_VNDK_VERSION := $(BOARD_VNDK_VERSION)
+endif
+
+# Device Compatibility Matrix
+ifdef DEVICE_MATRIX_FILE
+DEVICE_MATRIX_INPUT_FILE := $(DEVICE_MATRIX_FILE)
+else
+DEVICE_MATRIX_INPUT_FILE := $(LOCAL_PATH)/device_compatibility_matrix.default.xml
+endif
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := device_compatibility_matrix.xml
+LOCAL_MODULE_STEM := compatibility_matrix.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/vintf
+
+GEN := $(local-generated-sources-dir)/compatibility_matrix.xml
+
+$(GEN): PRIVATE_VINTF_VNDK_VERSION := $(VINTF_VNDK_VERSION)
+$(GEN): $(DEVICE_MATRIX_INPUT_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+ REQUIRED_VNDK_VERSION=$(PRIVATE_VINTF_VNDK_VERSION) \
+ BOARD_SYSTEMSDK_VERSIONS="$(BOARD_SYSTEMSDK_VERSIONS)" \
+ $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $< -o $@
+
+LOCAL_PREBUILT_MODULE_FILE := $(GEN)
+include $(BUILD_PREBUILT)
+BUILT_VENDOR_MATRIX := $(LOCAL_BUILT_MODULE)
+
+# Framework Manifest
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_manifest.xml
+LOCAL_MODULE_STEM := manifest.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
+
+GEN := $(local-generated-sources-dir)/manifest.xml
+
+$(GEN): PRIVATE_FLAGS :=
+
+ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
+ifdef BUILT_VENDOR_MATRIX
+$(GEN): $(BUILT_VENDOR_MATRIX)
+$(GEN): PRIVATE_FLAGS += -c "$(BUILT_VENDOR_MATRIX)"
+endif
+endif
+
+$(GEN): PRIVATE_VINTF_VNDK_VERSION := $(VINTF_VNDK_VERSION)
+$(GEN): PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES := $(FRAMEWORK_MANIFEST_INPUT_FILES)
+$(GEN): $(FRAMEWORK_MANIFEST_INPUT_FILES) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+ PROVIDED_VNDK_VERSIONS="$(PRIVATE_VINTF_VNDK_VERSION) $(PRODUCT_EXTRA_VNDK_VERSIONS)" \
+ PLATFORM_SYSTEMSDK_VERSIONS="$(PLATFORM_SYSTEMSDK_VERSIONS)" \
+ $(HOST_OUT_EXECUTABLES)/assemble_vintf \
+ -i $(call normalize-path-list,$(PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES)) \
+ -o $@ $(PRIVATE_FLAGS)
+
+LOCAL_PREBUILT_MODULE_FILE := $(GEN)
+include $(BUILD_PREBUILT)
+BUILT_SYSTEM_MANIFEST := $(LOCAL_BUILT_MODULE)
+
+VINTF_VNDK_VERSION :=
+FRAMEWORK_MANIFEST_INPUT_FILES :=
+DEVICE_MATRIX_INPUT_FILE :=
diff --git a/vintfdata/device_compatibility_matrix.default.xml b/vintfdata/device_compatibility_matrix.default.xml
new file mode 100644
index 0000000..eaa513e
--- /dev/null
+++ b/vintfdata/device_compatibility_matrix.default.xml
@@ -0,0 +1,10 @@
+<compatibility-matrix version="1.0" type="device">
+ <hal format="hidl" optional="false">
+ <name>android.hidl.manager</name>
+ <version>1.0</version>
+ <interface>
+ <name>IServiceManager</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</compatibility-matrix>
diff --git a/manifest.xml b/vintfdata/manifest.xml
similarity index 90%
rename from manifest.xml
rename to vintfdata/manifest.xml
index f34bfb1..51d68eb 100644
--- a/manifest.xml
+++ b/vintfdata/manifest.xml
@@ -65,7 +65,7 @@
<hal format="hidl">
<name>android.system.net.netd</name>
<transport>hwbinder</transport>
- <version>1.0</version>
+ <version>1.1</version>
<interface>
<name>INetd</name>
<instance>default</instance>
@@ -89,6 +89,16 @@
<instance>vr</instance>
</interface>
</hal>
+ <hal>
+ <name>android.hardware.health</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IHealth</name>
+ <!-- The backup instance provided by healthd. -->
+ <instance>backup</instance>
+ </interface>
+ </hal>
<hal format="native">
<name>netutils-wrapper</name>
<!--
diff --git a/vintfdata/manifest_healthd_exclude.xml b/vintfdata/manifest_healthd_exclude.xml
new file mode 100644
index 0000000..b4060f0
--- /dev/null
+++ b/vintfdata/manifest_healthd_exclude.xml
@@ -0,0 +1,15 @@
+<!--
+ Include this file to DEVICE_FRAMEWORK_MANIFEST_FILE to disable
+ having an healthd on the device which is not needed if you have
+ an alternative implementation like the following:
+ (1) Device has android.hardware.health@2.0-service.override
+ (2) Device has android.hardware.health@2.0-service.<device>, which
+ contains the following:
+ overrides: ["healthd"]
+-->
+<manifest version="1.0" type="framework">
+ <hal format="hidl" override="true">
+ <name>android.hardware.health</name>
+ <transport>hwbinder</transport>
+ </hal>
+</manifest>