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>