Merge "Update HIDL makefiles."
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index 5237088..d657793 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -21,6 +21,7 @@
 
 #ifdef LIBHIDL_TARGET_DEBUGGABLE
 #include <cutils/properties.h>
+#include <dlfcn.h>
 #include <regex>
 #include <utility>
 #endif
diff --git a/base/Status.cpp b/base/Status.cpp
index 4ce26ee..8367fb8 100644
--- a/base/Status.cpp
+++ b/base/Status.cpp
@@ -13,9 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "HidlStatus"
 
 #include <hidl/Status.h>
 
+#include <android-base/logging.h>
+
 namespace android {
 namespace hardware {
 
@@ -94,5 +97,20 @@
     return stream;
 }
 
+namespace details {
+    void return_status::checkStatus() const {
+        if (!isOk()) {
+            LOG(FATAL) << "Attempted to retrieve value from failed HIDL call: " << description();
+        }
+    }
+
+    return_status::~return_status() {
+        // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
+        if (!mCheckedStatus && !isOk()) {
+            LOG(FATAL) << "Failed HIDL return status not checked: " << description();
+        }
+    }
+}  // namespace details
+
 }  // namespace hardware
 }  // namespace android
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index a8f0f55..8d43bfd 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -20,7 +20,6 @@
 #include <algorithm>
 #include <array>
 #include <dirent.h>
-#include <dlfcn.h>
 #include <iterator>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index 1be818d..13f0c2c 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -21,7 +21,6 @@
 #include <sstream>
 
 #include <android-base/macros.h>
-#include <hidl/HidlInternal.h>
 #include <utils/Errors.h>
 #include <utils/StrongPointer.h>
 
@@ -143,29 +142,19 @@
 std::ostream& operator<< (std::ostream& stream, const Status& s);
 
 namespace details {
-    class return_status : public details::hidl_log_base {
+    class return_status {
     private:
         Status mStatus {};
         mutable bool mCheckedStatus = false;
     protected:
-        void checkStatus() const {
-            if (!isOk()) {
-                logAlwaysFatal("Attempted to retrieve value from hidl service, "
-                               "but there was a transport error.");
-            }
-        }
+        void checkStatus() const;
     public:
         return_status() {}
         return_status(Status s) : mStatus(s) {}
 
         return_status(const return_status &) = default;
 
-        ~return_status() {
-            // mCheckedStatus must be checked before isOk since isOk modifies mCheckedStatus
-            if (!mCheckedStatus && !isOk()) {
-                logAlwaysFatal("HIDL return status not checked and transport error occured.");
-            }
-        }
+        ~return_status();
 
         bool isOk() const {
             mCheckedStatus = true;
diff --git a/transport/Android.bp b/transport/Android.bp
index 9b0fe2c..a5903e0 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -29,6 +29,7 @@
         "libhidlbase",
         "libhwbinder",
         "libcutils",
+        "libhidl-gen-utils"
     ],
     export_shared_lib_headers: [
         "libbase",
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 1e6e3df..418e2c0 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -21,11 +21,11 @@
 #include <hidl/Static.h>
 #include <hidl/Status.h>
 
+#include <android-base/logging.h>
+#include <dlfcn.h>
+#include <hidl-util/FQName.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/Parcel.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-
 #include <unistd.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
@@ -33,6 +33,7 @@
 #include <android/hidl/manager/1.0/BnHwServiceManager.h>
 
 using android::hidl::manager::V1_0::IServiceManager;
+using android::hidl::manager::V1_0::IServiceNotification;
 using android::hidl::manager::V1_0::BpHwServiceManager;
 using android::hidl::manager::V1_0::BnHwServiceManager;
 
@@ -60,5 +61,78 @@
     return gDefaultServiceManager;
 }
 
+struct PassthroughServiceManager : IServiceManager {
+    Return<sp<IBase>> get(const hidl_string& fqName,
+                     const hidl_string& name) override {
+        FQName iface(fqName);
+
+        if (!iface.isValid() ||
+            !iface.isFullyQualified() ||
+            iface.isIdentifier()) {
+            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
+            return nullptr;
+        }
+
+        const int dlMode = RTLD_LAZY;
+        void *handle = nullptr;
+
+        for (const std::string &path : {
+            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
+        }) {
+            const std::string lib = path + iface.getPackageAndVersion().string() + "-impl.so";
+            handle = dlopen(lib.c_str(), dlMode);
+            if (handle != nullptr) {
+                break;
+            }
+        }
+
+        if (handle == nullptr) {
+            return nullptr;
+        }
+
+        const std::string sym = "HIDL_FETCH_" + iface.name();
+
+        IBase* (*generator)(const char* name);
+        *(void **)(&generator) = dlsym(handle, sym.c_str());
+        if(!generator) {
+            return nullptr;
+        }
+        return (*generator)(name);
+    }
+
+    Return<bool> add(const hidl_vec<hidl_string>& /* interfaceChain */,
+                     const hidl_string& /* name */,
+                     const sp<IBase>& /* service */) override {
+        LOG(FATAL) << "Cannot register services with passthrough service manager.";
+        return false;
+    }
+
+    Return<void> list(list_cb /* _hidl_cb */) override {
+        // TODO: add this functionality
+        LOG(FATAL) << "Cannot list services with passthrough service manager.";
+        return Void();
+    }
+    Return<void> listByInterface(const hidl_string& /* fqInstanceName */,
+                                 listByInterface_cb /* _hidl_cb */) override {
+        // TODO: add this functionality
+        LOG(FATAL) << "Cannot list services with passthrough service manager.";
+        return Void();
+    }
+
+    Return<bool> registerForNotifications(const hidl_string& /* fqName */,
+                                          const hidl_string& /* name */,
+                                          const sp<IServiceNotification>& /* callback */) override {
+        // This makes no sense.
+        LOG(FATAL) << "Cannot register for notifications with passthrough service manager.";
+        return false;
+    }
+
+};
+
+sp<IServiceManager> getPassthroughServiceManager() {
+    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
+    return manager;
+}
+
 }; // namespace hardware
 }; // namespace android
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 51faf0b..d4552a7 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -31,7 +31,11 @@
 
 namespace hardware {
 
+// These functions are for internal use by hidl. If you want to get ahold
+// of an interface, the best way to do this is by calling IFoo::getService()
+
 sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
+sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
 
 }; // namespace hardware
 }; // namespace android