Merge pie-platform-release to aosp-master - DO NOT MERGE

Change-Id: I19d3fcbb4eb71702b49096b780b13a73bd0bd194
diff --git a/Android.bp b/Android.bp
index 032a61a..0f91348 100644
--- a/Android.bp
+++ b/Android.bp
@@ -17,6 +17,7 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-Wextra-semi",
     ],
 }
 
diff --git a/adapter/HidlBinderAdapter.cpp b/adapter/HidlBinderAdapter.cpp
index b6aa58e..ed6dad1 100644
--- a/adapter/HidlBinderAdapter.cpp
+++ b/adapter/HidlBinderAdapter.cpp
@@ -36,42 +36,92 @@
 
 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."
+int usage(const std::string& me) {
+    std::cerr << "usage: " << me
+              << " [-p|P] [-n instance-name] interface-name instance-name number-of-threads."
               << std::endl;
     std::cerr << "    -p: stop based on property " << kDeactivateProp << "and reset it."
               << std::endl;
+    std::cerr << "    -P: stop based on interface specific property " << kDeactivateProp
+              << ".<fq-name>.<instance-name>" << std::endl;
+    std::cerr
+        << "    -n instance-name: register as a different instance name (does not de-register)"
+        << std::endl;
+    return EINVAL;
 }
 
