Merge "Introduce fromBinder() helper."
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 102fa6c..6753cb8 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "ServiceManagement"
 
+#include <hidl/HidlBinderSupport.h>
 #include <hidl/ServiceManagement.h>
 #include <hidl/Static.h>
 #include <hidl/Status.h>
@@ -28,10 +29,12 @@
 #include <unistd.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IHwServiceManager.h>
+#include <android/hidl/manager/1.0/BpServiceManager.h>
+#include <android/hidl/manager/1.0/BnServiceManager.h>
 
-using android::hidl::manager::V1_0::IHwServiceManager;
 using android::hidl::manager::V1_0::IServiceManager;
+using android::hidl::manager::V1_0::BpServiceManager;
+using android::hidl::manager::V1_0::BnServiceManager;
 
 namespace android {
 namespace hardware {
@@ -47,7 +50,7 @@
     {
         AutoMutex _l(gDefaultServiceManagerLock);
         while (gDefaultServiceManager == NULL) {
-            gDefaultServiceManager = interface_cast<IHwServiceManager>(
+            gDefaultServiceManager = fromBinder<IServiceManager, BpServiceManager, BnServiceManager>(
                 ProcessState::self()->getContextObject(NULL));
             if (gDefaultServiceManager == NULL)
                 sleep(1);
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index a596917..8c2cd61 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -18,11 +18,12 @@
 #define ANDROID_HIDL_BINDER_SUPPORT_H
 
 #include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportUtils.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Static.h>
 #include <hwbinder/IBinder.h>
 #include <hwbinder/Parcel.h>
-
+#include <android/hidl/base/1.0/BnBase.h>
 // Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
 // etc. to interact with Parcel.
 
@@ -286,14 +287,14 @@
 // 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 IHwType>
+template <typename IType, typename ProxyType>
 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<IHwType *>(ifacePtr));
+        return ::android::hardware::IInterface::asBinder(static_cast<ProxyType *>(ifacePtr));
     } else {
         std::string myDescriptor{};
         ifacePtr->interfaceChain([&](const hidl_vec<hidl_string> &types) {
@@ -313,6 +314,26 @@
     }
 }
 
+template <typename IType, typename ProxyType, typename StubType>
+sp<IType> fromBinder(const sp<IBinder>& binderIface) {
+    using ::android::hidl::base::V1_0::IBase;
+    using ::android::hidl::base::V1_0::BnBase;
+
+    if (binderIface.get() == nullptr) {
+        return nullptr;
+    }
+    if (binderIface->localBinder() == nullptr) {
+        return new ProxyType(binderIface);
+    }
+    sp<IBase> base = static_cast<BnBase*>(binderIface.get())->getImpl();
+    if (canCastInterface(base.get(), IType::descriptor)) {
+        StubType* stub = static_cast<StubType*>(binderIface.get());
+        return stub->getImpl();
+    } else {
+        return nullptr;
+    }
+}
+
 #define IMPLEMENT_SERVICE_MANAGER_INTERACTIONS(INTERFACE, PACKAGE)                       \
     ::android::sp<I##INTERFACE> I##INTERFACE::getService(                                \
             const std::string &serviceName, bool getStub)                                \
@@ -363,14 +384,13 @@
         using ::android::sp;                                                             \
         using ::android::hardware::defaultServiceManager;                                \
         using ::android::hidl::manager::V1_0::IServiceManager;                           \
-        sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this);                         \
         const sp<IServiceManager> sm = defaultServiceManager();                          \
         bool success = false;                                                            \
         ::android::hardware::Return<void> ret =                                          \
             this->interfaceChain(                                                        \
-                [&success, &sm, &serviceName, &binderIface](const auto &chain) {         \
+                [&success, &sm, &serviceName, this](const auto &chain) {                 \
                     ::android::hardware::Return<bool> addRet =                           \
-                            sm->add(chain, serviceName.c_str(), binderIface);            \
+                            sm->add(chain, serviceName.c_str(), this);                   \
                     success = addRet.isOk() && addRet;                                   \
                 });                                                                      \
         success = success && ret.getStatus().isOk();                                     \
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 1d22cb7..190227f 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -19,27 +19,20 @@
 
 #include <hidl/HidlBinderSupport.h>
 #include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportUtils.h>
 
 namespace android {
 namespace hardware {
 
 // cast the interface IParent to IChild.
 // Return nullptr if parent is null or any failure.
-template<typename IChild, typename IParent, typename BpChild, typename IHwParent>
+template<typename IChild, typename IParent, typename BpChild, typename BpParent>
 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;
-            }
-        }
-    });
+    bool canCast = canCastInterface(parent.get(), childIndicator);
 
     if (!canCast) {
         return sp<IChild>(nullptr); // cast failed.
@@ -47,7 +40,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, IHwParent>(parent)));
+        return sp<IChild>(new BpChild(toBinder<IParent, BpParent>(parent)));
     }
     // Passthrough mode. Got BnChild and BsChild.
     return sp<IChild>(static_cast<IChild *>(parent.get()));
diff --git a/transport/include/hidl/HidlTransportUtils.h b/transport/include/hidl/HidlTransportUtils.h
new file mode 100644
index 0000000..d890988
--- /dev/null
+++ b/transport/include/hidl/HidlTransportUtils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HIDL_TRANSPORT_UTILS_H
+#define ANDROID_HIDL_TRANSPORT_UTILS_H
+
+#include <android/hidl/base/1.0/IBase.h>
+
+namespace android {
+namespace hardware {
+
+/*
+ * Verifies the interface chain of 'interface' contains 'castTo'
+ */
+inline bool canCastInterface(::android::hidl::base::V1_0::IBase* interface, const char* castTo) {
+    if (interface == nullptr) {
+        return false;
+    }
+
+    bool canCast = false;
+    interface->interfaceChain([&](const hidl_vec<hidl_string> &types) {
+        for (size_t i = 0; i < types.size(); i++) {
+            if (types[i] == castTo) {
+                canCast = true;
+                break;
+            }
+        }
+    });
+    return canCast;
+}
+
+}   // namespace hardware
+}   // namespace android
+
+#endif //ANDROID_HIDL_TRANSPORT_UTILS_H