Add casting and toBinder method to all interfaces.

Test: hidl_test

Bug: 32001926
Change-Id: I7080f5865b98b0eb5c5c474dbabf6f35909dfd82
diff --git a/include/hidl/HidlSupport.h b/include/hidl/HidlSupport.h
index 37c4431..826ca9f 100644
--- a/include/hidl/HidlSupport.h
+++ b/include/hidl/HidlSupport.h
@@ -22,6 +22,7 @@
 #include <dlfcn.h>
 #include <cutils/properties.h>
 #include <hidl/Status.h>
+#include <hwbinder/IBinder.h>
 #include <hwbinder/Parcel.h>
 #include <tuple>
 #include <utils/Errors.h>
@@ -584,6 +585,7 @@
 
 struct IHidlInterfaceBase : virtual public RefBase {
     virtual bool isRemote() const = 0;
+    virtual sp<::android::hardware::IBinder> toBinder() = 0;
     // HIDL reserved methods follow.
     virtual ::android::hardware::Return<void> interfaceChain(
             std::function<void(const hidl_vec<hidl_string>&)> _hidl_cb) = 0;
@@ -591,6 +593,33 @@
     static const ::android::String16 descriptor;
 };
 
+template<typename IChild, typename IParent, typename BpChild>
+sp<IChild> castInterface(sp<IParent> parent, const char *childIndicator) {
+    if (parent.get() == nullptr) {
+        // casts always succeed with nullptrs.
+        return nullptr;
+    }
+    bool canCast = false;
+    parent->interfaceChain([&](const hidl_vec<hidl_string> &allowedCastTypes) {
+        for (size_t i = 0; i < allowedCastTypes.size(); i++) {
+            if (allowedCastTypes[i] == childIndicator) {
+                canCast = true;
+                break;
+            }
+        }
+    });
+
+    if (!canCast) {
+        return sp<IChild>(nullptr); // cast failed.
+    }
+    if (parent->isRemote()) {
+        // binderized mode. Got BpChild. grab the remote and wrap it.
+        return sp<IChild>(new BpChild(parent->toBinder()));
+    }
+    // Passthrough mode. Got BnChild and BsChild.
+    return sp<IChild>(static_cast<IChild *>(parent.get()));
+}
+
 #if defined(__LP64__)
 #define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/"
 #define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/"