Merge "Add android.frameworks.sensorservice to system/manifest.xml"
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index 4f88be5..36ffae8 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -32,7 +32,7 @@
 namespace hardware {
 namespace details {
 
-void hidl_log_base::logAlwaysFatal(const char *message) const {
+void logAlwaysFatal(const char *message) {
     LOG(FATAL) << message;
 }
 
diff --git a/base/include/hidl/HidlInternal.h b/base/include/hidl/HidlInternal.h
index c0250fb..6c0d8df 100644
--- a/base/include/hidl/HidlInternal.h
+++ b/base/include/hidl/HidlInternal.h
@@ -28,12 +28,9 @@
 namespace hardware {
 namespace details {
 
-// hidl_log_base is a base class that templatized
-// classes implemented in a header can inherit from,
-// to avoid creating dependencies on liblog.
-struct hidl_log_base {
-    void logAlwaysFatal(const char *message) const;
-};
+//Templated classes can use the below method
+//to avoid creating dependencies on liblog.
+void logAlwaysFatal(const char *message);
 
 // HIDL client/server code should *NOT* use this class.
 //
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 14afce3..f6ce09b 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -288,7 +288,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 template<typename T>
-struct hidl_vec : private details::hidl_log_base {
+struct hidl_vec {
     hidl_vec()
         : mBuffer(NULL),
           mSize(0),
@@ -308,7 +308,7 @@
     hidl_vec(const std::initializer_list<T> list)
             : mOwnsBuffer(true) {
         if (list.size() > UINT32_MAX) {
-            logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
+            details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
         }
         mSize = static_cast<uint32_t>(list.size());
         mBuffer = new T[mSize];
@@ -339,7 +339,7 @@
         }
         mBuffer = data;
         if (size > UINT32_MAX) {
-            logAlwaysFatal("external vector size exceeds 2^32 elements.");
+            details::logAlwaysFatal("external vector size exceeds 2^32 elements.");
         }
         mSize = static_cast<uint32_t>(size);
         mOwnsBuffer = shouldOwn;
@@ -433,7 +433,7 @@
 
     void resize(size_t size) {
         if (size > UINT32_MAX) {
-            logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
+            details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
         }
         T *newBuffer = new T[size];
 
@@ -818,7 +818,7 @@
 
 ///////////////////// toString functions
 
-namespace details {
+std::string toString(const void *t);
 
 // toString alias for numeric types
 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
@@ -826,6 +826,8 @@
     return std::to_string(t);
 }
 
+namespace details {
+
 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
 inline std::string toHexString(T t, bool prefix = true) {
     std::ostringstream os;
@@ -844,8 +846,48 @@
     return toHexString(static_cast<int32_t>(t), prefix);
 }
 
-inline std::string toString(const void *t, bool prefix = true) {
-    return toHexString(reinterpret_cast<uintptr_t>(t), prefix);
+template<typename Array>
+std::string arrayToString(const Array &a, size_t size);
+
+template<size_t SIZE1>
+std::string arraySizeToString() {
+    return std::string{"["} + toString(SIZE1) + "]";
+}
+
+template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string arraySizeToString() {
+    return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
+}
+
+template<typename T, size_t SIZE1>
+std::string toString(details::const_accessor<T, SIZE1> a) {
+    return arrayToString(a, SIZE1);
+}
+
+template<typename Array>
+std::string arrayToString(const Array &a, size_t size) {
+    using android::hardware::toString;
+    std::string os;
+    os += "{";
+    for (size_t i = 0; i < size; ++i) {
+        if (i > 0) {
+            os += ", ";
+        }
+        os += toString(a[i]);
+    }
+    os += "}";
+    return os;
+}
+
+template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
+std::string toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
+    return arrayToString(a, SIZE1);
+}
+
+}  //namespace details
+
+inline std::string toString(const void *t) {
+    return details::toHexString(reinterpret_cast<uintptr_t>(t));
 }
 
 // debug string dump. There will be quotes around the string!
@@ -868,68 +910,27 @@
     return std::string{"death_recipient@"} + toString(dr.get());
 }
 
-template<typename Array>
-std::string arrayToString(const Array &a, size_t size);
-
 // debug string dump, assuming that toString(T) is defined.
 template<typename T>
 std::string toString(const hidl_vec<T> &a) {
     std::string os;
     os += "[" + toString(a.size()) + "]";
-    os += arrayToString(a, a.size());
+    os += details::arrayToString(a, a.size());
     return os;
 }
 
-template<size_t SIZE1>
-std::string arraySizeToString() {
-    return std::string{"["} + toString(SIZE1) + "]";
-}
-
-template<typename T, size_t SIZE1>
-std::string toString(const_accessor<T, SIZE1> a) {
-    return arrayToString(a, SIZE1);
-}
-
 template<typename T, size_t SIZE1>
 std::string toString(const hidl_array<T, SIZE1> &a) {
-    return arraySizeToString<SIZE1>()
-            + toString(const_accessor<T, SIZE1>(a.data()));
-}
-
-template<size_t SIZE1, size_t SIZE2, size_t... SIZES>
-std::string arraySizeToString() {
-    return std::string{"["} + toString(SIZE1) + "]" + arraySizeToString<SIZE2, SIZES...>();
-}
-
-
-template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
-std::string toString(const_accessor<T, SIZE1, SIZE2, SIZES...> a) {
-    return arrayToString(a, SIZE1);
+    return details::arraySizeToString<SIZE1>()
+            + details::toString(details::const_accessor<T, SIZE1>(a.data()));
 }
 
 template<typename T, size_t SIZE1, size_t SIZE2, size_t... SIZES>
 std::string toString(const hidl_array<T, SIZE1, SIZE2, SIZES...> &a) {
-    return arraySizeToString<SIZE1, SIZE2, SIZES...>()
-            + toString(const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
+    return details::arraySizeToString<SIZE1, SIZE2, SIZES...>()
+            + details::toString(details::const_accessor<T, SIZE1, SIZE2, SIZES...>(a.data()));
 }
 
-template<typename Array>
-std::string arrayToString(const Array &a, size_t size) {
-    std::string os;
-    os += "{";
-    for (size_t i = 0; i < size; ++i) {
-        if (i > 0) {
-            os += ", ";
-        }
-        os += toString(a[i]);
-    }
-    os += "}";
-    return os;
-}
-
-}  // namespace details
-
-
 }  // namespace hardware
 }  // namespace android
 
diff --git a/base/include/hidl/MQDescriptor.h b/base/include/hidl/MQDescriptor.h
index 90b30d1..bf2f8a4 100644
--- a/base/include/hidl/MQDescriptor.h
+++ b/base/include/hidl/MQDescriptor.h
@@ -19,6 +19,7 @@
 
 #include <android-base/macros.h>
 #include <cutils/native_handle.h>
+#include <hidl/HidlInternal.h>
 #include <hidl/HidlSupport.h>
 #include <utils/Log.h>
 
@@ -116,7 +117,9 @@
     //TODO(b/34160777) Identify a better solution that supports remoting.
     static inline size_t alignToWordBoundary(size_t length) {
         constexpr size_t kAlignmentSize = 64;
-        LOG_ALWAYS_FATAL_IF(kAlignmentSize % __WORDSIZE != 0, "Incompatible word size");
+        if (kAlignmentSize % __WORDSIZE != 0) {
+            details::logAlwaysFatal("Incompatible word size");
+        }
         return (length + kAlignmentSize/8 - 1) & ~(kAlignmentSize/8 - 1U);
     }
 
@@ -161,8 +164,9 @@
       mFlags(flavor) {
     mGrantors.resize(grantors.size());
     for (size_t i = 0; i < grantors.size(); ++i) {
-        LOG_ALWAYS_FATAL_IF(isAlignedToWordBoundary(grantors[i].offset) == false,
-                            "Grantor offsets need to be aligned");
+        if (isAlignedToWordBoundary(grantors[i].offset) == false) {
+            details::logAlwaysFatal("Grantor offsets need to be aligned");
+        }
         mGrantors[i] = grantors[i];
     }
 }
@@ -246,7 +250,6 @@
 template<typename T, MQFlavor flavor>
 int32_t MQDescriptor<T, flavor>::getFlags() const { return mFlags; }
 
-namespace details {
 template<typename T, MQFlavor flavor>
 std::string toString(const MQDescriptor<T, flavor> &q) {
     std::string os;
@@ -263,7 +266,6 @@
        + ", .quantum = " + toString(q.getQuantum()) + "}";
     return os;
 }
-}  // namespace details
 
 }  // namespace hardware
 }  // namespace android
diff --git a/manifest.xml b/manifest.xml
index 1fc8bd2..8dc9304 100644
--- a/manifest.xml
+++ b/manifest.xml
@@ -1,5 +1,3 @@
-<!-- TODO(b/35434793): move to frameworks/interfaces -->
-
 <manifest version="1.0">
     <hal>
         <name>android.hidl.manager</name>
diff --git a/transport/Android.bp b/transport/Android.bp
index 1c1a310..f81d9c6 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -20,6 +20,7 @@
     "memory/1.0",
     "memory/1.0/default",
     "token/1.0",
+    "token/1.0/utils",
 ]
 
 cc_library_shared {
diff --git a/transport/HidlPassthroughSupport.cpp b/transport/HidlPassthroughSupport.cpp
index 981a139..3a7f6dc 100644
--- a/transport/HidlPassthroughSupport.cpp
+++ b/transport/HidlPassthroughSupport.cpp
@@ -16,8 +16,8 @@
 #include <hidl/HidlPassthroughSupport.h>
 
 #include <hidl/HidlSupport.h>
-#include <hidl/Static.h>
 #include <hidl/HidlTransportUtils.h>
+#include <hidl/Static.h>
 
 namespace android {
 namespace hardware {
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 15abb92..d425591 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -26,7 +26,6 @@
 
 #include <hidl/HidlBinderSupport.h>
 #include <hidl/ServiceManagement.h>
-#include <hidl/Static.h>
 #include <hidl/Status.h>
 
 #include <android-base/logging.h>
@@ -51,25 +50,34 @@
 namespace android {
 namespace hardware {
 
+namespace details {
+extern Mutex gDefaultServiceManagerLock;
+extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
+}  // namespace details
+
 sp<IServiceManager> defaultServiceManager() {
 
-    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
-    if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
-        // HwBinder not available on this device or not accessible to
-        // this process.
-        return nullptr;
-    }
     {
-        AutoMutex _l(gDefaultServiceManagerLock);
-        while (gDefaultServiceManager == NULL) {
-            gDefaultServiceManager = fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
-                ProcessState::self()->getContextObject(NULL));
-            if (gDefaultServiceManager == NULL)
+        AutoMutex _l(details::gDefaultServiceManagerLock);
+        if (details::gDefaultServiceManager != NULL) {
+            return details::gDefaultServiceManager;
+        }
+        if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
+            // HwBinder not available on this device or not accessible to
+            // this process.
+            return nullptr;
+        }
+        while (details::gDefaultServiceManager == NULL) {
+            details::gDefaultServiceManager =
+                    fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
+                        ProcessState::self()->getContextObject(NULL));
+            if (details::gDefaultServiceManager == NULL) {
                 sleep(1);
+            }
         }
     }
 
-    return gDefaultServiceManager;
+    return details::gDefaultServiceManager;
 }
 
 std::vector<std::string> search(const std::string &path,
diff --git a/transport/Static.cpp b/transport/Static.cpp
index d5b335e..496c8f0 100644
--- a/transport/Static.cpp
+++ b/transport/Static.cpp
@@ -19,8 +19,12 @@
 
 #include <hidl/Static.h>
 
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <utils/Mutex.h>
+
 namespace android {
 namespace hardware {
+namespace details {
 
 Mutex gDefaultServiceManagerLock;
 sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
@@ -31,5 +35,6 @@
 ConcurrentMap<std::string, std::function<sp<::android::hidl::base::V1_0::IBase>(void *)>>
         gBsConstructorMap;
 
-}   // namespace hardware
-}   // namespace android
+}  // namespace details
+}  // namespace hardware
+}  // namespace android
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 8b98021..86ac74c 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -328,7 +328,7 @@
             // interfaceDescriptor fails
             return nullptr;
         }
-        auto func = gBnConstructorMap.get(myDescriptor, nullptr);
+        auto func = details::gBnConstructorMap.get(myDescriptor, nullptr);
         if (!func) {
             return nullptr;
         }
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 04b1729..e6c9139 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -17,31 +17,29 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
+#include <functional>
+
 #include <android/hidl/base/1.0/IBase.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl/ConcurrentMap.h>
 #include <hwbinder/IBinder.h>
 #include <utils/StrongPointer.h>
-#include <utils/Mutex.h>
 
 namespace android {
 namespace hardware {
+namespace details {
 
-// For ServiceManagement.cpp
-extern Mutex gDefaultServiceManagerLock;
-extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
-
-// For HidlBinderSupport
+// 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;
 
-// For HidlPassthroughSupport
+// 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;
 
-}   // namespace hardware
-}   // namespace android
+}  // namespace details
+}  // namespace hardware
+}  // namespace android
diff --git a/transport/memory/1.0/IMemory.hal b/transport/memory/1.0/IMemory.hal
index 66f37b3..14dcfb1 100644
--- a/transport/memory/1.0/IMemory.hal
+++ b/transport/memory/1.0/IMemory.hal
@@ -34,7 +34,20 @@
     updateRange(uint64_t start, uint64_t length);
 
     /**
-     * Notify that you are done modifying this memory.
+     * Notify that you are about to start reading all of this memory.
+     */
+    read();
+
+    /**
+     * Notify that you are about to read the specific range.
+     *
+     * @param start Offset from start of buffer about to be read.
+     * @param length Number of bytes to be read.
+     */
+    readRange(uint64_t start, uint64_t length);
+
+    /**
+     * Notify that you are done reading and/or writing this memory.
      *
      * Must commit all previous update's and updateAll's.
      */