-bool processArguments(int* argc, char*** argv, bool* propertyStop) {
+enum class StopMethod {
+    NONE,
+    ALL,
+    SPECIFIC,
+};
+
+struct Args {
+    StopMethod stopMethod = StopMethod::NONE;
+    std::string interface;     // e.x. IFoo
+    std::string instanceName;  // e.x. default
+    int threadNumber;
+    std::string registerInstanceName;  // e.x. default
+};
+
+bool processArguments(int argc, char** argv, Args* args) {
     int c;
-    while ((c = getopt(*argc, *argv, "p")) != -1) {
+    while ((c = getopt(argc, argv, "pPn:")) != -1) {
         switch (c) {
             case 'p': {
-                *propertyStop = true;
+                args->stopMethod = StopMethod::ALL;
+                break;
+            }
+            case 'P': {
+                args->stopMethod = StopMethod::SPECIFIC;
+                break;
+            }
+            case 'n': {
+                args->registerInstanceName = optarg;
                 break;
             }
             default: { return false; }
         }
     }
 
-    *argc -= optind;
-    *argv += optind;
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 3) {
+        std::cerr << "ERROR: requires exactly three positional arguments for "
+                     "interface, instance name, and number of threads, but "
+                  << argc << " provided." << std::endl;
+        return false;
+    }
+
+    args->interface = argv[0];
+    args->instanceName = argv[1];
+    args->threadNumber = std::stoi(argv[2]);
+
+    if (args->threadNumber <= 0) {
+        std::cerr << "ERROR: invalid thread number " << args->threadNumber
+                  << " must be a positive integer." << std::endl;
+        return false;
+    }
+
+    if (args->registerInstanceName.empty()) {
+        args->registerInstanceName = args->instanceName;
+    }
+
     return true;
 }
 
 // only applies for -p argument
-void waitForAdaptersDeactivated() {
+void waitForAdaptersDeactivated(const std::string& property) {
     using std::literals::chrono_literals::operator""s;
 
-    while (!WaitForProperty(kDeactivateProp, "true", 30s)) {
+    while (!WaitForProperty(property, "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;
+        LOG(WARNING) << "Adapter use in progress. Waiting for stop based on 'true' " << property;
     }
 
-    SetProperty(kDeactivateProp, "false");
+    SetProperty(property, "false");
 }
 
 int adapterMain(const std::string& package, int argc, char** argv,
@@ -82,25 +132,12 @@
 
     const std::string& me = argc > 0 ? argv[0] : "(error)";
 
-    bool propertyStop = false;
-    if (!processArguments(&argc, &argv, &propertyStop)) {
-        usage(me);
-        return EINVAL;
+    Args args;
+    if (!processArguments(argc, argv, &args)) {
+        return usage(me);
     }
 
-    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.";
-    }
+    std::string interfaceName = package + "::" + args.interface;
 
     auto it = adapters.find(interfaceName);
     if (it == adapters.end()) {
@@ -108,9 +145,10 @@
         return 1;
     }
 
-    std::cout << "Trying to adapt down " << interfaceName << "/" << instanceName << std::endl;
+    std::cout << "Trying to adapt down " << interfaceName << "/" << args.instanceName << " to "
+              << args.registerInstanceName << std::endl;
 
-    configureRpcThreadpool(threadNumber, false /* callerWillJoin */);
+    configureRpcThreadpool(args.threadNumber, false /* callerWillJoin */);
 
     sp<IServiceManager> manager = IServiceManager::getService();
     if (manager == nullptr) {
@@ -118,7 +156,7 @@
         return 1;
     }
 
-    sp<IBase> implementation = manager->get(interfaceName, instanceName).withDefault(nullptr);
+    sp<IBase> implementation = manager->get(interfaceName, args.instanceName).withDefault(nullptr);
     if (implementation == nullptr) {
         std::cerr << "ERROR: could not retrieve desired implementation" << std::endl;
         return 1;
@@ -130,25 +168,40 @@
         return 1;
     }
 
-    bool replaced = manager->add(instanceName, adapter).withDefault(false);
+    bool replaced = manager->add(args.registerInstanceName, 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();
+    switch (args.stopMethod) {
+        case StopMethod::NONE: {
+            std::cout << "Press any key to disassociate adapter." << std::endl;
+            getchar();
+            break;
+        };
+        case StopMethod::SPECIFIC: {
+            const std::string property =
+                kDeactivateProp + "." + interfaceName + "." + args.registerInstanceName;
+            std::cout << "Set " << property << " to true to deactivate." << std::endl;
+            waitForAdaptersDeactivated(property);
+            break;
+        };
+        case StopMethod::ALL: {
+            std::cout << "Set " << kDeactivateProp << " to true to deactivate." << std::endl;
+            waitForAdaptersDeactivated(kDeactivateProp);
+            break;
+        };
     }
 
-    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;
+    // automatically unregistered on process exit if it is a new instance name
+    if (args.registerInstanceName == args.instanceName) {
+        bool restored = manager->add(args.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;
diff --git a/base/Android.bp b/base/Android.bp
index 22f5ee1..359ac91 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -14,6 +14,7 @@
 
 cc_library {
     name: "libhidlbase",
+    recovery_available: true,
     vendor_available: true,
     vndk: {
         enabled: true,
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index babdac1..440b30f 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -31,16 +31,17 @@
 #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";
+
+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";
+const char kSysPropInstrumentationPath[] = "hal.instrumentation.lib.path.64";
 #else
-const char* kSysPropInstrumentationPath = "hal.instrumentation.lib.path.32";
+const char kSysPropInstrumentationPath[] = "hal.instrumentation.lib.path.32";
 #endif
-#endif
+#endif  // LIBHIDL_TARGET_DEBUGGABLE
 
 namespace android {
 namespace hardware {
@@ -145,7 +146,9 @@
     } else {
         static std::string halLibPathVndkSp = android::base::StringPrintf(
             HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, getVndkVersionStr().c_str());
+#ifndef __ANDROID_VNDK__
         instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
+#endif
         instrumentationLibPaths.push_back(halLibPathVndkSp);
         instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
         instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
@@ -153,7 +156,7 @@
 
     for (const auto& path : instrumentationLibPaths) {
         DIR *dir = opendir(path.c_str());
-        if (dir == 0) {
+        if (dir == nullptr) {
             LOG(WARNING) << path << " does not exist. ";
             return;
         }
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index 8f3c057..58afa69 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -56,7 +56,7 @@
 }
 
 // move constructor.
-hidl_handle::hidl_handle(hidl_handle &&other) {
+hidl_handle::hidl_handle(hidl_handle&& other) noexcept {
     mOwnsHandle = false;
     *this = std::move(other);
 }
@@ -87,7 +87,7 @@
     return *this;
 }
 
-hidl_handle &hidl_handle::operator=(hidl_handle &&other) {
+hidl_handle& hidl_handle::operator=(hidl_handle&& other) noexcept {
     if (this != &other) {
         freeHandle();
         mHandle = other.mHandle;
@@ -167,11 +167,11 @@
     copyFrom(s.c_str(), s.size());
 }
 
-hidl_string::hidl_string(hidl_string &&other): hidl_string() {
+hidl_string::hidl_string(hidl_string&& other) noexcept : hidl_string() {
     moveFrom(std::forward<hidl_string>(other));
 }
 
-hidl_string &hidl_string::operator=(hidl_string &&other) {
+hidl_string& hidl_string::operator=(hidl_string&& other) noexcept {
     if (this != &other) {
         clear();
         moveFrom(std::forward<hidl_string>(other));
@@ -254,6 +254,14 @@
     if (size > UINT32_MAX) {
         LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size;
     }
+
+    // When the binder driver copies this data into its buffer, it must
+    // have a zero byte there because the remote process will have a pointer
+    // directly into the read-only binder buffer. If we manually copy the
+    // data now to add a zero, then we lose the efficiency of this method.
+    // Checking here (it's also checked in the parceling code later).
+    CHECK(data[size] == '\0');
+
     clear();
 
     mBuffer = data;
@@ -307,9 +315,7 @@
         : 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();
-}
+HidlMemory::~HidlMemory() {}
 
 }  // namespace hardware
 }  // namespace android
diff --git a/base/Status.cpp b/base/Status.cpp
index 1ba91c3..5a4c918 100644
--- a/base/Status.cpp
+++ b/base/Status.cpp
@@ -82,11 +82,17 @@
 }
 
 Status Status::fromExceptionCode(int32_t exceptionCode) {
+    if (exceptionCode == EX_TRANSACTION_FAILED) {
+        return Status(exceptionCode, FAILED_TRANSACTION);
+    }
     return Status(exceptionCode, OK);
 }
 
 Status Status::fromExceptionCode(int32_t exceptionCode,
                                  const char *message) {
+    if (exceptionCode == EX_TRANSACTION_FAILED) {
+        return Status(exceptionCode, FAILED_TRANSACTION, message);
+    }
     return Status(exceptionCode, OK, message);
 }
 
@@ -107,7 +113,7 @@
 
 void Status::setException(int32_t ex, const char *message) {
     mException = ex;
-    mErrorCode = NO_ERROR;  // an exception, not a transaction failure.
+    mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
     mMessage = message;
 }
 
@@ -150,7 +156,7 @@
         }
     }
 
-    return_status &return_status::operator=(return_status &&other) {
+    return_status& return_status::operator=(return_status&& other) noexcept {
         if (!mCheckedStatus && !isOk()) {
             LOG(FATAL) << "Failed HIDL return status not checked: " << description();
         }
diff --git a/base/include/hidl/HidlInternal.h b/base/include/hidl/HidlInternal.h
index 5a08bc3..6377c46 100644
--- a/base/include/hidl/HidlInternal.h
+++ b/base/include/hidl/HidlInternal.h
@@ -48,6 +48,15 @@
 // If "ro.vndk.version" is not set or set to "current", it returns empty string.
 std::string getVndkVersionStr();
 
+// Explicitly invokes the parameterized element's destructor;
+// intended to be used alongside the placement new operator.
+template<typename T>
+void destructElement(T* element) {
+    if (element != nullptr) {
+        element->~T();
+    }
+}
+
 // HIDL client/server code should *NOT* use this class.
 //
 // hidl_pointer wraps a pointer without taking ownership,
@@ -62,13 +71,13 @@
     }
     hidl_pointer(T* ptr) : hidl_pointer() { mPointer = ptr; }
     hidl_pointer(const hidl_pointer<T>& other) : hidl_pointer() { mPointer = other.mPointer; }
-    hidl_pointer(hidl_pointer<T>&& other) : hidl_pointer() { *this = std::move(other); }
+    hidl_pointer(hidl_pointer<T>&& other) noexcept : hidl_pointer() { *this = std::move(other); }
 
     hidl_pointer &operator=(const hidl_pointer<T>& other) {
         mPointer = other.mPointer;
         return *this;
     }
-    hidl_pointer &operator=(hidl_pointer<T>&& other) {
+    hidl_pointer& operator=(hidl_pointer<T>&& other) noexcept {
         mPointer = other.mPointer;
         other.mPointer = nullptr;
         return *this;
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index f09eb63..2d0dc25 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -40,18 +40,22 @@
 namespace hidl {
 namespace memory {
 namespace V1_0 {
-    struct IMemory;
-}; // namespace V1_0
-}; // namespace manager
-}; // namespace hidl
+
+struct IMemory;
+
+}  // namespace V1_0
+}  // namespace memory
+}  // namespace hidl
 
 namespace hidl {
 namespace base {
 namespace V1_0 {
-    struct IBase;
-}; // namespace V1_0
-}; // namespace base
-}; // namespace hidl
+
+struct IBase;
+
+}  // namespace V1_0
+}  // namespace base
+}  // namespace hidl
 
 namespace hardware {
 
@@ -112,6 +116,10 @@
 
     // explicit conversion
     const native_handle_t *getNativeHandle() const;
+
+    // offsetof(hidl_handle, mHandle) exposed since mHandle is private.
+    static const size_t kOffsetOfNativeHandle;
+
 private:
     void freeHandle();
 
@@ -155,6 +163,8 @@
     // Reference an external char array. Ownership is _not_ transferred.
     // Caller is responsible for ensuring that underlying memory is valid
     // for the lifetime of this hidl_string.
+    //
+    // size == strlen(data)
     void setToExternal(const char *data, size_t size);
 
     // offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
@@ -839,6 +849,10 @@
         return (mMajor == other.get_major() && mMinor == other.get_minor());
     }
 
+    bool operator!=(const hidl_version& other) const {
+        return !(*this == other);
+    }
+
     bool operator<(const hidl_version& other) const {
         return (mMajor < other.get_major() ||
                 (mMajor == other.get_major() && mMinor < other.get_minor()));
@@ -985,10 +999,17 @@
 
 /**
  * Every HIDL generated enum generates an implementation of this function.
- * E.x.: for(const auto v : hidl_enum_iterator<Enum>) { ... }
+ * E.x.: for(const auto v : hidl_enum_range<Enum>) { ... }
  */
-template <typename>
-struct hidl_enum_iterator;
+template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
+struct hidl_enum_range;
+
+template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
+struct hidl_enum_iterator {
+    static_assert(!std::is_enum<T>::value,
+                  "b/78573628: hidl_enum_iterator was renamed to hidl_enum_range because it is not "
+                  "actually an iterator. Please use that type instead.");
+};
 
 /**
  * Bitfields in HIDL are the underlying type of the enumeration.
diff --git a/base/include/hidl/MQDescriptor.h b/base/include/hidl/MQDescriptor.h
index 23be971..0f61cb5 100644
--- a/base/include/hidl/MQDescriptor.h
+++ b/base/include/hidl/MQDescriptor.h
@@ -59,18 +59,20 @@
 
 template <typename T, MQFlavor flavor>
 struct MQDescriptor {
+    // Takes ownership of handle
     MQDescriptor(
             const std::vector<GrantorDescriptor>& grantors,
             native_handle_t* nHandle, size_t size);
 
+    // Takes ownership of handle
     MQDescriptor(size_t bufferSize, native_handle_t* nHandle,
                  size_t messageSize, bool configureEventFlag = false);
 
     MQDescriptor();
     ~MQDescriptor();
 
-    explicit MQDescriptor(const MQDescriptor &other);
-    MQDescriptor &operator=(const MQDescriptor &other) = delete;
+    explicit MQDescriptor(const MQDescriptor& other) : MQDescriptor() { *this = other; }
+    MQDescriptor& operator=(const MQDescriptor& other);
 
     size_t getSize() const;
 
@@ -213,12 +215,17 @@
     }
 }
 
-template<typename T, MQFlavor flavor>
-MQDescriptor<T, flavor>::MQDescriptor(const MQDescriptor<T, flavor> &other)
-    : mGrantors(other.mGrantors),
-      mHandle(nullptr),
-      mQuantum(other.mQuantum),
-      mFlags(other.mFlags) {
+template <typename T, MQFlavor flavor>
+MQDescriptor<T, flavor>& MQDescriptor<T, flavor>::operator=(const MQDescriptor& other) {
+    mGrantors = other.mGrantors;
+    if (mHandle != nullptr) {
+        native_handle_close(mHandle);
+        native_handle_delete(mHandle);
+        mHandle = nullptr;
+    }
+    mQuantum = other.mQuantum;
+    mFlags = other.mFlags;
+
     if (other.mHandle != nullptr) {
         mHandle = native_handle_create(
                 other.mHandle->numFds, other.mHandle->numInts);
@@ -231,6 +238,8 @@
                &other.mHandle->data[other.mHandle->numFds],
                other.mHandle->numInts * sizeof(int));
     }
+
+    return *this;
 }
 
 template<typename T, MQFlavor flavor>
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index 1a2ef6d..b69d4e4 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -148,10 +148,8 @@
         return_status(const return_status &) = delete;
         return_status &operator=(const return_status &) = delete;
 
-        return_status(return_status &&other) {
-            *this = std::move(other);
-        }
-        return_status &operator=(return_status &&other);
+        return_status(return_status&& other) noexcept { *this = std::move(other); }
+        return_status& operator=(return_status&& other) noexcept;
 
         ~return_status();
 
@@ -197,8 +195,8 @@
     // move-able.
     // precondition: "this" has checked status
     // postcondition: other is safe to destroy after moving to *this.
-    Return(Return &&other) = default;
-    Return &operator=(Return &&) = default;
+    Return(Return&& other) noexcept = default;
+    Return& operator=(Return&&) noexcept = default;
 
     ~Return() = default;
 
@@ -226,8 +224,8 @@
     // move-able.
     // precondition: "this" has checked status
     // postcondition: other is safe to destroy after moving to *this.
-    Return(Return &&other) = default;
-    Return &operator=(Return &&) = default;
+    Return(Return&& other) noexcept = default;
+    Return& operator=(Return&&) noexcept = default;
 
     ~Return() = default;
 
diff --git a/libhidlcache/HidlCache.h b/libhidlcache/HidlCache.h
index db778d3..39a7b3a 100644
--- a/libhidlcache/HidlCache.h
+++ b/libhidlcache/HidlCache.h
@@ -97,7 +97,7 @@
 template <class Key, class Value, class Compare>
 sp<Value> HidlCache<Key, Value, Compare>::unlock(const Key& key) {
     Lock lock(mMutex);
-    if (locked(key) > 0) {
+    if (locked(key)) {
         sp<Value> v = mLocked[key];
         mLocked.erase(key);
         return v;
diff --git a/libhidlcache/HidlMemoryCache.cpp b/libhidlcache/HidlMemoryCache.cpp
index 6f9c25c..a23c388 100644
--- a/libhidlcache/HidlMemoryCache.cpp
+++ b/libhidlcache/HidlMemoryCache.cpp
@@ -28,12 +28,12 @@
 using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
 using IMemory = ::android::hidl::memory::V1_0::IMemory;
 
-class IMemoryDecorator : public virtual IMemory {
+class MemoryDecorator : public virtual IMemory {
    public:
-    IMemoryDecorator(sp<IMemory> heap) : mHeap(heap) {}
-    virtual ~IMemoryDecorator(){};
+    MemoryDecorator(const sp<IMemory>& heap) : mHeap(heap) {}
+    virtual ~MemoryDecorator() {}
     Return<void> update() override { return mHeap->update(); }
-    Return<void> read() override { return mHeap->read(); };
+    Return<void> read() override { return mHeap->read(); }
     Return<void> updateRange(uint64_t start, uint64_t length) override {
         return mHeap->updateRange(start, length);
     }
@@ -49,29 +49,28 @@
     sp<IMemory> mHeap;
 };
 
-class IMemoryCacheable : public virtual IMemoryDecorator {
+class MemoryCacheable : public virtual MemoryDecorator {
    public:
-    IMemoryCacheable(sp<IMemory> heap, sp<IMemoryToken> key) : IMemoryDecorator(heap), mKey(key) {}
-    virtual ~IMemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
+    MemoryCacheable(const sp<IMemory>& heap, sp<IMemoryToken> key)
+        : MemoryDecorator(heap), mKey(key) {}
+    virtual ~MemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
 
    protected:
     sp<IMemoryToken> mKey;
 };
 
-class IMemoryBlock : public virtual IMemoryDecorator {
+class MemoryBlockImpl : public virtual IMemory {
    public:
-    IMemoryBlock(sp<IMemory> heap, uint64_t size, uint64_t offset)
-        : IMemoryDecorator(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
+    MemoryBlockImpl(const sp<IMemory>& heap, uint64_t size, uint64_t offset)
+        : mHeap(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
     bool validRange(uint64_t start, uint64_t length) {
-        return (start + length < mSize) && (start + length >= start) &&
-               (mOffset + mSize < mHeapSize);
+        return (start + length <= mSize) && (start + length >= start) &&
+               (mOffset + mSize <= mHeapSize);
     }
-    Return<void> readRange(uint64_t start, uint64_t length) {
+    Return<void> readRange(uint64_t start, uint64_t length) override {
         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 Void();
         }
         return mHeap->readRange(mOffset + start, length);
     }
@@ -82,6 +81,9 @@
         }
         return mHeap->updateRange(mOffset + start, length);
     }
+    Return<void> read() override { return this->readRange(0, mSize); }
+    Return<void> update() override { return this->updateRange(0, mSize); }
+    Return<void> commit() override { return mHeap->commit(); }
     Return<uint64_t> getSize() override { return mSize; }
     Return<void*> getPointer() override {
         void* p = mHeap->getPointer();
@@ -89,6 +91,7 @@
     }
 
    protected:
+    sp<IMemory> mHeap;
     uint64_t mSize;
     uint64_t mOffset;
     uint64_t mHeapSize;
@@ -102,7 +105,7 @@
 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); });
+        [&](const hidl_memory& mem) { memory = new MemoryCacheable(mapMemory(mem), key); });
     if (!ret.isOk()) {
         ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get.");
         return nullptr;
@@ -117,7 +120,7 @@
     if (heap == nullptr) {
         return nullptr;
     }
-    return new IMemoryBlock(heap, memblk.size, memblk.offset);
+    return new MemoryBlockImpl(heap, memblk.size, memblk.offset);
 }
 
 }  // namespace hardware
diff --git a/libhidlcache/MemoryDealer.cpp b/libhidlcache/MemoryDealer.cpp
index e9196a1..e0e18c7 100644
--- a/libhidlcache/MemoryDealer.cpp
+++ b/libhidlcache/MemoryDealer.cpp
@@ -123,7 +123,7 @@
         // 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);
+        LOG_ALWAYS_FATAL_IF(mList.front() == removed);
 #endif
         delete removed;
     }
@@ -240,7 +240,7 @@
             return freed;
         }
     }
-    return 0;
+    return nullptr;
 }
 
 void SimpleBestFitAllocator::dump(const char* tag) const {
diff --git a/minijail/HardwareMinijail.cpp b/minijail/HardwareMinijail.cpp
index e6b1144..990a689 100644
--- a/minijail/HardwareMinijail.cpp
+++ b/minijail/HardwareMinijail.cpp
@@ -29,7 +29,7 @@
     }
 
     struct minijail* jail = minijail_new();
-    if (jail == NULL) {
+    if (jail == nullptr) {
         LOG(FATAL) << "Failed to create minijail.";
     }
 
diff --git a/test_main.cpp b/test_main.cpp
index 0de46ec..7f80d71 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -390,12 +390,15 @@
     hidl_version v3_0b{3,0};
 
     EXPECT_TRUE(v1_0 < v2_0);
+    EXPECT_TRUE(v1_0 != v2_0);
     EXPECT_TRUE(v2_0 < v2_1);
     EXPECT_TRUE(v2_1 < v3_0);
     EXPECT_TRUE(v2_0 > v1_0);
+    EXPECT_TRUE(v2_0 != v1_0);
     EXPECT_TRUE(v2_1 > v2_0);
     EXPECT_TRUE(v3_0 > v2_1);
     EXPECT_TRUE(v3_0 == v3_0b);
+    EXPECT_FALSE(v3_0 != v3_0b);
     EXPECT_TRUE(v3_0 <= v3_0b);
     EXPECT_TRUE(v2_2 <= v3_0);
     EXPECT_TRUE(v3_0 >= v3_0b);
diff --git a/transport/Android.bp b/transport/Android.bp
index 5b0c11c..f783022 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -14,11 +14,11 @@
 
 hidl_package_root {
     name: "android.hidl",
-    path: "system/libhidl/transport",
 }
 
 cc_library {
     name: "libhidltransport",
+    recovery_available: true,
     vendor_available: true,
     vndk: {
         enabled: true,
@@ -47,16 +47,19 @@
     generated_sources: [
         "android.hidl.manager@1.0_genc++",
         "android.hidl.manager@1.1_genc++",
+        "android.hidl.manager@1.2_genc++",
         "android.hidl.base@1.0_genc++"
     ],
     generated_headers: [
         "android.hidl.manager@1.0_genc++_headers",
         "android.hidl.manager@1.1_genc++_headers",
+        "android.hidl.manager@1.2_genc++_headers",
         "android.hidl.base@1.0_genc++_headers"
     ],
     export_generated_headers: [
         "android.hidl.manager@1.0_genc++_headers",
         "android.hidl.manager@1.1_genc++_headers",
+        "android.hidl.manager@1.2_genc++_headers",
         "android.hidl.base@1.0_genc++_headers"
     ],
 
@@ -77,4 +80,10 @@
             cflags: ["-DENFORCE_VINTF_MANIFEST"]
         },
     },
+
+    target: {
+        recovery: {
+            exclude_shared_libs: ["libvndksupport"],
+        },
+    },
 }
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index 4f8d7c5..caf7cf8 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -18,6 +18,10 @@
 
 #include <hidl/HidlBinderSupport.h>
 
+#include <InternalStatic.h>  // TODO(b/69122224): remove this include, for getOrCreateCachedBinder
+#include <android/hidl/base/1.0/BpHwBase.h>
+#include <hwbinder/IPCThreadState.h>
+
 // C includes
 #include <inttypes.h>
 #include <unistd.h>
@@ -46,6 +50,30 @@
     return mRecipient;
 }
 
+const size_t hidl_handle::kOffsetOfNativeHandle = offsetof(hidl_handle, mHandle);
+static_assert(hidl_handle::kOffsetOfNativeHandle == 0, "wrong offset");
+
+status_t readEmbeddedFromParcel(const hidl_handle& /* handle */,
+        const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
+    const native_handle_t *handle;
+    status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
+            parentHandle,
+            parentOffset + hidl_handle::kOffsetOfNativeHandle,
+            &handle);
+
+    return _hidl_err;
+}
+
+status_t writeEmbeddedToParcel(const hidl_handle &handle,
+        Parcel *parcel, size_t parentHandle, size_t parentOffset) {
+    status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
+            handle.getNativeHandle(),
+            parentHandle,
+            parentOffset + hidl_handle::kOffsetOfNativeHandle);
+
+    return _hidl_err;
+}
+
 const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
 const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
 static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset");
@@ -53,6 +81,7 @@
 
 status_t readEmbeddedFromParcel(const hidl_memory& memory,
         const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
+    // TODO(b/111883309): Invoke readEmbeddedFromParcel(hidl_handle, ...).
     const native_handle_t *handle;
     ::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
             parentHandle,
@@ -81,6 +110,7 @@
 
 status_t writeEmbeddedToParcel(const hidl_memory &memory,
         Parcel *parcel, size_t parentHandle, size_t parentOffset) {
+    // TODO(b/111883309): Invoke writeEmbeddedToParcel(hidl_handle, ...).
     status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
             memory.handle(),
             parentHandle,
@@ -206,11 +236,63 @@
     return status;
 }
 
+sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
+    if (ifacePtr == nullptr) {
+        return nullptr;
+    }
+
+    if (ifacePtr->isRemote()) {
+        using ::android::hidl::base::V1_0::BpHwBase;
+
+        BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
+        BpHwRefBase* bpRefBase = static_cast<BpHwRefBase*>(bpBase);
+        return sp<IBinder>(bpRefBase->remote());
+    }
+
+    std::string descriptor = details::getDescriptor(ifacePtr);
+    if (descriptor.empty()) {
+        // interfaceDescriptor fails
+        return nullptr;
+    }
+
+    // for get + set
+    std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
+
+    wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
+    sp<IBinder> sBnObj = wBnObj.promote();
+
+    if (sBnObj == nullptr) {
+        auto func = details::getBnConstructorMap().get(descriptor, nullptr);
+        if (!func) {
+            // TODO(b/69122224): remove this static variable when prebuilts updated
+            func = details::gBnConstructorMap.get(descriptor, nullptr);
+        }
+        LOG_ALWAYS_FATAL_IF(func == nullptr, "%s gBnConstructorMap returned null for %s", __func__,
+                            descriptor.c_str());
+
+        sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
+        LOG_ALWAYS_FATAL_IF(sBnObj == nullptr, "%s Bn constructor function returned null for %s",
+                            __func__, descriptor.c_str());
+
+        details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
+    }
+
+    return sBnObj;
+}
+
+static bool gThreadPoolConfigured = false;
+
 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
-    ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
+    status_t ret = ProcessState::self()->setThreadPoolConfiguration(
+        maxThreads, callerWillJoin /*callerJoinsPool*/);
+    LOG_ALWAYS_FATAL_IF(ret != OK, "Could not setThreadPoolConfiguration: %d", ret);
+
+    gThreadPoolConfigured = true;
 }
 
 void joinBinderRpcThreadpool() {
+    LOG_ALWAYS_FATAL_IF(!gThreadPoolConfigured,
+                        "HIDL joinRpcThreadpool without calling configureRpcThreadPool.");
     IPCThreadState::self()->joinThreadPool();
 }
 
@@ -218,9 +300,7 @@
     int fd;
     int err = IPCThreadState::self()->setupPolling(&fd);
 
-    if (err != OK) {
-        ALOGE("Failed to setup binder polling: %d (%s)", err, strerror(err));
-    }
+    LOG_ALWAYS_FATAL_IF(err != OK, "Failed to setup binder polling: %d (%s)", err, strerror(err));
 
     return err == OK ? fd : -1;
 }
@@ -229,5 +309,9 @@
     return IPCThreadState::self()->handlePolledCommands();
 }
 
+void addPostCommandTask(const std::function<void(void)> task) {
+    IPCThreadState::self()->addPostCommandTask(task);
+}
+
 }  // namespace hardware
 }  // namespace android
diff --git a/transport/HidlPassthroughSupport.cpp b/transport/HidlPassthroughSupport.cpp
index e5eb164..ff68a1e 100644
--- a/transport/HidlPassthroughSupport.cpp
+++ b/transport/HidlPassthroughSupport.cpp
@@ -16,6 +16,8 @@
 
 #include <hidl/HidlPassthroughSupport.h>
 
+#include <InternalStatic.h>  // TODO(b/69122224): remove this include, for tryWrap
+
 #include <hidl/HidlTransportUtils.h>
 #include <hidl/Static.h>
 
@@ -28,6 +30,7 @@
 static sp<IBase> tryWrap(const std::string& descriptor, sp<IBase> iface) {
     auto func = getBsConstructorMap().get(descriptor, nullptr);
     if (!func) {
+        // TODO(b/69122224): remove this when prebuilts don't reference it
         func = gBsConstructorMap.get(descriptor, nullptr);
     }
     if (func) {
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
index d0871f6..591ccba 100644
--- a/transport/HidlTransportSupport.cpp
+++ b/transport/HidlTransportSupport.cpp
@@ -13,9 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <hidl/HidlTransportSupport.h>
 #include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Static.h>
 
+#include <android-base/logging.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 
 namespace android {
@@ -41,24 +43,47 @@
 bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
                            int policy, int priority) {
     if (service->isRemote()) {
-        ALOGE("Can't set scheduler policy on remote service.");
+        LOG(ERROR) << "Can't set scheduler policy on remote service.";
         return false;
     }
 
-    if (policy != SCHED_NORMAL && policy != SCHED_FIFO && policy != SCHED_RR) {
-        ALOGE("Invalid scheduler policy %d", policy);
-        return false;
+    switch (policy) {
+        case SCHED_NORMAL: {
+            if (priority < -20 || priority > 19) {
+                LOG(ERROR) << "Invalid priority for SCHED_NORMAL: " << priority;
+                return false;
+            }
+        } break;
+        case SCHED_RR:
+        case SCHED_FIFO: {
+            if (priority < 1 || priority > 99) {
+                LOG(ERROR) << "Invalid priority for " << policy << " policy: " << priority;
+                return false;
+            }
+        } break;
+        default: {
+            LOG(ERROR) << "Invalid scheduler policy " << policy;
+            return false;
+        }
     }
 
-    if (policy == SCHED_NORMAL && (priority < -20 || priority > 19)) {
-        ALOGE("Invalid priority for SCHED_NORMAL: %d", priority);
-        return false;
-    } else if (priority < 1 || priority > 99) {
-        ALOGE("Invalid priority for real-time policy: %d", priority);
-        return false;
-    }
+    // Due to ABI considerations, IBase cannot have a destructor to clean this up.
+    // So, because this API is so infrequently used, (expected to be usually only
+    // one time for a process, but it can be more), we are cleaning it up here.
+    // TODO(b/37794345): if ever we update the HIDL ABI for launches in an Android
+    // release in the meta-version sense, we should remove this.
+    std::unique_lock<std::mutex> lock = details::gServicePrioMap.lock();
 
-    details::gServicePrioMap.set(service, { policy, priority });
+    std::vector<wp<::android::hidl::base::V1_0::IBase>> toDelete;
+    for (const auto& kv : details::gServicePrioMap) {
+        if (kv.first.promote() == nullptr) {
+            toDelete.push_back(kv.first);
+        }
+    }
+    for (const auto& k : toDelete) {
+        details::gServicePrioMap.eraseLocked(k);
+    }
+    details::gServicePrioMap.setLocked(service, {policy, priority});
 
     return true;
 }
diff --git a/transport/InternalStatic.h b/transport/InternalStatic.h
new file mode 100644
index 0000000..b0fefa9
--- /dev/null
+++ b/transport/InternalStatic.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+// This file is for legacy static variables that we are trying to get rid of.
+// TODO(b/69122224): remove this file
+
+#ifndef ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
+#define ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
+
+#include <hidl/Static.h>
+
+namespace android {
+namespace hardware {
+namespace details {
+
+// deprecated; use getBnConstructorMap instead.
+extern BnConstructorMap gBnConstructorMap;
+// deprecated; use getBsConstructorMap instead.
+extern BsConstructorMap gBsConstructorMap;
+
+}  // namespace details
+}  // namespace hardware
+}  // namespace android
+
+#endif
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 01f83bd..40a7ff5 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -33,17 +33,23 @@
 #include <hidl/HidlTransportUtils.h>
 #include <hidl/ServiceManagement.h>
 #include <hidl/Status.h>
+#include <utils/SystemClock.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/Parcel.h>
+#if !defined(__ANDROID_RECOVERY__)
 #include <vndksupport/linker.h>
+#endif
 
-#include <android/hidl/manager/1.1/IServiceManager.h>
-#include <android/hidl/manager/1.1/BpHwServiceManager.h>
-#include <android/hidl/manager/1.1/BnHwServiceManager.h>
+#include <android/hidl/manager/1.2/BnHwServiceManager.h>
+#include <android/hidl/manager/1.2/BpHwServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
 
 #define RE_COMPONENT    "[a-zA-Z_][a-zA-Z_0-9]*"
 #define RE_PATH         RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
@@ -51,23 +57,24 @@
 
 using android::base::WaitForProperty;
 
+using ::android::hidl::base::V1_0::IBase;
 using IServiceManager1_0 = android::hidl::manager::V1_0::IServiceManager;
 using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager;
-using android::hidl::manager::V1_0::IServiceNotification;
-using android::hidl::manager::V1_1::BpHwServiceManager;
-using android::hidl::manager::V1_1::BnHwServiceManager;
+using IServiceManager1_2 = android::hidl::manager::V1_2::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
 
 namespace android {
 namespace hardware {
 
-namespace details {
-extern Mutex gDefaultServiceManagerLock;
-extern sp<android::hidl::manager::V1_1::IServiceManager> gDefaultServiceManager;
-}  // namespace details
-
 static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
 
-void waitForHwServiceManager() {
+#if defined(__ANDROID_RECOVERY__)
+static constexpr bool kIsRecovery = true;
+#else
+static constexpr bool kIsRecovery = false;
+#endif
+
+static void waitForHwServiceManager() {
     using std::literals::chrono_literals::operator""s;
 
     while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
@@ -75,17 +82,7 @@
     }
 }
 
-bool endsWith(const std::string &in, const std::string &suffix) {
-    return in.size() >= suffix.size() &&
-           in.substr(in.size() - suffix.size()) == suffix;
-}
-
-bool startsWith(const std::string &in, const std::string &prefix) {
-    return in.size() >= prefix.size() &&
-           in.substr(0, prefix.size()) == prefix;
-}
-
-std::string binaryName() {
+static std::string binaryName() {
     std::ifstream ifs("/proc/self/cmdline");
     std::string cmdline;
     if (!ifs.is_open()) {
@@ -101,27 +98,27 @@
     return cmdline;
 }
 
-std::string packageWithoutVersion(const std::string& packageAndVersion) {
+static 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) {
+static void tryShortenProcessName(const std::string& descriptor) {
     const static std::string kTasks = "/proc/self/task/";
 
     // make sure that this binary name is in the same package
     std::string processName = binaryName();
 
     // e.x. android.hardware.foo is this package
-    if (!startsWith(packageWithoutVersion(processName), packageWithoutVersion(packageAndVersion))) {
+    if (!base::StartsWith(packageWithoutVersion(processName), packageWithoutVersion(descriptor))) {
         return;
     }
 
-    // e.x. android.hardware.module.foo@1.2 -> foo@1.2
-    size_t lastDot = packageAndVersion.rfind('.');
+    // e.x. android.hardware.module.foo@1.2::IFoo -> foo@1.2
+    size_t lastDot = descriptor.rfind('.');
     if (lastDot == std::string::npos) return;
-    size_t secondDot = packageAndVersion.rfind('.', lastDot - 1);
+    size_t secondDot = descriptor.rfind('.', lastDot - 1);
     if (secondDot == std::string::npos) return;
 
     std::string newName = processName.substr(secondDot + 1, std::string::npos);
@@ -145,7 +142,7 @@
         fs >> oldComm;
 
         // don't rename if it already has an explicit name
-        if (startsWith(packageAndVersion, oldComm)) {
+        if (base::StartsWith(descriptor, oldComm)) {
             fs.seekg(0, fs.beg);
             fs << newName;
         }
@@ -154,22 +151,69 @@
 
 namespace details {
 
-void onRegistration(const std::string &packageName,
-                    const std::string& /* interfaceName */,
-                    const std::string& /* instanceName */) {
-    tryShortenProcessName(packageName);
+/*
+ * Returns the age of the current process by reading /proc/self/stat and comparing starttime to the
+ * current time. This is useful for measuring how long it took a HAL to register itself.
+ */
+static long getProcessAgeMs() {
+    constexpr const int PROCFS_STAT_STARTTIME_INDEX = 21;
+    std::string content;
+    android::base::ReadFileToString("/proc/self/stat", &content, false);
+    auto stats = android::base::Split(content, " ");
+    if (stats.size() <= PROCFS_STAT_STARTTIME_INDEX) {
+        LOG(INFO) << "Could not read starttime from /proc/self/stat";
+        return -1;
+    }
+    const std::string& startTimeString = stats[PROCFS_STAT_STARTTIME_INDEX];
+    static const int64_t ticksPerSecond = sysconf(_SC_CLK_TCK);
+    const int64_t uptime = android::uptimeMillis();
+
+    unsigned long long startTimeInClockTicks = 0;
+    if (android::base::ParseUint(startTimeString, &startTimeInClockTicks)) {
+        long startTimeMs = 1000ULL * startTimeInClockTicks / ticksPerSecond;
+        return uptime - startTimeMs;
+    }
+    return -1;
+}
+
+static void onRegistrationImpl(const std::string& descriptor, const std::string& instanceName) {
+    long halStartDelay = getProcessAgeMs();
+    if (halStartDelay >= 0) {
+        // The "start delay" printed here is an estimate of how long it took the HAL to go from
+        // process creation to registering itself as a HAL.  Actual start time could be longer
+        // because the process might not have joined the threadpool yet, so it might not be ready to
+        // process transactions.
+        LOG(INFO) << "Registered " << descriptor << "/" << instanceName << " (start delay of "
+                  << halStartDelay << "ms)";
+    }
+
+    tryShortenProcessName(descriptor);
+}
+
+void onRegistration(const std::string& packageName, const std::string& interfaceName,
+                    const std::string& instanceName) {
+    return onRegistrationImpl(packageName + "::" + interfaceName, instanceName);
 }
 
 }  // details
 
 sp<IServiceManager1_0> defaultServiceManager() {
-    return defaultServiceManager1_1();
+    return defaultServiceManager1_2();
 }
 sp<IServiceManager1_1> defaultServiceManager1_1() {
+    return defaultServiceManager1_2();
+}
+sp<IServiceManager1_2> defaultServiceManager1_2() {
+    using android::hidl::manager::V1_2::BnHwServiceManager;
+    using android::hidl::manager::V1_2::BpHwServiceManager;
+
+    static std::mutex gDefaultServiceManagerLock;
+    static sp<IServiceManager1_2> gDefaultServiceManager;
+
     {
-        AutoMutex _l(details::gDefaultServiceManagerLock);
-        if (details::gDefaultServiceManager != nullptr) {
-            return details::gDefaultServiceManager;
+        std::lock_guard<std::mutex> _l(gDefaultServiceManagerLock);
+        if (gDefaultServiceManager != nullptr) {
+            return gDefaultServiceManager;
         }
 
         if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
@@ -180,18 +224,18 @@
 
         waitForHwServiceManager();
 
-        while (details::gDefaultServiceManager == nullptr) {
-            details::gDefaultServiceManager =
-                    fromBinder<IServiceManager1_1, BpHwServiceManager, BnHwServiceManager>(
-                        ProcessState::self()->getContextObject(nullptr));
-            if (details::gDefaultServiceManager == nullptr) {
+        while (gDefaultServiceManager == nullptr) {
+            gDefaultServiceManager =
+                fromBinder<IServiceManager1_2, BpHwServiceManager, BnHwServiceManager>(
+                    ProcessState::self()->getContextObject(nullptr));
+            if (gDefaultServiceManager == nullptr) {
                 LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
                 sleep(1);
             }
         }
     }
 
-    return details::gDefaultServiceManager;
+    return gDefaultServiceManager;
 }
 
 std::vector<std::string> search(const std::string &path,
@@ -206,8 +250,7 @@
     while ((dp = readdir(dir.get())) != nullptr) {
         std::string name = dp->d_name;
 
-        if (startsWith(name, prefix) &&
-                endsWith(name, suffix)) {
+        if (base::StartsWith(name, prefix) && base::EndsWith(name, suffix)) {
             results.push_back(name);
         }
     }
@@ -226,6 +269,11 @@
 }
 
 static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
+    if (kIsRecovery) {
+        // No hwservicemanager in recovery.
+        return;
+    }
+
     sp<IServiceManager1_0> binderizedManager = defaultServiceManager();
     if (binderizedManager == nullptr) {
         LOG(WARNING) << "Could not registerReference for "
@@ -309,8 +357,12 @@
 
         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,
-                                          halLibPathVndkSp, HAL_LIBRARY_PATH_SYSTEM};
+        std::vector<std::string> paths = {
+            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, halLibPathVndkSp,
+#ifndef __ANDROID_VNDK__
+            HAL_LIBRARY_PATH_SYSTEM,
+#endif
+        };
 
 #ifdef LIBHIDL_TARGET_DEBUGGABLE
         const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
@@ -341,10 +393,12 @@
             for (const std::string &lib : libs) {
                 const std::string fullPath = path + lib;
 
-                if (path == HAL_LIBRARY_PATH_SYSTEM) {
+                if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
                     handle = dlopen(fullPath.c_str(), dlMode);
                 } else {
+#if !defined(__ANDROID_RECOVERY__)
                     handle = android_load_sphal_library(fullPath.c_str(), dlMode);
+#endif
                 }
 
                 if (handle == nullptr) {
@@ -436,11 +490,21 @@
             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,
-              halLibPathVndkSp64.c_str(), HAL_LIBRARY_PATH_SYSTEM_64BIT}},
+             {
+                 HAL_LIBRARY_PATH_ODM_64BIT, HAL_LIBRARY_PATH_VENDOR_64BIT,
+                 halLibPathVndkSp64.c_str(),
+#ifndef __ANDROID_VNDK__
+                 HAL_LIBRARY_PATH_SYSTEM_64BIT,
+#endif
+             }},
             {Arch::IS_32BIT,
-             {HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT,
-              halLibPathVndkSp32.c_str(), HAL_LIBRARY_PATH_SYSTEM_32BIT}}};
+             {
+                 HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT,
+                 halLibPathVndkSp32.c_str(),
+#ifndef __ANDROID_VNDK__
+                 HAL_LIBRARY_PATH_SYSTEM_32BIT,
+#endif
+             }}};
         std::map<std::string, InstanceDebugInfo> map;
         for (const auto &pair : sAllPaths) {
             Arch arch = pair.first;
@@ -563,7 +627,7 @@
         return Void();
     }
 
-    void wait() {
+    void wait(bool timeout) {
         using std::literals::chrono_literals::operator""s;
 
         if (!mRegisteredForNotifications) {
@@ -574,7 +638,7 @@
         }
 
         std::unique_lock<std::mutex> lock(mMutex);
-        while(true) {
+        do {
             mCondition.wait_for(lock, 1s, [this]{
                 return mRegistered;
             });
@@ -583,9 +647,8 @@
                 break;
             }
 
-            LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName
-                         << ". Waiting another...";
-        }
+            LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName;
+        } while (!timeout);
     }
 
     // Be careful when using this; after calling reset(), you must always try to retrieve
@@ -615,7 +678,7 @@
    private:
     const std::string mInterfaceName;
     const std::string mInstanceName;
-    const sp<IServiceManager1_1>& mSm;
+    sp<IServiceManager1_1> mSm;
     std::mutex mMutex;
     std::condition_variable mCondition;
     bool mRegistered = false;
@@ -626,7 +689,7 @@
 void waitForHwService(
         const std::string &interface, const std::string &instanceName) {
     sp<Waiter> waiter = new Waiter(interface, instanceName, defaultServiceManager1_1());
-    waiter->wait();
+    waiter->wait(false /* timeout */);
     waiter->done();
 }
 
@@ -665,24 +728,30 @@
                                                              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<IServiceManager1_1> sm;
+    Transport transport = Transport::EMPTY;
+    if (kIsRecovery) {
+        transport = Transport::PASSTHROUGH;
+    } else {
+        sm = defaultServiceManager1_1();
+        if (sm == nullptr) {
+            ALOGE("getService: defaultServiceManager() is null");
+            return nullptr;
+        }
+
+        Return<Transport> transportRet = sm->getTransport(descriptor, instance);
+
+        if (!transportRet.isOk()) {
+            ALOGE("getService: defaultServiceManager()->getTransport returns %s",
+                  transportRet.description().c_str());
+            return nullptr;
+        }
+        transport = transportRet;
     }
 
-    Return<Transport> transportRet = sm->getTransport(descriptor, instance);
-
-    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);
 
@@ -736,7 +805,7 @@
 
         if (waiter != nullptr) {
             ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
-            waiter->wait();
+            waiter->wait(true /* timeout */);
         }
     }
 
@@ -758,7 +827,33 @@
     return nullptr;
 }
 
-}; // namespace details
+status_t registerAsServiceInternal(const sp<IBase>& service, const std::string& name) {
+    if (service == nullptr) {
+        return UNEXPECTED_NULL;
+    }
 
-}; // namespace hardware
-}; // namespace android
+    sp<IServiceManager1_2> sm = defaultServiceManager1_2();
+    if (sm == nullptr) {
+        return INVALID_OPERATION;
+    }
+
+    bool registered = false;
+    Return<void> ret = service->interfaceChain([&](const auto& chain) {
+        registered = sm->addWithChain(name.c_str(), service, chain).withDefault(false);
+    });
+
+    if (!ret.isOk()) {
+        LOG(ERROR) << "Could not retrieve interface chain: " << ret.description();
+    }
+
+    if (registered) {
+        onRegistrationImpl(getDescriptor(service.get()), name);
+    }
+
+    return registered ? OK : UNKNOWN_ERROR;
+}
+
+} // namespace details
+
+} // namespace hardware
+} // namespace android
diff --git a/transport/Static.cpp b/transport/Static.cpp
index cbe6add..45ae27c 100644
--- a/transport/Static.cpp
+++ b/transport/Static.cpp
@@ -17,6 +17,7 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
+#include <InternalStatic.h>
 #include <hidl/Static.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
@@ -26,9 +27,6 @@
 namespace hardware {
 namespace details {
 
-Mutex gDefaultServiceManagerLock;
-sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
-
 // Deprecated; kept for ABI compatibility. Use getBnConstructorMap.
 BnConstructorMap gBnConstructorMap{};
 
diff --git a/transport/allocator/1.0/default/Android.bp b/transport/allocator/1.0/default/Android.bp
index fc352c3..1fdfb26 100644
--- a/transport/allocator/1.0/default/Android.bp
+++ b/transport/allocator/1.0/default/Android.bp
@@ -21,6 +21,7 @@
         "service.cpp"
     ],
     init_rc: ["android.hidl.allocator@1.0-service.rc"],
+    vintf_fragments: ["android.hidl.allocator@1.0-service.xml"],
 
     shared_libs: [
         "android.hidl.allocator@1.0",
diff --git a/transport/allocator/1.0/default/AshmemAllocator.cpp b/transport/allocator/1.0/default/AshmemAllocator.cpp
index 0bd4f81..5cc2eea 100644
--- a/transport/allocator/1.0/default/AshmemAllocator.cpp
+++ b/transport/allocator/1.0/default/AshmemAllocator.cpp
@@ -36,8 +36,8 @@
 
     native_handle_t* handle = native_handle_create(1, 0);
     handle->data[0] = fd;
-    LOG(WARNING) << "ashmem_create_region(" << size << ") returning hidl_memory(" << handle
-            << ", " << size << ")";
+    LOG(VERBOSE) << "ashmem_create_region(" << size << ") returning hidl_memory(" << handle << ", "
+                 << size << ")";
     return hidl_memory("ashmem", handle, size);
 }
 
diff --git a/transport/allocator/1.0/default/android.hidl.allocator@1.0-service.xml b/transport/allocator/1.0/default/android.hidl.allocator@1.0-service.xml
new file mode 100644
index 0000000..5218241
--- /dev/null
+++ b/transport/allocator/1.0/default/android.hidl.allocator@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="framework">
+    <hal>
+        <name>android.hidl.allocator</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>ashmem</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/transport/allocator/1.0/vts/functional/Android.bp b/transport/allocator/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..797d3f8
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "VtsHidlAllocatorV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHidlAllocatorV1_0TargetTest.cpp"],
+    shared_libs: [
+        "libhidlmemory",
+    ],
+    static_libs: [
+        "android.hidl.allocator@1.0",
+    ],
+}
+
diff --git a/transport/allocator/1.0/vts/functional/Android.mk b/transport/allocator/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..62880ed
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/Android.mk
@@ -0,0 +1,22 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsHidlAllocatorV1_0Target
+-include test/vts/tools/build/Android.host_config.mk
diff --git a/transport/allocator/1.0/vts/functional/AndroidTest.xml b/transport/allocator/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..6ac167f
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VtsHidlAllocatorV1_0Target 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="VtsHidlAllocatorV1_0Target"/>
+        <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/VtsHidlAllocatorV1_0TargetTest/VtsHidlAllocatorV1_0TargetTest" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/VtsHidlAllocatorV1_0TargetTest/VtsHidlAllocatorV1_0TargetTest" />
+        <option name="binary-test-type" value="hal_hidl_gtest"/>
+        <option name="test-timeout" value="5m"/>
+    </test>
+</configuration>
diff --git a/transport/allocator/1.0/vts/functional/VtsHidlAllocatorV1_0TargetTest.cpp b/transport/allocator/1.0/vts/functional/VtsHidlAllocatorV1_0TargetTest.cpp
new file mode 100644
index 0000000..39ce606
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/VtsHidlAllocatorV1_0TargetTest.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+
+#define ASSERT_OK(ret) ASSERT_TRUE((ret).isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE((ret).isOk())
+
+class AllocatorEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    virtual void registerTestServices() override { registerTestService<IAllocator>(); }
+
+    static AllocatorEnvironment* instance() {
+        static AllocatorEnvironment* instance = new AllocatorEnvironment();
+        return instance;
+    };
+};
+
+class AllocatorHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        allocator = getService<IAllocator>(AllocatorEnvironment::instance());
+        ASSERT_NE(allocator, nullptr);
+    }
+
+    sp<IMemory> expectAllocateSuccess(size_t size) {
+        sp<IMemory> memory;
+        EXPECT_OK(allocator->allocate(size, [&](bool success, const hidl_memory& mem) {
+            ASSERT_TRUE(success) << "Allocate failed for size: " << size;
+            EXPECT_EQ(mem.size(), size)
+                << "Allocated " << size << " but got hidl_memory with size " << mem.size();
+            memory = mapMemory(mem);
+        }));
+        EXPECT_NE(nullptr, memory.get());
+        EXPECT_EQ(memory->getSize(), size)
+            << "Allocated " << size << " but got IMemory with size " << memory->getSize();
+        return memory;
+    }
+
+    std::vector<sp<IMemory>> expectBatchAllocateSuccess(size_t size, size_t count) {
+        std::vector<sp<IMemory>> memories;
+        memories.reserve(count);
+        EXPECT_OK(allocator->batchAllocate(
+            size, count, [&](bool success, const hidl_vec<hidl_memory>& mems) {
+                EXPECT_EQ(count, mems.size());
+
+                for (const hidl_memory& mem : mems) {
+                    ASSERT_TRUE(success) << "Allocate failed for size: " << size;
+                    EXPECT_EQ(mem.size(), size)
+                        << "Allocated " << size << " but got hidl_memory with size " << mem.size();
+                    memories.push_back(mapMemory(mem));
+                }
+            }));
+        for (const sp<IMemory>& memory : memories) {
+            EXPECT_NE(nullptr, memory.get());
+            EXPECT_EQ(memory->getSize(), size)
+                << "Allocated " << size << " but got IMemory with size " << memory->getSize();
+        }
+        return memories;
+    }
+
+    sp<IAllocator> allocator;
+};
+
+TEST_F(AllocatorHidlTest, TestAllocateSizes) {
+    for (size_t size : {1, 1023, 1024, 1025, 4096}) {
+        expectAllocateSuccess(size);
+    }
+}
+
+TEST_F(AllocatorHidlTest, TestBatchAllocateSizes) {
+    for (size_t count : {1, 1, 2, 3, 10}) {
+        for (size_t size : {1, 1023, 1024, 1025, 4096}) {
+            expectBatchAllocateSuccess(size, count);
+        }
+    }
+}
+
+TEST_F(AllocatorHidlTest, TestCommit) {
+    constexpr size_t kSize = 1337;
+
+    sp<IMemory> memory = expectAllocateSuccess(kSize);
+    for (int i = 0; i < 100; i++) {
+        EXPECT_OK(memory->read());
+        EXPECT_OK(memory->update());
+        EXPECT_OK(memory->commit());
+
+        EXPECT_OK(memory->read());
+        EXPECT_OK(memory->commit());
+
+        EXPECT_OK(memory->update());
+        EXPECT_OK(memory->commit());
+    }
+
+    for (int i = 0; i < kSize; i++) {
+        EXPECT_OK(memory->readRange(i, kSize));
+        EXPECT_OK(memory->updateRange(i, kSize));
+        EXPECT_OK(memory->commit());
+
+        EXPECT_OK(memory->readRange(i, kSize));
+        EXPECT_OK(memory->commit());
+
+        EXPECT_OK(memory->updateRange(i, kSize));
+        EXPECT_OK(memory->commit());
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(AllocatorEnvironment::instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    AllocatorEnvironment::instance()->init(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/transport/base/1.0/Android.bp b/transport/base/1.0/Android.bp
index bd2ae49..00d2f2b 100644
--- a/transport/base/1.0/Android.bp
+++ b/transport/base/1.0/Android.bp
@@ -3,7 +3,6 @@
 hidl_interface {
     name: "android.hidl.base@1.0",
     root: "android.hidl",
-    core_interface: true,
     vndk: {
         enabled: true,
     },
diff --git a/transport/base/1.0/IBase.hal b/transport/base/1.0/IBase.hal
index e862ec8..22007f0 100644
--- a/transport/base/1.0/IBase.hal
+++ b/transport/base/1.0/IBase.hal
@@ -87,7 +87,10 @@
     linkToDeath(death_recipient recipient, uint64_t cookie) generates (bool success);
 
     /*
-     * Unregisters a previously registered death recipient.
+     * Unregisters the registered death recipient. If this service was registered
+     * multiple times with the same exact death recipient, this unlinks the most
+     * recently registered one.
+     *
      * @param recipient a previously registered hidl_death_recipient callback
      * @return success whether the death recipient was unregistered successfully.
      */
diff --git a/transport/current.txt b/transport/current.txt
index a48233c..3794dfe 100644
--- a/transport/current.txt
+++ b/transport/current.txt
@@ -22,3 +22,6 @@
 
 # ABI preserving changes to HALs during Android Q
 fcde1d0788066a62d5766f4dc19d4c1ec76967d5ddb636f59ccc66603460bcf8 android.hidl.manager@1.0::IServiceNotification
+
+# Clarification for b/67503915
+ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c android.hidl.base@1.0::IBase
diff --git a/transport/include/hidl/ConcurrentMap.h b/transport/include/hidl/ConcurrentMap.h
index 4066869..54c1a32 100644
--- a/transport/include/hidl/ConcurrentMap.h
+++ b/transport/include/hidl/ConcurrentMap.h
@@ -76,6 +76,14 @@
         return iter->second;
     }
 
+    size_type eraseLocked(const K& k) { return mMap.erase(k); }
+
+    // the concurrent map must be locked in order to iterate over it
+    iterator begin() { return mMap.begin(); }
+    iterator end() { return mMap.end(); }
+    const_iterator begin() const { return mMap.begin(); }
+    const_iterator end() const { return mMap.end(); }
+
    private:
     mutable std::mutex mMutex;
     std::map<K, V> mMap;
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 9759af1..a098805 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -24,11 +24,10 @@
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportUtils.h>
 #include <hidl/MQDescriptor.h>
-#include <hidl/Static.h>
 #include <hwbinder/IBinder.h>
-#include <hwbinder/IPCThreadState.h>
 #include <hwbinder/Parcel.h>
-#include <hwbinder/ProcessState.h>
+#include <log/log.h>  // TODO(b/65843592): remove. Too many users depending on this transitively.
+
 // Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
 // etc. to interact with Parcel.
 
@@ -49,6 +48,14 @@
     wp<::android::hidl::base::V1_0::IBase> mBase;
 };
 
+// ---------------------- hidl_handle
+
+status_t readEmbeddedFromParcel(const hidl_handle &handle,
+        const Parcel &parcel, size_t parentHandle, size_t parentOffset);
+
+status_t writeEmbeddedToParcel(const hidl_handle &handle,
+        Parcel *parcel, size_t parentHandle, size_t parentOffset);
+
 // ---------------------- hidl_memory
 
 status_t readEmbeddedFromParcel(const hidl_memory &memory,
@@ -301,6 +308,10 @@
 
 // ---------------------- support for casting interfaces
 
+// Constructs a binder for this interface and caches it. If it has already been created
+// then it returns it.
+sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr);
+
 // Construct a smallest possible binder from the given interface.
 // If it is remote, then its remote() will be retrieved.
 // Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
@@ -310,43 +321,7 @@
           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) {
-        return nullptr;
-    }
-    if (ifacePtr->isRemote()) {
-        return ::android::hardware::IInterface::asBinder(
-            static_cast<BpInterface<IType>*>(ifacePtr));
-    } else {
-        std::string myDescriptor = details::getDescriptor(ifacePtr);
-        if (myDescriptor.empty()) {
-            // interfaceDescriptor fails
-            return nullptr;
-        }
-
-        // for get + set
-        std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
-
-        wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
-        sp<IBinder> sBnObj = wBnObj.promote();
-
-        if (sBnObj == nullptr) {
-            auto func = details::getBnConstructorMap().get(myDescriptor, nullptr);
-            if (!func) {
-                func = details::gBnConstructorMap.get(myDescriptor, nullptr);
-                if (!func) {
-                    return nullptr;
-                }
-            }
-
-            sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
-
-            if (sBnObj != nullptr) {
-                details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
-            }
-        }
-
-        return sBnObj;
-    }
+    return getOrCreateCachedBinder(ifacePtr);
 }
 
 template <typename IType, typename ProxyType, typename StubType>
@@ -374,6 +349,8 @@
 int setupBinderPolling();
 status_t handleBinderPoll();
 
+void addPostCommandTask(const std::function<void(void)> task);
+
 }  // namespace hardware
 }  // namespace android
 
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 4df156b..a962034 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -28,21 +28,21 @@
 namespace manager {
 namespace V1_0 {
     struct IServiceManager;
-}; // namespace V1_0
+}  // namespace V1_0
 namespace V1_1 {
-    struct IServiceManager;
-}; // namespace V1_0
-}; // namespace manager
-}; // namespace hidl
+struct IServiceManager;
+}  // namespace V1_1
+namespace V1_2 {
+struct IServiceManager;
+}  // namespace V1_2
+}  // namespace manager
+}  // namespace hidl
 
 namespace hardware {
 
 namespace details {
-// e.x.: android.hardware.foo@1.0, IFoo, default
-void onRegistration(const std::string &packageName,
-                    const std::string &interfaceName,
-                    const std::string &instanceName);
 
+// Will not attempt to start a lazy HAL
 // e.x.: android.hardware.foo@1.0::IFoo, default
 void waitForHwService(const std::string &interface, const std::string &instanceName);
 
@@ -57,12 +57,16 @@
 sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
                                                              const std::string& instance,
                                                              bool retry, bool getStub);
-};
+
+status_t registerAsServiceInternal(const sp<::android::hidl::base::V1_0::IBase>& service,
+                                   const std::string& name);
+}  // namespace details
 
 // These functions are for internal use by hidl. If you want to get ahold
 // of an interface, the best way to do this is by calling IFoo::getService()
 sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
 sp<::android::hidl::manager::V1_1::IServiceManager> defaultServiceManager1_1();
