Allow proxies to be compared.

Also:
- removed unnecessary template parameter to toBinder
- don't create redundant BnObjects
- added comparison function for hidl interfaces

toBinder now caches the HIDL pure interface objects
in order to recreate the behavior that the binder kernel does by
itself. This means that if you pass a HIDL object out, you will
always get the same remote reference.

Test: boot a device
Test: boot a marlin
Test: hidl_test and hidl_test_java
Bug: 38348572
Bug: 32172906

Merged-In: I6453200e45eb29e685b06aab4746d9ba18c011a9
Change-Id: I6453200e45eb29e685b06aab4746d9ba18c011a9
diff --git a/transport/Static.cpp b/transport/Static.cpp
index 18cb475..784b835 100644
--- a/transport/Static.cpp
+++ b/transport/Static.cpp
@@ -32,6 +32,9 @@
 ConcurrentMap<std::string, std::function<sp<IBinder>(void *)>>
         gBnConstructorMap{};
 
+ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>
+    gBnMap{};
+
 ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap{};
 
 ConcurrentMap<std::string, std::function<sp<::android::hidl::base::V1_0::IBase>(void *)>>
diff --git a/transport/include/hidl/ConcurrentMap.h b/transport/include/hidl/ConcurrentMap.h
index 18881f1..cd55ad4 100644
--- a/transport/include/hidl/ConcurrentMap.h
+++ b/transport/include/hidl/ConcurrentMap.h
@@ -50,7 +50,19 @@
         return mMap.erase(k);
     }
 
-private:
+    std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(mMutex); }
+
+    void setLocked(K&& k, V&& v) { mMap[std::forward<K>(k)] = std::forward<V>(v); }
+
+    const V& getLocked(const K& k, const V& def) const {
+        const_iterator iter = mMap.find(k);
+        if (iter == mMap.end()) {
+            return def;
+        }
+        return iter->second;
+    }
+
+   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 6f82dbc..47ff581 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -306,25 +306,42 @@
 // Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
 // and iface is of class IChild. BnChild will be used to wrapped the given iface.
 // Return nullptr if iface is null or any failure.
-template <typename IType, typename ProxyType>
+template <typename IType>
 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<ProxyType *>(ifacePtr));
+        return ::android::hardware::IInterface::asBinder(
+            static_cast<BpInterface<IType>*>(ifacePtr));
     } else {
         std::string myDescriptor = details::getDescriptor(ifacePtr);
         if (myDescriptor.empty()) {
             // interfaceDescriptor fails
             return nullptr;
         }
-        auto func = details::gBnConstructorMap.get(myDescriptor, nullptr);
-        if (!func) {
-            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::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 sp<IBinder>(func(static_cast<void *>(ifacePtr)));
+
+        return sBnObj;
     }
 }
 
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 0c174f7..d116598 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -62,6 +62,15 @@
 bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
                            int policy, int priority);
 
+template <typename ILeft, typename IRight>
+bool interfacesEqual(sp<ILeft> left, sp<IRight> right) {
+    if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
+        return left == right;
+    }
+
+    return toBinder<ILeft>(left) == toBinder<IRight>(right);
+}
+
 namespace details {
 
 // cast the interface IParent to IChild.
@@ -72,8 +81,8 @@
 // 3. !emitError, calling into parent fails.
 // Return an error Return object if:
 // 1. emitError, calling into parent fails.
-template<typename IChild, typename IParent, typename BpChild, typename BpParent>
-Return<sp<IChild>> castInterface(sp<IParent> parent, const char *childIndicator, bool emitError) {
+template <typename IChild, typename IParent, typename BpChild>
+Return<sp<IChild>> castInterface(sp<IParent> parent, const char* childIndicator, bool emitError) {
     if (parent.get() == nullptr) {
         // casts always succeed with nullptrs.
         return nullptr;
@@ -92,7 +101,7 @@
     // TODO b/32001926 Needs to be fixed for socket mode.
     if (parent->isRemote()) {
         // binderized mode. Got BpChild. grab the remote and wrap it.
-        return sp<IChild>(new BpChild(toBinder<IParent, BpParent>(parent)));
+        return sp<IChild>(new BpChild(toBinder<IParent>(parent)));
     }
     // Passthrough mode. Got BnChild and BsChild.
     return sp<IChild>(static_cast<IChild *>(parent.get()));
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 0133ff7..63b06fe 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -22,6 +22,7 @@
 #include <android/hidl/base/1.0/IBase.h>
 #include <hidl/ConcurrentMap.h>
 #include <hwbinder/IBinder.h>
+#include <hwbinder/IInterface.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -33,14 +34,18 @@
     int prio;
 };
 
+extern ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap;
+
+// For HidlBinderSupport and autogenerated code
+extern ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>
+    gBnMap;
+
 // 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;
 
-extern ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap;
-
 // For HidlPassthroughSupport and autogenerated code
 // value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
 // returns sp<IBase>