[automerger skipped] Add gServiceSidMap.
am: ca016f9ac4 -s ours
am skip reason: change_id I4e5821d91ea694f86911218c23e68fcb987daaf9 with SHA1 d7f8d2226f is in history

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