+sp<::android::hidl::manager::V1_2::IServiceManager> defaultServiceManager1_2();
 sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
 sp<::android::hidl::manager::V1_1::IServiceManager> getPassthroughServiceManager1_1();
 
@@ -77,8 +81,8 @@
     details::preloadPassthroughService(I::descriptor);
 }
 
-}; // namespace hardware
-}; // namespace android
+} // namespace hardware
+} // namespace android
 
 #endif // ANDROID_HARDWARE_ISERVICE_MANAGER_H
 
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 0522e44..b50c173 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -17,6 +17,9 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
+#ifndef ANDROID_HARDWARE_HIDL_STATIC_H
+#define ANDROID_HARDWARE_HIDL_STATIC_H
+
 #include <functional>
 
 #include <android/hidl/base/1.0/IBase.h>
@@ -44,8 +47,6 @@
 // For HidlBinderSupport and autogenerated code
 // value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
 // returns sp<IBinder>
-// deprecated; use getBnConstructorMap instead.
-extern BnConstructorMap gBnConstructorMap;
 BnConstructorMap& getBnConstructorMap();
 
 using BsConstructorMap = ConcurrentMap<std::string,
@@ -53,9 +54,9 @@
 // For HidlPassthroughSupport and autogenerated code
 // value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
 // returns sp<IBase>
