Merge "Add sleep in unsafe path."
diff --git a/Android.bp b/Android.bp
index 4bd5eb3..819732d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -26,12 +26,17 @@
name: "libhidl",
required: [
"libhidlbase",
- "libhidltransport",
],
}
+cc_library_headers {
+ name: "libhidl_gtest_helpers",
+ export_include_dirs: ["gtest_helpers"],
+}
+
cc_test {
name: "libhidl_test",
+ host_supported: true,
defaults: ["libhidl-defaults"],
gtest: false,
srcs: ["test_main.cpp"],
@@ -41,8 +46,6 @@
"android.hidl.memory@1.0",
"libbase",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
"libcutils",
@@ -54,3 +57,58 @@
"-g",
],
}
+
+cc_defaults {
+ name: "libhidlbase-combined-impl",
+
+ defaults: [
+ "libhwbinder-impl-shared-libs",
+ "libhidlbase-impl-shared-libs",
+ "libhidltransport-impl-shared-libs",
+ ],
+
+ whole_static_libs: [
+ "libhidlbase-impl-internal",
+ "libhidltransport-impl-internal",
+ ],
+}
+
+cc_library {
+ name: "libhidlbase",
+ defaults: ["libhidlbase-combined-impl"],
+ host_supported: true,
+ recovery_available: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ whole_static_libs: [
+ "libhwbinder-impl-internal",
+ ],
+}
+
+// Only libhwbinder_benchmark needs to have pgo enabled. When all places
+// support having PGO selectively enabled, all places can use libhwbinder.
+//
+// http://b/77320844
+cc_library {
+ name: "libhidlbase_pgo",
+ defaults: [
+ "libhidlbase-combined-impl",
+ "hwbinder_benchmark_pgo",
+ ],
+ whole_static_libs: [
+ "libhwbinder_pgo-impl-internal",
+ ],
+
+ visibility: ["//system/libhwbinder:__subpackages__"],
+}
+
+// WARNING: deprecated
+// This library is no longer required, and dependencies should be taken
+// on libhidlbase instead.
+cc_library {
+ name: "libhidltransport",
+ vendor_available: true,
+}
diff --git a/adapter/Android.bp b/adapter/Android.bp
index eb322bc..ae801bc 100644
--- a/adapter/Android.bp
+++ b/adapter/Android.bp
@@ -23,14 +23,11 @@
shared_libs: [
"libbase",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
export_shared_lib_headers: [
"libhidlbase",
- "libhidltransport",
"libutils",
],
}
diff --git a/base/Android.bp b/base/Android.bp
index 359ac91..ca4e259 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -12,15 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library {
- name: "libhidlbase",
- recovery_available: true,
- vendor_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- defaults: ["libhidl-defaults"],
+cc_defaults {
+ name: "libhidlbase-impl-shared-libs",
shared_libs: [
"libbase",
"libcutils",
@@ -31,6 +24,17 @@
"libutils",
"libcutils", // for native_handle.h
],
+}
+
+cc_library {
+ name: "libhidlbase-impl-internal",
+ host_supported: true,
+ recovery_available: true,
+ vendor_available: true,
+ defaults: [
+ "libhidlbase-impl-shared-libs",
+ "libhidl-defaults"
+ ],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
@@ -50,4 +54,6 @@
cflags: ["-DLIBHIDL_TARGET_DEBUGGABLE"],
},
},
+
+ visibility: ["//system/libhidl:__subpackages__"],
}
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index 440b30f..956effd 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -21,7 +21,6 @@
#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>
@@ -56,7 +55,7 @@
// "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", "");
+ vndkVersion = base::GetProperty("ro.vndk.version", "");
if (vndkVersion != "" && vndkVersion != "current") {
vndkVersion = "-" + vndkVersion;
} else {
@@ -76,44 +75,44 @@
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);
+ []() {
+ bool enableCoverage = base::GetBoolProperty(kSysPropHalCoverage, false);
+ if (enableCoverage) {
+ __sanitizer_cov_dump();
+ }
+ },
+ 0);
}
- if (property_get_bool("ro.vts.coverage", false)) {
+ if (base::GetBoolProperty("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;
+ []() {
+ const bool enableCoverage = base::GetBoolProperty(kSysPropHalCoverage, false);
+ if (enableCoverage) {
+ dl_iterate_phdr(
+ [](struct dl_phdr_info* info, size_t /* size */, void* /* data */) {
+ if (strlen(info->dlpi_name) == 0) return 0;
- void* handle = dlopen(info->dlpi_name, RTLD_LAZY);
- if (handle == nullptr) {
- LOG(INFO) << "coverage dlopen failed: " << dlerror();
- return 0;
- }
- void (*flush)() = (void (*)())dlsym(handle, "__gcov_flush");
- if (flush == nullptr) {
- return 0;
- }
- flush();
- return 0;
- },
- nullptr /* data */);
- }
- },
- 0 /* priority */);
+ 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
}
@@ -121,7 +120,7 @@
HidlInstrumentor::~HidlInstrumentor() {}
void HidlInstrumentor::configureInstrumentation(bool log) {
- mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
+ mEnableInstrumentation = base::GetBoolProperty("hal.instrumentation.enable", false);
if (mEnableInstrumentation) {
if (log) {
LOG(INFO) << "Enable instrumentation.";
@@ -140,8 +139,8 @@
std::vector<InstrumentationCallback> *instrumentationCallbacks) {
#ifdef LIBHIDL_TARGET_DEBUGGABLE
std::vector<std::string> instrumentationLibPaths;
- char instrumentationLibPath[PROPERTY_VALUE_MAX];
- if (property_get(kSysPropInstrumentationPath, instrumentationLibPath, "") > 0) {
+ const std::string instrumentationLibPath = base::GetProperty(kSysPropInstrumentationPath, "");
+ if (instrumentationLibPath.size() > 0) {
instrumentationLibPaths.push_back(instrumentationLibPath);
} else {
static std::string halLibPathVndkSp = android::base::StringPrintf(
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index c15d326..af805b9 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -35,10 +35,8 @@
}
} // namespace details
-hidl_handle::hidl_handle() {
- memset(this, 0, sizeof(*this));
- // mHandle = nullptr;
- // mOwnsHandle = false;
+hidl_handle::hidl_handle() : mHandle(nullptr), mOwnsHandle(false) {
+ memset(mPad, 0, sizeof(mPad));
}
hidl_handle::~hidl_handle() {
@@ -57,7 +55,7 @@
}
// move constructor.
-hidl_handle::hidl_handle(hidl_handle&& other) noexcept {
+hidl_handle::hidl_handle(hidl_handle&& other) noexcept : hidl_handle() {
mOwnsHandle = false;
*this = std::move(other);
}
@@ -138,11 +136,8 @@
static const char *const kEmptyString = "";
-hidl_string::hidl_string() {
- memset(this, 0, sizeof(*this));
- // mSize is zero
- // mOwnsBuffer is false
- mBuffer = kEmptyString;
+hidl_string::hidl_string() : mBuffer(kEmptyString), mSize(0), mOwnsBuffer(false) {
+ memset(mPad, 0, sizeof(mPad));
}
hidl_string::~hidl_string() {
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index c0ae1c0..1b91c26 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -20,18 +20,24 @@
#include <algorithm>
#include <array>
#include <iterator>
-#include <cutils/native_handle.h>
#include <hidl/HidlInternal.h>
-#include <hidl/Status.h>
#include <map>
#include <sstream>
#include <stddef.h>
#include <tuple>
#include <type_traits>
+#include <vector>
+
+// no requirements on types not used in scatter/gather
+// no requirements on other libraries
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#include <cutils/native_handle.h>
+#include <hidl/Status.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
-#include <vector>
+#pragma clang diagnostic pop
namespace android {
@@ -123,8 +129,9 @@
private:
void freeHandle();
- details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
- bool mOwnsHandle __attribute ((aligned(8)));
+ details::hidl_pointer<const native_handle_t> mHandle;
+ bool mOwnsHandle;
+ uint8_t mPad[7];
};
struct hidl_string {
@@ -174,6 +181,7 @@
details::hidl_pointer<const char> mBuffer;
uint32_t mSize; // NOT including the terminating '\0'.
bool mOwnsBuffer; // if true then mBuffer is a mutable char *
+ uint8_t mPad[3];
// copy from data with size. Assume that my memory is freed
// (through clear(), for example)
@@ -294,9 +302,9 @@
static const size_t kOffsetOfName;
private:
- hidl_handle mHandle __attribute__ ((aligned(8)));
- uint64_t mSize __attribute__ ((aligned(8)));
- hidl_string mName __attribute__ ((aligned(8)));
+ hidl_handle mHandle;
+ uint64_t mSize;
+ hidl_string mName;
};
// HidlMemory is a wrapper class to support sp<> for hidl_memory. It also
@@ -328,15 +336,10 @@
struct hidl_vec {
using value_type = T;
- hidl_vec() {
+ hidl_vec() : mBuffer(nullptr), mSize(0), mOwnsBuffer(false) {
static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
- memset(this, 0, sizeof(*this));
- // mSize is 0
- // mBuffer is nullptr
-
- // this is for consistency with the original implementation
- mOwnsBuffer = true;
+ memset(mPad, 0, sizeof(mPad));
}
// Note, does not initialize primitive types.
@@ -350,19 +353,7 @@
*this = std::move(other);
}
- hidl_vec(const std::initializer_list<T> list) : hidl_vec() {
- if (list.size() > UINT32_MAX) {
- details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
- }
- mSize = static_cast<uint32_t>(list.size());
- mBuffer = new T[mSize]();
- mOwnsBuffer = true;
-
- size_t idx = 0;
- for (auto it = list.begin(); it != list.end(); ++it) {
- mBuffer[idx++] = *it;
- }
- }
+ hidl_vec(const std::initializer_list<T> list) : hidl_vec() { *this = list; }
hidl_vec(const std::vector<T> &other) : hidl_vec() {
*this = other;
@@ -467,7 +458,7 @@
delete[] mBuffer;
}
mSize = static_cast<uint32_t>(list.size());
- mBuffer = new T[mSize];
+ mBuffer = new T[mSize]();
mOwnsBuffer = true;
size_t idx = 0;
@@ -593,6 +584,7 @@
details::hidl_pointer<T> mBuffer;
uint32_t mSize;
bool mOwnsBuffer;
+ uint8_t mPad[3];
// copy from an array-like object, assuming my resources are freed.
template <typename Array>
diff --git a/gtest_helpers/hidl/GtestPrinter.h b/gtest_helpers/hidl/GtestPrinter.h
new file mode 100644
index 0000000..c9f5dd3
--- /dev/null
+++ b/gtest_helpers/hidl/GtestPrinter.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+
+static inline std::string PrintInstanceNameToString(
+ const testing::TestParamInfo<std::string>& info) {
+ // test names need to be unique -> index prefix
+ std::string name = std::to_string(info.index) + "/" + info.param;
+
+ for (size_t i = 0; i < name.size(); i++) {
+ // gtest test names must only contain alphanumeric characters
+ if (!std::isalnum(name[i])) name[i] = '_';
+ }
+
+ return name;
+}
+
+} // namespace hardware
+} // namespace android
diff --git a/libhidlmemory/Android.bp b/libhidlmemory/Android.bp
index 2135ef3..2f97d5d 100644
--- a/libhidlmemory/Android.bp
+++ b/libhidlmemory/Android.bp
@@ -26,7 +26,6 @@
"libutils",
"libcutils",
"libhidlbase",
- "libhidltransport",
"android.hidl.memory@1.0",
"android.hidl.memory.token@1.0",
],
diff --git a/test_main.cpp b/test_main.cpp
index 7b6781a..fc71231 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -16,11 +16,16 @@
#define LOG_TAG "LibHidlTest"
+#pragma clang diagnostic push
+#pragma clang diagnostic fatal "-Wpadded"
+#include <hidl/HidlInternal.h>
+#include <hidl/HidlSupport.h>
+#pragma clang diagnostic pop
+
#include <android-base/logging.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <hidl/TaskRunner.h>
@@ -28,6 +33,12 @@
#include <fstream>
#include <vector>
+#ifdef __ANDROID__
+static bool kAndroid = true;
+#else
+static bool kAndroid = false;
+#endif
+
#define EXPECT_ARRAYEQ(__a1__, __a2__, __size__) EXPECT_TRUE(isArrayEqual(__a1__, __a2__, __size__))
#define EXPECT_2DARRAYEQ(__a1__, __a2__, __size1__, __size2__) \
EXPECT_TRUE(is2dArrayEqual(__a1__, __a2__, __size1__, __size2__))
@@ -558,6 +569,10 @@
}
TEST_F(LibHidlTest, PreloadTest) {
+ // HIDL doesn't have support to load passthrough implementations on host, but we
+ // could do this by loading implementations from the output directory
+ if (!kAndroid) GTEST_SKIP();
+
using ::android::hardware::preloadPassthroughService;
using ::android::hidl::memory::V1_0::IMemory;
@@ -570,6 +585,51 @@
EXPECT_TRUE(isLibraryOpen(kLib));
}
+template <typename T, size_t start, size_t end>
+static void assertZeroInRange(const T* t) {
+ static_assert(start < sizeof(T));
+ static_assert(end <= sizeof(T));
+
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(t);
+
+ for (size_t i = start; i < end; i++) {
+ EXPECT_EQ(0, ptr[i]);
+ }
+}
+
+template <typename T, size_t start, size_t end>
+static void uninitTest() {
+ uint8_t buf[sizeof(T)];
+ memset(buf, 0xFF, sizeof(T));
+
+ T* type = new (buf) T;
+ assertZeroInRange<T, start, end>(type);
+ type->~T();
+}
+
+TEST_F(LibHidlTest, HidlVecUninit) {
+ using ::android::hardware::hidl_vec;
+ struct SomeType {};
+ static_assert(sizeof(hidl_vec<SomeType>) == 16);
+
+ // padding after mOwnsBuffer
+ uninitTest<hidl_vec<SomeType>, 13, 16>();
+}
+TEST_F(LibHidlTest, HidlHandleUninit) {
+ using ::android::hardware::hidl_handle;
+ static_assert(sizeof(hidl_handle) == 16);
+
+ // padding after mOwnsHandle
+ uninitTest<hidl_handle, 9, 16>();
+}
+TEST_F(LibHidlTest, HidlStringUninit) {
+ using ::android::hardware::hidl_string;
+ static_assert(sizeof(hidl_string) == 16);
+
+ // padding after mOwnsBuffer
+ uninitTest<hidl_string, 13, 16>();
+}
+
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/transport/Android.bp b/transport/Android.bp
index 6518177..324dbde 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -16,30 +16,52 @@
name: "android.hidl",
}
-cc_library {
- name: "libhidltransport",
- recovery_available: true,
- vendor_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- defaults: [
- "libhidl-defaults",
- "hidl-module-defaults",
- ],
+cc_defaults {
+ name: "libhidltransport-impl-shared-libs",
shared_libs: [
"libbase",
"liblog",
"libutils",
- "libhidlbase",
- "libhwbinder",
"libcutils",
- "libvndksupport",
],
export_shared_lib_headers: [
"libutils",
- "libhidlbase",
+ ],
+ static_libs: [
+ "libhwbinder-impl-internal",
+ ],
+
+ target: {
+ android: {
+ shared_libs: [
+ "libvndksupport",
+ ],
+ },
+ recovery: {
+ exclude_shared_libs: [
+ "libvndksupport",
+ ],
+ },
+ },
+}
+
+cc_library_static {
+ name: "libhidltransport-impl-internal",
+ host_supported: true,
+ vendor_available: true,
+ recovery_available: true,
+
+ defaults: [
+ "hidl-module-defaults",
+ "libhidl-defaults",
+ "libhidltransport-impl-shared-libs",
+ ],
+
+ static_libs: [
+ "libhidlbase-impl-internal",
+ ],
+ export_static_lib_headers: [
+ "libhidlbase-impl-internal",
],
export_include_dirs: ["include"],
@@ -82,9 +104,5 @@
},
},
- target: {
- recovery: {
- exclude_shared_libs: ["libvndksupport"],
- },
- },
+ visibility: ["//system/libhidl:__subpackages__"],
}
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
index b433b70..e645cd0 100644
--- a/transport/HidlTransportSupport.cpp
+++ b/transport/HidlTransportSupport.cpp
@@ -13,13 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <hidl/HidlBinderSupport.h>
#include <hidl/HidlTransportSupport.h>
-#include <hidl/Static.h>
+
+#include <hidl/HidlBinderSupport.h>
+#include "InternalStatic.h"
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <linux/sched.h>
+
namespace android {
namespace hardware {
@@ -92,6 +95,10 @@
return true;
}
+SchedPrio getMinSchedulerPolicy(const sp<IBase>& service) {
+ return details::gServicePrioMap->get(service, {SCHED_NORMAL, 0});
+}
+
bool setRequestingSid(const sp<IBase>& service, bool requesting) {
if (service->isRemote()) {
LOG(ERROR) << "Can't set requesting sid on remote service.";
@@ -108,6 +115,10 @@
return true;
}
+bool getRequestingSid(const sp<IBase>& service) {
+ return details::gServiceSidMap->get(service.get(), false);
+}
+
bool interfacesEqual(const sp<IBase>& left, const sp<IBase>& right) {
if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
return left == right;
diff --git a/transport/InternalStatic.h b/transport/InternalStatic.h
index 1dfaae4..666b2b6 100644
--- a/transport/InternalStatic.h
+++ b/transport/InternalStatic.h
@@ -20,19 +20,26 @@
#ifndef ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
#define ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
+#include <hidl/HidlTransportSupport.h> // for SchedPrio
#include <hidl/Static.h>
namespace android {
namespace hardware {
namespace details {
-// TODO(b/69122224): remove this
+// TODO(b/69122224): remove this once no prebuilts reference it
// deprecated; use getBnConstructorMap instead.
extern DoNotDestruct<BnConstructorMap> gBnConstructorMap;
-// TODO(b/69122224): remove this
+// TODO(b/69122224): remove this once no prebuilts reference it
// deprecated; use getBsConstructorMap instead.
extern DoNotDestruct<BsConstructorMap> gBsConstructorMap;
+// TODO(b/69122224): remove this once no prebuilts reference it
+extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio>>
+ gServicePrioMap;
+// TODO(b/69122224): remove this once no prebuilts reference it
+extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool>> gServiceSidMap;
+
} // namespace details
} // namespace hardware
} // namespace android
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 884b056..2442590 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -16,7 +16,10 @@
#define LOG_TAG "HidlServiceManagement"
+#ifdef __ANDROID__
#include <android/dlext.h>
+#endif // __ANDROID__
+
#include <condition_variable>
#include <dlfcn.h>
#include <dirent.h>
@@ -43,7 +46,7 @@
#include <android-base/strings.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/Parcel.h>
-#if !defined(__ANDROID_RECOVERY__)
+#if !defined(__ANDROID_RECOVERY__) && defined(__ANDROID__)
#include <vndksupport/linker.h>
#endif
@@ -55,8 +58,6 @@
#define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
-using android::base::WaitForProperty;
-
using ::android::hidl::base::V1_0::IBase;
using IServiceManager1_0 = android::hidl::manager::V1_0::IServiceManager;
using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager;
@@ -66,8 +67,6 @@
namespace android {
namespace hardware {
-static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
-
#if defined(__ANDROID_RECOVERY__)
static constexpr bool kIsRecovery = true;
#else
@@ -75,11 +74,18 @@
#endif
static void waitForHwServiceManager() {
+ // TODO(b/31559095): need bionic host so that we can use 'prop_info' returned
+ // from WaitForProperty
+#ifdef __ANDROID__
+ static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
+
using std::literals::chrono_literals::operator""s;
+ using android::base::WaitForProperty;
while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
}
+#endif // __ANDROID__
}
static std::string binaryName() {
@@ -395,7 +401,7 @@
if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
handle = dlopen(fullPath.c_str(), dlMode);
} else {
-#if !defined(__ANDROID_RECOVERY__)
+#if !defined(__ANDROID_RECOVERY__) && defined(__ANDROID__)
handle = android_load_sphal_library(fullPath.c_str(), dlMode);
#endif
}
@@ -559,6 +565,18 @@
return manager;
}
+std::vector<std::string> getAllHalInstanceNames(const std::string& descriptor) {
+ std::vector<std::string> ret;
+ auto sm = defaultServiceManager1_2();
+ sm->listManifestByInterface(descriptor, [&](const auto& instances) {
+ ret.reserve(instances.size());
+ for (const auto& i : instances) {
+ ret.push_back(i);
+ }
+ });
+ return ret;
+}
+
namespace details {
void preloadPassthroughService(const std::string &descriptor) {
diff --git a/transport/allocator/1.0/default/Android.bp b/transport/allocator/1.0/default/Android.bp
index 1fdfb26..1116f1d 100644
--- a/transport/allocator/1.0/default/Android.bp
+++ b/transport/allocator/1.0/default/Android.bp
@@ -26,8 +26,6 @@
shared_libs: [
"android.hidl.allocator@1.0",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"libbase",
"liblog",
"libutils",
diff --git a/transport/allocator/1.0/utils/Android.bp b/transport/allocator/1.0/utils/Android.bp
index 9f70963..b324ef1 100644
--- a/transport/allocator/1.0/utils/Android.bp
+++ b/transport/allocator/1.0/utils/Android.bp
@@ -24,7 +24,6 @@
"libbinder",
"libcutils",
"libhidlbase",
- "libhidltransport",
"android.hidl.memory@1.0"
],
export_include_dirs: ["include"],
diff --git a/transport/base/1.0/vts/functional/Android.bp b/transport/base/1.0/vts/functional/Android.bp
index fb9af33..38b03f7 100644
--- a/transport/base/1.0/vts/functional/Android.bp
+++ b/transport/base/1.0/vts/functional/Android.bp
@@ -24,8 +24,6 @@
shared_libs: [
"libbase",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
"libprotobuf-cpp-lite",
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index a132bfa..454a4e5 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -84,6 +84,13 @@
bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
int policy, int priority);
+struct SchedPrio {
+ int sched_policy;
+ int prio;
+};
+
+SchedPrio getMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service);
+
/**
* Sets whether or not this object should request security contexts to be populatd for incoming
* calls (e.g. with getCallingSid).
@@ -97,6 +104,12 @@
bool setRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service, bool requesting);
/**
+ * Says whether or not this service is requesting a SID. If this was set after the service was
+ * sent to another process, then it will not take effect.
+ */
+bool getRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service);
+
+/**
* Returns whether two interfaces represent the same interface. References to interfaces in the same
* process will always be equivalent. However, in order to compare a service that is a proxy to a
* different process, its underlying structure may have to be checked.
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index a962034..4573a25 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -18,6 +18,7 @@
#define ANDROID_HARDWARE_ISERVICE_MANAGER_H
#include <string>
+#include <vector>
#include <android/hidl/base/1.0/IBase.h>
#include <utils/StrongPointer.h>
@@ -71,6 +72,14 @@
sp<::android::hidl::manager::V1_1::IServiceManager> getPassthroughServiceManager1_1();
/**
+ * Given a descriptor (e.g. from IFoo::descriptor), return a list of all instance names
+ * on a device (e.g. the VINTF manifest). These HALs may not be currently running, but
+ * the expectation is that if they aren't running, they should start as lazy HALs.
+ * So, getService should return for each of these instance names.
+ */
+std::vector<std::string> getAllHalInstanceNames(const std::string& descriptor);
+
+/**
* Given a service that is in passthrough mode, this function will go ahead and load the
* required passthrough module library (but not call HIDL_FETCH_I* functions to instantiate it).
*
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index be74bae..3f6203c 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -32,17 +32,6 @@
namespace hardware {
namespace details {
-struct SchedPrio {
- int sched_policy;
- int prio;
-};
-
-// TODO(b/69122224): remove this
-extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio>>
- gServicePrioMap;
-// TODO(b/69122224): remove this
-extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool>> gServiceSidMap;
-
// TODO(b/69122224): remove this
// For HidlBinderSupport and autogenerated code
extern DoNotDestruct<ConcurrentMap<const ::android::hidl::base::V1_0::IBase*,
diff --git a/transport/memory/1.0/default/Android.bp b/transport/memory/1.0/default/Android.bp
index d242ddf..f56ee95 100644
--- a/transport/memory/1.0/default/Android.bp
+++ b/transport/memory/1.0/default/Android.bp
@@ -29,12 +29,10 @@
],
shared_libs: [
"libcutils",
- "libhwbinder",
"libbase",
"liblog",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hidl.memory@1.0",
],
}
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
index 5a8d51c..8e23c62 100644
--- a/transport/token/1.0/utils/Android.bp
+++ b/transport/token/1.0/utils/Android.bp
@@ -30,10 +30,10 @@
],
shared_libs: [
- "libutils",
- "liblog",
- "libhidlbase",
"android.hidl.token@1.0",
+ "libhidlbase",
+ "liblog",
+ "libutils",
],
export_header_lib_headers: [
diff --git a/transport/token/1.0/utils/HybridInterface.cpp b/transport/token/1.0/utils/HybridInterface.cpp
index 106ad4e..675db8f 100644
--- a/transport/token/1.0/utils/HybridInterface.cpp
+++ b/transport/token/1.0/utils/HybridInterface.cpp
@@ -117,5 +117,4 @@
return static_cast<bool>(transaction);
}
-}; // namespace android
-
+} // namespace android
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
index 595c2e3..d00a0a1 100644
--- a/transport/token/1.0/utils/include/hidl/HybridInterface.h
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -23,6 +23,9 @@
#include <binder/Parcel.h>
#include <hidl/HidlSupport.h>
+#include <cinttypes>
+#include <variant>
+
/**
* Hybrid Interfaces
* =================
@@ -47,50 +50,130 @@
*
* To demonstrate how this is done, here is an example. Suppose `INTERFACE` is
* `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are:
- * 1. Use DECLARE_HYBRID_META_INTERFACE instead of DECLARE_META_INTERFACE in the
- * definition of `IFoo`. The usage is
- * DECLARE_HYBRID_META_INTERFACE(IFoo, HFoo)
- * inside the body of `IFoo`.
+ * 1. Use `DECLARE_HYBRID_META_INTERFACE` instead of `DECLARE_META_INTERFACE` in
+ * the declaration of `IFoo`. `DECLARE_HYBRID_META_INTERFACE` takes an
+ * additional argument that is the hidl interface to be converted into a
+ * binder interface. Example:
+ * Change from `DECLARE_META_INTERFACE(Foo)`
+ * to `DECLARE_HYBRID_META_INTERFACE(Foo, HFoo)`
* 2. Create a converter class that derives from
- * `H2BConverter<HFoo, IFoo, BnFoo>`. Let us call this `H2BFoo`.
+ * `H2BConverter<HFoo, BnFoo>`. Let us call this `H2BFoo`.
* 3. Add the following constructor in `H2BFoo` that call the corresponding
* constructors in `H2BConverter`:
- * H2BFoo(const sp<HalInterface>& base) : CBase(base) {}
- * Note: `CBase = H2BConverter<HFoo, IFoo, BnFoo>` and `HalInterface = HFoo`
- * are member typedefs of `H2BConverter<HFoo, IFoo, BnFoo>`, so the above
- * line can be copied into `H2BFoo`.
+ * `H2BFoo(const sp<HalInterface>& base) : CBase(base) {}`
+ * Note: `CBase = H2BConverter<HFoo, BnFoo>` and `HalInterface = HFoo` are
+ * member typedefs of `H2BConverter<HFoo, BnFoo>`, so the above line can be
+ * copied verbatim into `H2BFoo`.
* 4. Implement `IFoo` in `H2BFoo` on top of `HFoo`. `H2BConverter` provides a
* protected `mBase` of type `sp<HFoo>` that can be used to access the `HFoo`
- * instance. (There is also a public function named `getHalInterface()` that
- * returns `mBase`.)
+ * instance. (There is also a public function named `getBase()` that returns
+ * `mBase`.)
* 5. Create a hardware proxy class that derives from
* `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot
* deviate. See step 8 below.)
* 6. Add the following constructor to `HpFoo`:
- * HpFoo(const sp<IBinder>& base): PBase(base) {}
+ * `HpFoo(const sp<IBinder>& base): PBase(base) {}`
* Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is
* equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be
* copied verbatim into `HpFoo`.
- * 7. Delegate all functions in `HpFoo` that come from `IFoo` except
- * `getHalInterface` to the protected member `mBase`,
- * which is defined in `HpInterface<BpFoo, H2BFoo>` (hence in `HpFoo`) with
- * type `IFoo`. (There is also a public function named `getBaseInterface()`
- * that returns `mBase`.)
- * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for INTERFACE by
- * `IMPLEMENT_HYBRID_META_INTERFACE`. Note that this macro relies on the
- * exact naming of `HpFoo`, where `Foo` comes from the interface name `IFoo`.
- * An example usage is
- * IMPLEMENT_HYBRID_META_INTERFACE(IFoo, HFoo, "example.interface.foo");
+ * 7. Delegate all functions in `HpFoo` that come from `IFoo` (except those that
+ * are defined by the macro `DECLARE_HYBRID_META_INTERFACE`) to the protected
+ * member `mBase`. `mBase` is defined in `HpInterface<BpFoo, H2BFoo>` (hence
+ * in `HpFoo`) with type `IFoo`. There is also a public function named
+ * `getBase()` that returns `mBase`.
+ * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for `IFoo` by
+ * `IMPLEMENT_HYBRID_META_INTERFACE`. This macro assumes that the subclass of
+ * `HpInterface` for `IFoo` is named `HpFoo`.
*
- * `GETTOKEN` Template Argument
- * ============================
+ * After the hybrid interface has been put in place properly, it can be used to
+ * do the following tasks:
+ * 1. Create an `IFoo` instance from an `HFoo` by passing `sp<HFoo>` to
+ * the constructor of `H2BFoo`.
+ * 2. Retrieve an `HFoo` from an `HpFoo` instance by calling
+ * `HpFoo::getHalInterface<HFoo>()`. This function may return `nullptr` if
+ * the `HpFoo` object is not backed by `HFoo`. The template parameter is
+ * required because `HpFoo` in fact may be backed by multiple H2B converter
+ * classes.
*
- * Following the instructions above, `H2BConverter` and `HpInterface` would use
- * `transact()` to send over tokens, with `code` (the first argument of
- * `transact()`) equal to `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`. If this
- * value clashes with other values already in use in the `Bp` class, it can be
- * changed by supplying the last optional template argument to `H2BConverter`
- * and `HpInterface`.
+ * Multiple H2B Converters
+ * =======================
+ *
+ * Because the system may support multiple versions of hidl interfaces for the
+ * same object, one binder interface may correspond to multiple H2B converters.
+ * The hybrid interface is designed to handle this as
+ * well---`DECLARE_HYBRID_META_INTERFACE` and `HpInterface` can take a variable
+ * number of arguments.
+ *
+ * As a concrete example, suppose `IFoo` is a binder interface that corresponds
+ * to two hidl interfaces `HFoo1` and `HFoo2`. That means `HpFoo`, the hybrid
+ * interface presenting `IFoo`, may be backed by `HFoo1` or `HFoo2`. This is
+ * achievable by
+ *
+ * - Replacing `DECLARE_META_INTERFACE(Foo)` by
+ * `DECLARE_HYBRID_META_INTERFACE(Foo, HFoo1, HFoo2)` in the declaration of
+ * `IFoo`.
+ * - Creating `H2BFoo1` as a subclass of `H2BConverter<HFoo1, BnFoo>`;
+ * - Creating `H2BFoo2` as a subclass of `H2BConverter<HFoo2, BnFoo>`; and
+ * - Creating `HpFoo` as a subclass of `HpInterface<BpFoo, H2BFoo1, H2BFoo2>`.
+ *
+ * It is important that `HFoo1` and `HFoo2` are different hidl interfaces. [The
+ * actual requirement is that for each pair `<HFoo, IFoo>`, there can be only
+ * one subclass of `H2BConverter<HFoo, BnFoo>`.]
+ *
+ * As mentioned in the previous section, `HpFoo::getHalInterface` requires a
+ * template argument because it must be able to return different hidl
+ * interface types based on which hidl interface is being used. The user of
+ * `HpFoo` can query the type of the underlying hidl interface by calling
+ * `HpFoo::getHalIndex()`. The return value is a 1-based index into the list of
+ * all the supported hidl interfaces. In the example with 2 hidl interfaces
+ * `HFoo1` and `HFoo2`, index 1 corresponds to `HFoo1` and index 2 corresponds
+ * to `HFoo2`. A typical code block that accesses the underlying hidl interface
+ * of would look like this:
+ *
+ * void someFunction(const sp<IFoo> &foo) {
+ *
+ * switch (foo->getHalIndex()) {
+ * case 1: {
+ * sp<HFoo1> hFoo1 = foo->getHalInterface<HFoo1>();
+ * ...
+ * break;
+ * }
+ * case 2: {
+ * sp<HFoo2> hFoo2 = foo->getHalInterface<HFoo2>();
+ * ...
+ * break;
+ * }
+ * default: // Not backed by a hidl interface.
+ * // Alternatively, "case 0:" can be used.
+ * }
+ *
+ * }
+ *
+ * Error State
+ * ===========
+ *
+ * A corrupted transaction may cause an `HpInterface` to be in an error state.
+ * This could cause `getHalInterface<ExpectedHalInterface>()` to return
+ * `nullptr` even though `getHalIndex()` returns a non-zero index and
+ * `ExpectedHalInterface` is the corresponding hidl interface. It is therefore
+ * recommended that a null check be performed on the return value of
+ * `getHalInterface` before using it.
+ *
+ * DECLARE_HYBRID_META_INTERFACE_WITH_CODE
+ * =======================================
+ *
+ * `H2BConverter` and `HpInterface` use `transact()` to send over tokens with
+ * the transaction code (the first argument of `transact()`) equal to `_GHT`,
+ * which is defined as a global constant named
+ * `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`.
+ *
+ * In the rare occasion that this value clashes with other values already used
+ * by the `Bp` class and modifying the `Bp` class is difficult, the
+ * "GET_HAL_TOKEN" transaction code can be changed to a different value simply
+ * by replacing `DECLARE_HYBRID_META_INTERFACE` with
+ * `DECLARE_HYBRID_META_INTERFACE_WITH_CODE` in the declaration of the base
+ * interface and supplying the new transaction code in the first argument of
+ * this macro.
*
*/
@@ -106,23 +189,19 @@
bool createHalToken(const sp<HInterface>& interface, HalToken* token);
bool deleteHalToken(const HalToken& token);
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
+template <typename HINTERFACE,
+ typename BNINTERFACE>
class H2BConverter : public BNINTERFACE {
public:
- typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN> CBase; // Converter Base
- typedef INTERFACE BaseInterface;
+ typedef H2BConverter<HINTERFACE, BNINTERFACE> CBase; // Converter Base
+ typedef typename BNINTERFACE::BaseInterface BaseInterface;
typedef HINTERFACE HalInterface;
- static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
+ typedef typename BaseInterface::HalVariant HalVariant;
+ using BaseInterface::sGetHalTokenTransactionCode;
- H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
+ H2BConverter(const sp<HalInterface>& base) : mBase{base} {}
virtual status_t onTransact(uint32_t code,
const Parcel& data, Parcel* reply, uint32_t flags = 0);
- virtual sp<HalInterface> getHalInterface() { return mBase; }
- HalInterface* getBaseInterface() { return mBase.get(); }
virtual status_t linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie = nullptr,
@@ -132,9 +211,13 @@
void* cookie = nullptr,
uint32_t flags = 0,
wp<IBinder::DeathRecipient>* outRecipient = nullptr);
+ virtual HalVariant getHalVariant() const override { return { mBase }; }
+ HalInterface* getBase() { return mBase.get(); }
protected:
sp<HalInterface> mBase;
+
+private:
struct Obituary : public hardware::hidl_death_recipient {
wp<IBinder::DeathRecipient> recipient;
void* cookie;
@@ -168,78 +251,177 @@
};
std::mutex mObituariesLock;
std::vector<sp<Obituary> > mObituaries;
+
+ template <size_t Index = std::variant_size_v<HalVariant> - 1>
+ static constexpr size_t _findIndex() {
+ if constexpr (Index == 0) {
+ return Index;
+ } else if constexpr (
+ std::is_same_v<
+ std::variant_alternative_t<Index, HalVariant>,
+ sp<HalInterface>>) {
+ return Index;
+ } else {
+ return _findIndex<Index - 1>();
+ }
+ }
+
+ static constexpr size_t sHalIndex = _findIndex<>();
+ static_assert(sHalIndex != 0,
+ "H2BConverter from an unrecognized HAL interface.");
};
-template <
- typename BPINTERFACE,
- typename CONVERTER,
- uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
+template <typename BPINTERFACE, typename CONVERTER, typename... CONVERTERS>
class HpInterface : public CONVERTER::BaseInterface {
public:
- typedef HpInterface<BPINTERFACE, CONVERTER, GETTOKEN> PBase; // Proxy Base
+ typedef HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...> PBase; // Proxy Base
typedef typename CONVERTER::BaseInterface BaseInterface;
- typedef typename CONVERTER::HalInterface HalInterface;
- static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
+ typedef typename BaseInterface::HalVariant HalVariant;
+ using BaseInterface::sGetHalTokenTransactionCode;
explicit HpInterface(const sp<IBinder>& impl);
- virtual sp<HalInterface> getHalInterface() { return mHal; }
- BaseInterface* getBaseInterface() { return mBase.get(); }
+ BaseInterface* getBase() { return mBase.get(); }
+ virtual HalVariant getHalVariant() const override { return mHalVariant; }
protected:
- IBinder* mImpl;
+ IBinder* mBpBinder;
sp<BPINTERFACE> mBp;
sp<BaseInterface> mBase;
- sp<HalInterface> mHal;
- IBinder* onAsBinder() override { return mImpl; }
+ HalVariant mHalVariant;
+ bool mHasConverter{false};
+ IBinder* onAsBinder() override { return mBpBinder; }
+
+private:
+ typedef std::variant<std::monostate,
+ CONVERTER, CONVERTERS...> _ConverterVar;
+ typedef std::variant<std::monostate,
+ typename CONVERTER::HalInterface,
+ typename CONVERTERS::HalInterface...> _ConverterHalVar;
+ typedef std::variant<std::monostate,
+ sp<typename CONVERTER::HalInterface>,
+ sp<typename CONVERTERS::HalInterface>...> _ConverterHalPointerVar;
+
+ static_assert(std::is_same_v<_ConverterHalPointerVar, HalVariant>,
+ "Converter classes do not match HAL interfaces.");
+
+ template <size_t Index = std::variant_size_v<HalVariant> - 1>
+ bool _castFromHalBaseAndConvert(size_t halIndex,
+ const sp<HInterface>& halBase) {
+ if constexpr (Index == 0) {
+ return false;
+ } else {
+ if (halIndex != Index) {
+ return _castFromHalBaseAndConvert<Index - 1>(halIndex, halBase);
+ }
+ typedef std::variant_alternative_t<Index, _ConverterHalVar>
+ HalInterface;
+ sp<HalInterface> halInterface = HalInterface::castFrom(halBase);
+ mHalVariant.template emplace<Index>(halInterface);
+ if (!halInterface) {
+ return false;
+ }
+ if (mHasConverter) {
+ typedef std::variant_alternative_t<Index, _ConverterVar>
+ Converter;
+ sp<Converter> converter = new Converter(halInterface);
+ if (converter) {
+ mBase = converter;
+ } else {
+ ALOGW("HpInterface: Failed to create an H2B converter -- "
+ "index = %zu.", Index);
+ }
+ }
+ return true;
+ }
+ }
+
+ bool castFromHalBaseAndConvert(size_t halIndex,
+ const sp<HInterface>& halBase) {
+ if (!_castFromHalBaseAndConvert<>(halIndex, halBase)) {
+ return false;
+ }
+ return true;
+ }
+
};
// ----------------------------------------------------------------------
-#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, HAL) \
- static const ::android::String16 descriptor; \
- static ::android::sp<I##INTERFACE> asInterface( \
- const ::android::sp<::android::IBinder>& obj); \
- virtual const ::android::String16& getInterfaceDescriptor() const; \
- I##INTERFACE(); \
- virtual ~I##INTERFACE(); \
- virtual sp<HAL> getHalInterface(); \
+#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, ...) \
+ DECLARE_HYBRID_META_INTERFACE_WITH_CODE( \
+ ::android::DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE, \
+ INTERFACE, __VA_ARGS__) \
-#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, HAL, NAME) \
- const ::android::String16 I##INTERFACE::descriptor(NAME); \
- const ::android::String16& \
- I##INTERFACE::getInterfaceDescriptor() const { \
- return I##INTERFACE::descriptor; \
- } \
- ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
- const ::android::sp<::android::IBinder>& obj) \
- { \
- ::android::sp<I##INTERFACE> intr; \
- if (obj != nullptr) { \
- intr = static_cast<I##INTERFACE*>( \
- obj->queryLocalInterface( \
- I##INTERFACE::descriptor).get()); \
- if (intr == nullptr) { \
- intr = new Hp##INTERFACE(obj); \
- } \
- } \
- return intr; \
- } \
- I##INTERFACE::I##INTERFACE() { } \
- I##INTERFACE::~I##INTERFACE() { } \
- sp<HAL> I##INTERFACE::getHalInterface() { return nullptr; } \
+#define DECLARE_HYBRID_META_INTERFACE_WITH_CODE(GTKCODE, INTERFACE, ...) \
+private: \
+ typedef ::std::variant<::std::monostate, __VA_ARGS__> _HalVariant; \
+ template <typename... Types> \
+ using _SpVariant = \
+ ::std::variant<::std::monostate, ::android::sp<Types>...>; \
+public: \
+ typedef _SpVariant<__VA_ARGS__> HalVariant; \
+ virtual HalVariant getHalVariant() const; \
+ size_t getHalIndex() const; \
+ template <size_t Index> \
+ using HalInterface = ::std::variant_alternative_t<Index, _HalVariant>;\
+ template <typename HAL> \
+ sp<HAL> getHalInterface() const { \
+ HalVariant halVariant = getHalVariant(); \
+ const sp<HAL>* hal = std::get_if<sp<HAL>>(&halVariant); \
+ return hal ? *hal : nullptr; \
+ } \
+ \
+ static const ::android::String16 descriptor; \
+ static ::android::sp<I##INTERFACE> asInterface( \
+ const ::android::sp<::android::IBinder>& obj); \
+ virtual const ::android::String16& getInterfaceDescriptor() const; \
+ I##INTERFACE(); \
+ virtual ~I##INTERFACE(); \
+ static constexpr uint32_t sGetHalTokenTransactionCode = GTKCODE; \
+
+
+#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, NAME) \
+ I##INTERFACE::HalVariant I##INTERFACE::getHalVariant() const { \
+ return HalVariant{std::in_place_index<0>}; \
+ } \
+ size_t I##INTERFACE::getHalIndex() const { \
+ return getHalVariant().index(); \
+ } \
+ constexpr uint32_t I##INTERFACE::sGetHalTokenTransactionCode; \
+ static const ::android::StaticString16 I##INTERFACE##_desc_str16( \
+ u##NAME); \
+ const ::android::String16 I##INTERFACE::descriptor( \
+ I##INTERFACE##_desc_str16); \
+ const ::android::String16& \
+ I##INTERFACE::getInterfaceDescriptor() const { \
+ return I##INTERFACE::descriptor; \
+ } \
+ ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
+ const ::android::sp<::android::IBinder>& obj) \
+ { \
+ ::android::sp<I##INTERFACE> intr; \
+ if (obj != nullptr) { \
+ intr = static_cast<I##INTERFACE*>( \
+ obj->queryLocalInterface( \
+ I##INTERFACE::descriptor).get()); \
+ if (intr == nullptr) { \
+ intr = new Hp##INTERFACE(obj); \
+ } \
+ } \
+ return intr; \
+ } \
+ I##INTERFACE::I##INTERFACE() { } \
+ I##INTERFACE::~I##INTERFACE() { } \
// ----------------------------------------------------------------------
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN>
-status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
+template <typename HINTERFACE,
+ typename BNINTERFACE>
+status_t H2BConverter<HINTERFACE, BNINTERFACE>::
onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- if (code == GET_HAL_TOKEN) {
+ if (code == sGetHalTokenTransactionCode) {
if (!data.enforceInterface(BaseInterface::getInterfaceDescriptor())) {
return BAD_TYPE;
}
@@ -247,27 +429,35 @@
HalToken token;
bool result;
result = createHalToken(mBase, &token);
+ // Write whether a HAL token is present.
+ reply->writeBool(result);
if (!result) {
ALOGE("H2BConverter: Failed to create HAL token.");
+ return NO_ERROR;
}
- reply->writeBool(result);
+
+ // Write the HAL token.
reply->writeByteArray(token.size(), token.data());
+
+ // Write the HAL index.
+ reply->writeUint32(static_cast<uint32_t>(sHalIndex));
+
+ // Write a flag indicating that a converter needs to be created.
+ reply->writeBool(true);
+
return NO_ERROR;
}
return BNINTERFACE::onTransact(code, data, reply, flags);
}
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN>
-status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
- linkToDeath(
+template <typename HINTERFACE,
+ typename BNINTERFACE>
+status_t H2BConverter<HINTERFACE, BNINTERFACE>::linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
- LOG_ALWAYS_FATAL_IF(recipient == nullptr,
- "linkToDeath(): recipient must be non-nullptr");
+ LOG_ALWAYS_FATAL_IF(
+ recipient == nullptr,
+ "linkToDeath(): recipient must not be null.");
{
std::lock_guard<std::mutex> lock(mObituariesLock);
mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
@@ -278,13 +468,9 @@
return NO_ERROR;
}
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN>
-status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
- unlinkToDeath(
+template <typename HINTERFACE,
+ typename BNINTERFACE>
+status_t H2BConverter<HINTERFACE, BNINTERFACE>::unlinkToDeath(
const wp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags,
wp<IBinder::DeathRecipient>* outRecipient) {
@@ -304,43 +490,76 @@
return NAME_NOT_FOUND;
}
-template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN>
-HpInterface<BPINTERFACE, CONVERTER, GETTOKEN>::HpInterface(
- const sp<IBinder>& impl) :
- mImpl(impl.get()),
- mBp(new BPINTERFACE(impl)) {
+template <typename BPINTERFACE, typename CONVERTER, typename... CONVERTERS>
+HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...>::HpInterface(
+ const sp<IBinder>& impl)
+ : mBpBinder{impl.get()},
+ mBp{new BPINTERFACE(impl)} {
mBase = mBp;
- if (mImpl->remoteBinder() == nullptr) {
+ if (!mBpBinder->remoteBinder()) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor());
- if (mImpl->transact(GET_HAL_TOKEN, data, &reply) == NO_ERROR) {
- bool tokenCreated = reply.readBool();
+ if (mBpBinder->transact(sGetHalTokenTransactionCode,
+ data, &reply) == NO_ERROR) {
+ // Read whether a HAL token is present.
+ bool tokenCreated;
+ if (reply.readBool(&tokenCreated) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(tokenCreated).");
+ }
+ if (!tokenCreated) {
+ ALOGW("HpInterface: No HAL token was created.");
+ return;
+ }
+
+ // Read the HAL token.
std::vector<uint8_t> tokenVector;
- reply.readByteVector(&tokenVector);
- HalToken token = HalToken(tokenVector);
+ if (reply.readByteVector(&tokenVector) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(halToken).");
+ return;
+ }
- if (tokenCreated) {
- sp<HInterface> hBase = retrieveHalInterface(token);
- if (hBase != nullptr) {
- mHal = HalInterface::castFrom(hBase);
- if (mHal != nullptr) {
- mBase = new CONVERTER(mHal);
- } else {
- ALOGE("HpInterface: Wrong interface type.");
- }
- } else {
- ALOGE("HpInterface: Invalid HAL token.");
- }
- deleteHalToken(token);
+ // Retrieve the HAL interface from the token.
+ HalToken token{tokenVector};
+ sp<HInterface> halBase = retrieveHalInterface(token);
+ deleteHalToken(token);
+
+ if (!halBase) {
+ ALOGW("HpInterface: Failed to retrieve HAL interface.");
+ return;
+ }
+
+ uint32_t halIndex;
+ // Read the hal index.
+ if (reply.readUint32(&halIndex) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(halIndex).");
+ return;
+ }
+
+ // Read the converter flag.
+ if (reply.readBool(&mHasConverter) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(hasConverter).");
+ return;
+ }
+
+ // Call castFrom from the right HAL interface and create a converter if
+ // needed.
+ if (!castFromHalBaseAndConvert(static_cast<size_t>(halIndex),
+ halBase)) {
+ ALOGW("HpInterface: Failed to cast to the correct HAL interface -- "
+ "HAL index = %" PRIu32 ".", halIndex);
}
}
}
// ----------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_HYBRIDINTERFACE_H
diff --git a/vintfdata/Android.mk b/vintfdata/Android.mk
index ffe361f..7a30668 100644
--- a/vintfdata/Android.mk
+++ b/vintfdata/Android.mk
@@ -23,10 +23,6 @@
# installed on product partition.
FRAMEWORK_MANIFEST_INPUT_FILES := $(LOCAL_PATH)/manifest.xml
-# TODO(b/110487738): replace with vintf_fragment
-ifdef USE_VR_FLINGER
- FRAMEWORK_MANIFEST_INPUT_FILES += $(LOCAL_PATH)/manifest_vr_hwc.xml
-endif
ifdef DEVICE_FRAMEWORK_MANIFEST_FILE
FRAMEWORK_MANIFEST_INPUT_FILES += $(DEVICE_FRAMEWORK_MANIFEST_FILE)
endif
diff --git a/vintfdata/manifest_vr_hwc.xml b/vintfdata/manifest_vr_hwc.xml
deleted file mode 100644
index 1068cac..0000000
--- a/vintfdata/manifest_vr_hwc.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="framework">
- <hal>
- <name>android.hardware.graphics.composer</name>
- <transport>hwbinder</transport>
- <version>2.1</version>
- <interface>
- <name>IComposer</name>
- <instance>vr</instance>
- </interface>
- </hal>
-</manifest>