diff --git a/transport/memory/1.0/default/AshmemMemory.cpp b/transport/memory/1.0/default/AshmemMemory.cpp
index 912b724..0729608 100644
--- a/transport/memory/1.0/default/AshmemMemory.cpp
+++ b/transport/memory/1.0/default/AshmemMemory.cpp
@@ -46,6 +46,16 @@
     return Void();
 }
 
+Return<void> AshmemMemory::read() {
+    // NOOP (since non-remoted memory)
+    return Void();
+}
+
+Return<void> AshmemMemory::readRange(uint64_t /* start */, uint64_t /* length */) {
+    // NOOP (since non-remoted memory)
+    return Void();
+}
+
 Return<void> AshmemMemory::commit() {
     // NOOP (since non-remoted memory)
     return Void();
diff --git a/transport/memory/1.0/default/AshmemMemory.h b/transport/memory/1.0/default/AshmemMemory.h
index 825d74e..cf2d543 100644
--- a/transport/memory/1.0/default/AshmemMemory.h
+++ b/transport/memory/1.0/default/AshmemMemory.h
@@ -44,6 +44,8 @@
     // Methods from ::android::hidl::memory::V1_0::IMemory follow.
     Return<void> update() override;
     Return<void> updateRange(uint64_t start, uint64_t length) override;
+    Return<void> read() override;
+    Return<void> readRange(uint64_t start, uint64_t length) override;
     Return<void> commit() override;
     Return<void*> getPointer() override;
     Return<uint64_t> getSize() override;
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
new file mode 100644
index 0000000..0360d99
--- /dev/null
+++ b/transport/token/1.0/utils/Android.bp
@@ -0,0 +1,41 @@
+// 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: "android.hidl.token@1.0-utils",
+
+    srcs: [
+        "HybridInterface.cpp",
+    ],
+
+    shared_libs: [
+        "libutils",
+        "libbinder",
+        "liblog",
+        "libhidlbase",
+        "android.hidl.token@1.0",
+    ],
+
+    export_shared_lib_headers: [
+        "libbinder",
+        "libhidlbase",
+    ],
+
+    export_include_dirs: [
+        "include"
+    ],
+
+    clang: true,
+}
+
diff --git a/transport/token/1.0/utils/HybridInterface.cpp b/transport/token/1.0/utils/HybridInterface.cpp
new file mode 100644
index 0000000..f28446e
--- /dev/null
+++ b/transport/token/1.0/utils/HybridInterface.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "HybridInterface"
+
+#include <utils/Log.h>
+#include <hidl/HybridInterface.h>
+#include <hidl/HidlSupport.h>
+#include <android/hidl/token/1.0/ITokenManager.h>
+
+namespace android {
+
+using ::android::hidl::token::V1_0::ITokenManager;
+
+namespace {
+
+std::mutex gTokenManagerLock;
+sp<ITokenManager> gTokenManager = nullptr;
+
+struct TokenManagerDeathRecipient : public hardware::hidl_death_recipient {
+    void serviceDied(uint64_t, const wp<HInterface>&) {
+        std::lock_guard<std::mutex> lock(gTokenManagerLock);
+        gTokenManager = nullptr;
+    }
+};
+
+sp<TokenManagerDeathRecipient> gTokenManagerDeathRecipient =
+    new TokenManagerDeathRecipient();
+
+bool isBadTokenManager() {
+    if (gTokenManager != nullptr) {
+        return false;
+    }
+    gTokenManager = ITokenManager::getService();
+    if (gTokenManager == nullptr) {
+        ALOGE("Cannot retrieve TokenManager.");
+        return true;
+    }
+    auto transaction = gTokenManager->linkToDeath(
+            gTokenManagerDeathRecipient, 0);
+    if (!transaction.isOk()) {
+        ALOGE("Cannot observe TokenManager's death.");
+        gTokenManager = nullptr;
+        return true;
+    }
+    return false;
+}
+
+template <typename ReturnType>
+bool isBadTransaction(hardware::Return<ReturnType>& transaction) {
+    if (transaction.isOk()) {
+        return false;
+    }
+    ALOGE("TokenManager's transaction error: %s",
+            transaction.description().c_str());
+    gTokenManager->unlinkToDeath(gTokenManagerDeathRecipient).isOk();
+    gTokenManager = nullptr;
+    return true;
+}
+
+} // unnamed namespace
+
+sp<HInterface> retrieveHalInterface(const HalToken& token) {
+    hardware::Return<sp<HInterface> > transaction(nullptr);
+    {
+        std::lock_guard<std::mutex> lock(gTokenManagerLock);
+        if (isBadTokenManager()) {
+            return nullptr;
+        }
+        transaction = gTokenManager->get(token);
+        if (isBadTransaction(transaction)) {
+            return nullptr;
+        }
+    }
+    return static_cast<sp<HInterface> >(transaction);
+}
+
+bool createHalToken(const sp<HInterface>& interface, HalToken* token) {
+    hardware::Return<HalToken> transaction(false);
+    {
+        std::lock_guard<std::mutex> lock(gTokenManagerLock);
+        if (isBadTokenManager()) {
+            return false;
+        }
+        transaction = gTokenManager->createToken(interface);
+        if (isBadTransaction(transaction)) {
+            return false;
+        }
+    }
+    *token = static_cast<HalToken>(transaction);
+    return true;
+}
+
+bool deleteHalToken(const HalToken& token) {
+    hardware::Return<bool> transaction(false);
+    {
+        std::lock_guard<std::mutex> lock(gTokenManagerLock);
+        if (isBadTokenManager()) {
+            return false;
+        }
+        transaction = gTokenManager->unregister(token);
+        if (isBadTransaction(transaction)) {
+            return false;
+        }
+    }
+    return static_cast<bool>(transaction);
+}
+
+}; // namespace android
+
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
new file mode 100644
index 0000000..42d3734
--- /dev/null
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -0,0 +1,338 @@
+/*
+ * 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_HYBRIDINTERFACE_H
+#define ANDROID_HYBRIDINTERFACE_H
+
+#include <vector>
+#include <mutex>
+
+#include <binder/Parcel.h>
+#include <hidl/HidlSupport.h>
+
+/**
+ * Hybrid Interfaces
+ * =================
+ *
+ * A hybrid interface is a binder interface that
+ * 1. is implemented both traditionally and as a wrapper around a hidl
+ *    interface, and allows querying whether the underlying instance comes from
+ *    a hidl interface or not; and
+ * 2. allows efficient calls to a hidl interface (if the underlying instance
+ *    comes from a hidl interface) by automatically creating the wrapper in the
+ *    process that calls it.
+ *
+ * Terminology:
+ * - `HalToken`: The type for a "token" of a hidl interface. This is defined to
+ *   be compatible with `ITokenManager.hal`.
+ * - `HInterface`: The base type for a hidl interface. Currently, it is defined
+ *   as `::android::hidl::base::V1_0::IBase`.
+ * - `HALINTERFACE`: The hidl interface that will be sent through binders.
+ * - `INTERFACE`: The binder interface that will be the wrapper of
+ *   `HALINTERFACE`. `INTERFACE` is supposed to be somewhat similar to
+ *   `HALINTERFACE`.
+ *
+ * To demonstrate how this is done, here is an example. Suppose `INTERFACE` is
+ * `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are:
+ * 1. Use DECLARE_HYBRID_META_INTERFACE instead of DECLARE_META_INTERFACE in the
+ *    definition of `IFoo`. The usage is
+ *        DECLARE_HYBRID_META_INTERFACE(IFoo, HFoo)
+ *    inside the body of `IFoo`.
+ * 2. Create a converter class that derives from
+ *    `H2BConverter<HFoo, IFoo, BnFoo>`. Let us call this `H2BFoo`.
+ * 3. Add the following constructor in `H2BFoo` that call the corresponding
+ *    constructors in `H2BConverter`:
+ *        H2BFoo(const sp<HalInterface>& base) : CBase(base) {}
+ *    Note: `CBase = H2BConverter<HFoo, IFoo, BnFoo>` and `HalInterface = HFoo`
+ *    are member typedefs of `H2BConverter<HFoo, IFoo, BnFoo>`, so the above
+ *    line can be copied into `H2BFoo`.
+ * 4. Implement `IFoo` in `H2BFoo` on top of `HFoo`. `H2BConverter` provides a
+ *    protected `mBase` of type `sp<HFoo>` that can be used to access the `HFoo`
+ *    instance. (There is also a public function named `getHalInterface()` that
+ *    returns `mBase`.)
+ * 5. Create a hardware proxy class that derives from
+ *    `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot
+ *    deviate. See step 8 below.)
+ * 6. Add the following constructor to `HpFoo`:
+ *        HpFoo(const sp<IBinder>& base): PBase(base) {}
+ *    Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is
+ *    equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be
+ *    copied verbatim into `HpFoo`.
+ * 7. Delegate all functions in `HpFoo` that come from `IFoo` except
+ *    `getHalInterface` to the protected member `mBase`,
+ *    which is defined in `HpInterface<BpFoo, H2BFoo>` (hence in `HpFoo`) with
+ *    type `IFoo`. (There is also a public function named `getBaseInterface()`
+ *    that returns `mBase`.)
+ * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for INTERFACE by
+ *    `IMPLEMENT_HYBRID_META_INTERFACE`. Note that this macro relies on the
+ *    exact naming of `HpFoo`, where `Foo` comes from the interface name `IFoo`.
+ *    An example usage is
+ *        IMPLEMENT_HYBRID_META_INTERFACE(IFoo, HFoo, "example.interface.foo");
+ *
+ * `GETTOKEN` Template Argument
+ * ============================
+ *
+ * Following the instructions above, `H2BConverter` and `HpInterface` would use
+ * `transact()` to send over tokens, with `code` (the first argument of
+ * `transact()`) equal to `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`. If this
+ * value clashes with other values already in use in the `Bp` class, it can be
+ * changed by supplying the last optional template argument to `H2BConverter`
+ * and `HpInterface`.
+ *
+ */
+
+namespace android {
+
+typedef uint64_t HalToken;
+typedef ::android::hidl::base::V1_0::IBase HInterface;
+
+constexpr uint32_t DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE =
+        B_PACK_CHARS('_', 'G', 'H', 'T');
+
+sp<HInterface> retrieveHalInterface(const HalToken& token);
+bool createHalToken(const sp<HInterface>& interface, HalToken* token);
+bool deleteHalToken(const HalToken& token);
+
+template <
+        typename HINTERFACE,
+        typename INTERFACE,
+        typename BNINTERFACE,
+        uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
+class H2BConverter : public BNINTERFACE {
+public:
+    typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN> CBase; // Converter Base
+    typedef INTERFACE BaseInterface;
+    typedef HINTERFACE HalInterface;
+    static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
+
+    H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
+    virtual status_t onTransact(uint32_t code,
+            const Parcel& data, Parcel* reply, uint32_t flags = 0);
+    virtual sp<HalInterface> getHalInterface() { return mBase; }
+    HalInterface* getBaseInterface() { return mBase.get(); }
+    virtual status_t linkToDeath(
+            const sp<IBinder::DeathRecipient>& recipient,
+            void* cookie = NULL,
+            uint32_t flags = 0);
+    virtual status_t unlinkToDeath(
+            const wp<IBinder::DeathRecipient>& recipient,
+            void* cookie = NULL,
+            uint32_t flags = 0,
+            wp<IBinder::DeathRecipient>* outRecipient = NULL);
+
+protected:
+    sp<HalInterface> mBase;
+    struct Obituary : public hardware::hidl_death_recipient {
+        wp<IBinder::DeathRecipient> recipient;
+        void* cookie;
+        uint32_t flags;
+        wp<IBinder> who;
+        Obituary(
+                const wp<IBinder::DeathRecipient>& r,
+                void* c, uint32_t f,
+                const wp<IBinder>& w) :
+            recipient(r), cookie(c), flags(f), who(w) {
+        }
+        Obituary(const Obituary& o) :
+            recipient(o.recipient),
+            cookie(o.cookie),
+            flags(o.flags),
+            who(o.who) {
+        }
+        Obituary& operator=(const Obituary& o) {
+            recipient = o.recipient;
+            cookie = o.cookie;
+            flags = o.flags;
+            who = o.who;
+            return *this;
+        }
+        void serviceDied(uint64_t, const wp<HInterface>&) override {
+            sp<IBinder::DeathRecipient> dr = recipient.promote();
+            if (dr != nullptr) {
+                dr->binderDied(who);
+            }
+        }
+    };
+    std::mutex mObituariesLock;
+    std::vector<sp<Obituary> > mObituaries;
+};
+
+template <
+        typename BPINTERFACE,
+        typename CONVERTER,
+        uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
+class HpInterface : public CONVERTER::BaseInterface {
+public:
+    typedef HpInterface<BPINTERFACE, CONVERTER, GETTOKEN> PBase; // Proxy Base
+    typedef typename CONVERTER::BaseInterface BaseInterface;
+    typedef typename CONVERTER::HalInterface HalInterface;
+    static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
+
+    explicit HpInterface(const sp<IBinder>& impl);
+    virtual sp<HalInterface> getHalInterface() { return mHal; }
+    BaseInterface* getBaseInterface() { return mBase.get(); }
+
+protected:
+    IBinder* mImpl;
+    sp<BPINTERFACE> mBp;
+    sp<BaseInterface> mBase;
+    sp<HalInterface> mHal;
+    IBinder* onAsBinder() override { return mImpl; }
+};
+
+// ----------------------------------------------------------------------
+
+#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, HAL)                   \
+    static const ::android::String16 descriptor;                        \
+    static ::android::sp<I##INTERFACE> asInterface(                     \
+            const ::android::sp<::android::IBinder>& obj);              \
+    virtual const ::android::String16& getInterfaceDescriptor() const;  \
+    I##INTERFACE();                                                     \
+    virtual ~I##INTERFACE();                                            \
+    virtual sp<HAL> getHalInterface();                                  \
+
+
+#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, HAL, NAME)           \
+    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
+    const ::android::String16&                                          \
+            I##INTERFACE::getInterfaceDescriptor() const {              \
+        return I##INTERFACE::descriptor;                                \
+    }                                                                   \
+    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
+            const ::android::sp<::android::IBinder>& obj)               \
+    {                                                                   \
+        ::android::sp<I##INTERFACE> intr;                               \
+        if (obj != NULL) {                                              \
+            intr = static_cast<I##INTERFACE*>(                          \
+                obj->queryLocalInterface(                               \
+                        I##INTERFACE::descriptor).get());               \
+            if (intr == NULL) {                                         \
+                intr = new Hp##INTERFACE(obj);                          \
+            }                                                           \
+        }                                                               \
+        return intr;                                                    \
+    }                                                                   \
+    I##INTERFACE::I##INTERFACE() { }                                    \
+    I##INTERFACE::~I##INTERFACE() { }                                   \
+    sp<HAL> I##INTERFACE::getHalInterface() { return nullptr; }         \
+
+// ----------------------------------------------------------------------
+
+template <
+        typename HINTERFACE,
+        typename INTERFACE,
+        typename BNINTERFACE,
+        uint32_t GETTOKEN>
+status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
+        onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    if (code == GET_HAL_TOKEN) {
+        HalToken token;
+        bool result;
+        result = createHalToken(mBase, &token);
+        if (!result) {
+            ALOGE("H2BConverter: Failed to create HAL token.");
+        }
+        reply->writeBool(result);
+        reply->writeUint64(token);
+        return NO_ERROR;
+    }
+    return BNINTERFACE::onTransact(code, data, reply, flags);
+}
+
+template <
+        typename HINTERFACE,
+        typename INTERFACE,
+        typename BNINTERFACE,
+        uint32_t GETTOKEN>
+status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
+        linkToDeath(
+        const sp<IBinder::DeathRecipient>& recipient,
+        void* cookie, uint32_t flags) {
+    LOG_ALWAYS_FATAL_IF(recipient == NULL,
+            "linkToDeath(): recipient must be non-NULL");
+    {
+        std::lock_guard<std::mutex> lock(mObituariesLock);
+        mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
+        if (!mBase->linkToDeath(mObituaries.back(), 0)) {
+           return DEAD_OBJECT;
+        }
+    }
+    return NO_ERROR;
+}
+
+template <
+        typename HINTERFACE,
+        typename INTERFACE,
+        typename BNINTERFACE,
+        uint32_t GETTOKEN>
+status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
+        unlinkToDeath(
+        const wp<IBinder::DeathRecipient>& recipient,
+        void* cookie, uint32_t flags,
+        wp<IBinder::DeathRecipient>* outRecipient) {
+    std::lock_guard<std::mutex> lock(mObituariesLock);
+    for (auto i = mObituaries.begin(); i != mObituaries.end(); ++i) {
+        if ((flags = (*i)->flags) && (
+                (recipient == (*i)->recipient) ||
+                ((recipient == nullptr) && (cookie == (*i)->cookie)))) {
+            if (outRecipient != nullptr) {
+                *outRecipient = (*i)->recipient;
+            }
+            bool success = mBase->unlinkToDeath(*i);
+            mObituaries.erase(i);
+            return success ? NO_ERROR : DEAD_OBJECT;
+        }
+    }
+    return NAME_NOT_FOUND;
+}
+
+template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN>
+HpInterface<BPINTERFACE, CONVERTER, GETTOKEN>::HpInterface(
+        const sp<IBinder>& impl) :
+    mImpl(impl.get()),
+    mBp(new BPINTERFACE(impl)) {
+    mBase = mBp;
+    if (mImpl->remoteBinder() == nullptr) {
+        return;
+    }
+    Parcel data, reply;
+    data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor());
+    if (mImpl->transact(GET_HAL_TOKEN, data, &reply) == NO_ERROR) {
+        bool tokenCreated = reply.readBool();
+        HalToken token = reply.readUint64();
+        if (tokenCreated) {
+            sp<HInterface> hBase = retrieveHalInterface(token);
+            if (hBase != nullptr) {
+                mHal = HalInterface::castFrom(hBase);
+                if (mHal != nullptr) {
+                    mBase = new CONVERTER(mHal);
+                } else {
+                    ALOGE("HpInterface: Wrong interface type.");
+                }
+            } else {
+                ALOGE("HpInterface: Invalid HAL token.");
+            }
+            deleteHalToken(token);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_HYBRIDINTERFACE_H