-// deprecated; use getBsConstructorMap instead.
-extern BsConstructorMap gBsConstructorMap;
 BsConstructorMap& getBsConstructorMap();
 }  // namespace details
 }  // namespace hardware
 }  // namespace android
+
+#endif
diff --git a/transport/manager/1.0/Android.bp b/transport/manager/1.0/Android.bp
index e4a120b..869c58e 100644
--- a/transport/manager/1.0/Android.bp
+++ b/transport/manager/1.0/Android.bp
@@ -3,7 +3,6 @@
 hidl_interface {
     name: "android.hidl.manager@1.0",
     root: "android.hidl",
-    core_interface: true,
     vndk: {
         enabled: true,
     },
diff --git a/transport/manager/1.1/Android.bp b/transport/manager/1.1/Android.bp
index cde68a7..407dfa3 100644
--- a/transport/manager/1.1/Android.bp
+++ b/transport/manager/1.1/Android.bp
@@ -3,7 +3,6 @@
 hidl_interface {
     name: "android.hidl.manager@1.1",
     root: "android.hidl",
-    core_interface: true,
     vndk: {
         enabled: true,
     },
diff --git a/transport/manager/1.2/Android.bp b/transport/manager/1.2/Android.bp
new file mode 100644
index 0000000..3f02f78
--- /dev/null
+++ b/transport/manager/1.2/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hidl.manager@1.2",
+    root: "android.hidl",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IClientCallback.hal",
+        "IServiceManager.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+        "android.hidl.manager@1.0",
+        "android.hidl.manager@1.1",
+    ],
+    gen_java: true,
+}
+
diff --git a/transport/manager/1.2/IClientCallback.hal b/transport/manager/1.2/IClientCallback.hal
new file mode 100644
index 0000000..1189e44
--- /dev/null
+++ b/transport/manager/1.2/IClientCallback.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.hidl.manager@1.2;
+
+interface IClientCallback {
+    /**
+     * This is called when there is a transition between having >= 1 clients and having 0 clients
+     * (or vice versa).
+     *
+     * @param registered binder 'server' registered with IServiceManager's registerClientCallback
+     * @param hasClients whether there are currently clients
+     *     true - when there are >= 1 clients. This must be called as soon as IServiceManager::get
+     *         is called (no race).
+     *     false - when there are 0 clients. This may be delayed if it is thought that another
+     *         may be used again soon.
+     */
+    oneway onClients(interface registered, bool hasClients);
+};
diff --git a/transport/manager/1.2/IServiceManager.hal b/transport/manager/1.2/IServiceManager.hal
new file mode 100644
index 0000000..ae3fdfd
--- /dev/null
+++ b/transport/manager/1.2/IServiceManager.hal
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package android.hidl.manager@1.2;
+
+import @1.1::IServiceManager;
+
+import IClientCallback;
+
+interface IServiceManager extends @1.1::IServiceManager {
+    // TODO(b/66921961): additional functionality for the next release:
+    // - Better notifications (onRegistration will contain the interface)
+    // - Method to list interfaces in the manifest (for b/76108617, since if they are
+    //     lazy, they will no longer show up in listByInterface)
+
+    /**
+     * Adds a callback that must be called when the specified server has no clients.
+     *
+     * If the service has clients at the time of registration, the callback is called with
+     * hasClients true. After that, it is called based on the changes in clientele.
+     *
+     * @param server non-null service waiting to have no clients
+     * @param cb non-null callback to call when there are no clients
+     * @return success
+     *     true on success
+     *     false if either
+     *      - the server or cb parameters are null
+     *      - this is called by a process other than the server process
+     */
+    registerClientCallback(interface server, IClientCallback cb) generates (bool success);
+
+    /**
+     * Removes a callback previously registered with registerClientCallback.
+     *
+     * If server is null, then this must remove the cb from all matching services.
+     *
+     * @param server service registered with registerClientCallback
+     * @param cb non-null callback to remove
+     * @return success
+     *     true if the server(s) have been removed
+     *     false if cb is null or if the client callback or server could not be found
+     */
+    unregisterClientCallback(interface server, IClientCallback cb) generates (bool success);
+
+    /**
+     * Exactly the same as @1.0::IServiceManager.add, but the interfaceChain of the service is
+     * provided in the same call.
+     *
+     * @param name Instance name. Must also be used to retrieve service.
+     * @param service Handle to registering service.
+     * @param chain service->interfaceChain
+     *
+     * @return success Whether or not the service was registered.
+     */
+    addWithChain(string name, interface service, vec<string> chain) generates (bool success);
+};
diff --git a/transport/safe_union/1.0/Android.bp b/transport/safe_union/1.0/Android.bp
new file mode 100644
index 0000000..0fc2305
--- /dev/null
+++ b/transport/safe_union/1.0/Android.bp
@@ -0,0 +1,17 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hidl.safe_union@1.0",
+    root: "android.hidl",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+    ],
+    types: [
+        "Monostate",
+    ],
+    gen_java: true,
+}
+
diff --git a/transport/safe_union/1.0/types.hal b/transport/safe_union/1.0/types.hal
new file mode 100644
index 0000000..bc3dbc2
--- /dev/null
+++ b/transport/safe_union/1.0/types.hal
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package android.hidl.safe_union@1.0;
+
+/**
+ * Unit type easily available to be used with safe_union.
+ *
+ * Example usage:
+ *
+ * safe_union MaybeFoo {
+ *     Monostate no_init;
+ *     Foo foo;
+ * };
+ */
+struct Monostate {};
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
index fcb1613..d706cf6 100644
--- a/transport/token/1.0/utils/Android.bp
+++ b/transport/token/1.0/utils/Android.bp
@@ -19,6 +19,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
 
     srcs: [
         "HybridInterface.cpp",
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
index 984555e..595c2e3 100644
--- a/transport/token/1.0/utils/include/hidl/HybridInterface.h
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -240,6 +240,10 @@
         onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     if (code == GET_HAL_TOKEN) {
+        if (!data.enforceInterface(BaseInterface::getInterfaceDescriptor())) {
+            return BAD_TYPE;
+        }
+
         HalToken token;
         bool result;
         result = createHalToken(mBase, &token);
diff --git a/update-makefiles.sh b/update-makefiles.sh
index fd0a23c..cf13c83 100755
--- a/update-makefiles.sh
+++ b/update-makefiles.sh
@@ -5,7 +5,9 @@
     android.hidl.base@1.0
     android.hidl.manager@1.0
     android.hidl.manager@1.1
+    android.hidl.manager@1.2
     android.hidl.memory@1.0
+    android.hidl.safe_union@1.0
     android.hidl.token@1.0
 )
 
diff --git a/vintfdata/Android.mk b/vintfdata/Android.mk
index bc7a55a..232ef6f 100644
--- a/vintfdata/Android.mk
+++ b/vintfdata/Android.mk
@@ -17,6 +17,10 @@
 LOCAL_PATH := $(call my-dir)
 
 FRAMEWORK_MANIFEST_INPUT_FILES := $(LOCAL_PATH)/manifest.xml
+# TODO(b/110487738): replace with vintf_fragment
+ifdef USE_VR_FLINGER
+  FRAMEWORK_MANIFEST_INPUT_FILES += $(LOCAL_PATH)/manifest_vr_hwc.xml
+endif
 ifdef DEVICE_FRAMEWORK_MANIFEST_FILE
   FRAMEWORK_MANIFEST_INPUT_FILES += $(DEVICE_FRAMEWORK_MANIFEST_FILE)
 endif
@@ -62,15 +66,6 @@
 
 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
@@ -78,7 +73,7 @@
 	PLATFORM_SYSTEMSDK_VERSIONS="$(PLATFORM_SYSTEMSDK_VERSIONS)" \
 		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
 		-i $(call normalize-path-list,$(PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES)) \
-		-o $@ $(PRIVATE_FLAGS)
+		-o $@
 
 LOCAL_PREBUILT_MODULE_FILE := $(GEN)
 include $(BUILD_PREBUILT)
@@ -86,4 +81,4 @@
 
 VINTF_VNDK_VERSION :=
 FRAMEWORK_MANIFEST_INPUT_FILES :=
-DEVICE_MATRIX_INPUT_FILE :=
+DEVICE_MATRIX_INPUT_FILE :=
\ No newline at end of file
diff --git a/vintfdata/manifest.xml b/vintfdata/manifest.xml
index 51d68eb..27919d3 100644
--- a/vintfdata/manifest.xml
+++ b/vintfdata/manifest.xml
@@ -2,22 +2,13 @@
     <hal>
         <name>android.hidl.manager</name>
         <transport>hwbinder</transport>
-        <version>1.1</version>
+        <version>1.2</version>
         <interface>
             <name>IServiceManager</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal>
-        <name>android.hidl.allocator</name>
-        <transport>hwbinder</transport>
-        <version>1.0</version>
-        <interface>
-            <name>IAllocator</name>
-            <instance>ashmem</instance>
-        </interface>
-    </hal>
-    <hal>
         <name>android.hidl.memory</name>
         <transport arch="32+64">passthrough</transport>
         <version>1.0</version>
@@ -80,25 +71,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal>
-      <name>android.hardware.graphics.composer</name>
-      <transport>hwbinder</transport>
-      <version>2.1</version>
-      <interface>
-          <name>IComposer</name>
-          <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
deleted file mode 100644
index b4060f0..0000000
--- a/vintfdata/manifest_healthd_exclude.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<!--
-    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>
diff --git a/vintfdata/manifest_vr_hwc.xml b/vintfdata/manifest_vr_hwc.xml
new file mode 100644
index 0000000..1068cac
--- /dev/null
+++ b/vintfdata/manifest_vr_hwc.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="framework">
+    <hal>
+      <name>android.hardware.graphics.composer</name>
+      <transport>hwbinder</transport>
+      <version>2.1</version>
+      <interface>
+          <name>IComposer</name>
+          <instance>vr</instance>
+      </interface>
+    </hal>
+</manifest>