Move wrapPassthroughInternal out of headers. am: 0b1e62a08d am: c6b3fc2f41
am: 6cf1e134fc

Change-Id: Ie6e690c83ba7e4c8ae762f4f7202c3082f3fa342
diff --git a/transport/Android.bp b/transport/Android.bp
index dbbbdaf..23f6904 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -70,6 +70,7 @@
 
     srcs: [
         "HidlBinderSupport.cpp",
+        "HidlPassthroughSupport.cpp",
         "HidlTransportSupport.cpp",
         "HidlTransportUtils.cpp",
         "ServiceManagement.cpp",
diff --git a/transport/HidlPassthroughSupport.cpp b/transport/HidlPassthroughSupport.cpp
new file mode 100644
index 0000000..e101e27
--- /dev/null
+++ b/transport/HidlPassthroughSupport.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <hidl/HidlPassthroughSupport.h>
+
+#include <hidl/HidlTransportUtils.h>
+#include <hidl/Static.h>
+
+using ::android::hidl::base::V1_0::IBase;
+
+namespace android {
+namespace hardware {
+namespace details {
+
+sp<IBase> wrapPassthroughInternal(sp<IBase> iface) {
+    if (iface == nullptr || iface->isRemote()) {
+        // doesn't know how to handle it.
+        return iface;
+    }
+    std::string myDescriptor = getDescriptor(iface.get());
+    if (myDescriptor.empty()) {
+        // interfaceDescriptor fails
+        return nullptr;
+    }
+    auto func = gBsConstructorMap.get(myDescriptor, nullptr);
+    if (!func) {
+        return nullptr;
+    }
+
+    sp<IBase> base = func(static_cast<void*>(iface.get()));
+
+    // To ensure this is an instance of IType, we would normally
+    // call castFrom, but gBsConstructorMap guarantees that its
+    // result is of the appropriate type (not necessaryly BsType,
+    // but definitely a child of IType).
+    return base;
+}
+
+}  // namespace details
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/transport/include/hidl/HidlPassthroughSupport.h b/transport/include/hidl/HidlPassthroughSupport.h
index 2291060..a0f10f3 100644
--- a/transport/include/hidl/HidlPassthroughSupport.h
+++ b/transport/include/hidl/HidlPassthroughSupport.h
@@ -24,34 +24,25 @@
 namespace details {
 
 /*
- * Wrap the given interface with the smallest BsChild possible. Will return the
+ * Wrap the given interface with the lowest BsChild possible. Will return the
  * argument directly if nullptr or isRemote().
+ *
+ * Note that 'static_cast<IFoo*>(wrapPassthrough(foo).get()) is guaranteed to work'
+ * assuming that foo is an instance of IFoo.
+ *
+ * TODO(b/33754152): calling this method multiple times should not re-wrap.
+ */
+sp<::android::hidl::base::V1_0::IBase> wrapPassthroughInternal(
+    sp<::android::hidl::base::V1_0::IBase> iface);
+
+/**
+ * Helper method which provides reasonable code to wrapPassthroughInternal
+ * which can be used to call wrapPassthrough.
  */
 template <typename IType,
           typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>>
 sp<IType> wrapPassthrough(sp<IType> iface) {
-    using ::android::hidl::base::V1_0::IBase;
-
-    if (iface.get() == nullptr || iface->isRemote()) {
-        // doesn't know how to handle it.
-        return iface;
-    }
-    std::string myDescriptor = getDescriptor(iface.get());
-    if (myDescriptor.empty()) {
-        // interfaceDescriptor fails
-        return nullptr;
-    }
-    auto func = gBsConstructorMap.get(myDescriptor, nullptr);
-    if (!func) {
-        return nullptr;
-    }
-
-    sp<IBase> base = func(static_cast<void*>(iface.get()));
-
-    // would normally call castFrom, but gBsConstructorMap guarantees
-    // that its result is of the appropriate type (not necessaryly
-    // BsType, but definitely a child of IType).
-    return sp<IType>(static_cast<IType*>(base.get()));
+    return static_cast<IType*>(wrapPassthroughInternal(iface).get());
 }
 
 }  // namespace details