Merge "Don't initialize ProcessState without /dev/hwbinder."
diff --git a/include/hidl/HidlSupport.h b/include/hidl/HidlSupport.h
index 4b0e369..8c864ca 100644
--- a/include/hidl/HidlSupport.h
+++ b/include/hidl/HidlSupport.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HIDL_SUPPORT_H
 #define ANDROID_HIDL_SUPPORT_H
 
+#include <dlfcn.h>
 #include <hwbinder/Parcel.h>
 
 namespace android {
@@ -189,14 +190,14 @@
 // Version functions
 struct hidl_version {
 public:
-    hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {};
+    constexpr hidl_version(uint16_t major, uint16_t minor) : mMajor(major), mMinor(minor) {};
 
     bool operator==(const hidl_version& other) {
         return (mMajor == other.get_major() && mMinor == other.get_minor());
     }
 
-    uint16_t get_major() const { return mMajor; }
-    uint16_t get_minor() const { return mMinor; }
+    constexpr uint16_t get_major() const { return mMajor; }
+    constexpr uint16_t get_minor() const { return mMinor; }
 
     android::status_t writeToParcel(android::hardware::Parcel& parcel) const {
         return parcel.writeUint32((uint32_t) mMajor << 16 | mMinor);
@@ -221,35 +222,61 @@
     return hidl_version(major,minor);
 }
 
+#if defined(__LP64__)
+#define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/"
+#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/"
+#define HAL_LIBRARY_PATH_ODM "/odm/lib64/hw/"
+#else
+#define HAL_LIBRARY_PATH_SYSTEM "/system/lib/hw/"
+#define HAL_LIBRARY_PATH_VENDOR "/vendor/lib/hw/"
+#define HAL_LIBRARY_PATH_ODM "/odm/lib/hw/"
+#endif
+
 #define DECLARE_REGISTER_AND_GET_SERVICE(INTERFACE)                                      \
     static ::android::sp<I##INTERFACE> getService(                                       \
-            const ::android::String16 &serviceName,                                      \
-            const hidl_version &version);                                                \
-    status_t registerAsService(                                                            \
-            const ::android::String16& serviceName,                                      \
-            const hidl_version &version);
+            const std::string &serviceName);                                             \
+    status_t registerAsService(                                                          \
+            const std::string &serviceName);                                             \
 
-#define IMPLEMENT_REGISTER_AND_GET_SERVICE(INTERFACE)                                    \
+#define IMPLEMENT_REGISTER_AND_GET_SERVICE(INTERFACE, LIB)                               \
     ::android::sp<I##INTERFACE> I##INTERFACE::getService(                                \
-            const ::android::String16 &serviceName,                                      \
-            const hidl_version &version /* TODO get version from IFoo directly */)       \
+            const std::string &serviceName)                                              \
     {                                                                                    \
         sp<I##INTERFACE> iface;                                                          \
         const sp<IServiceManager> sm = defaultServiceManager();                          \
         if (sm != nullptr) {                                                             \
-            sp<IBinder> binderIface = sm->getService(serviceName, version);              \
+            sp<IBinder> binderIface = sm->checkService(String16(serviceName.c_str()),    \
+                                                       I##INTERFACE::version);           \
             iface = IHw##INTERFACE::asInterface(binderIface);                            \
         }                                                                                \
-        /* TODO: if we don't have a binder interface, try to instantiate default */      \
+        if (iface != nullptr) {                                                          \
+            return iface;                                                                \
+        }                                                                                \
+        int dlMode = RTLD_LAZY;                                                          \
+        void *handle = dlopen(HAL_LIBRARY_PATH_ODM LIB, dlMode);                         \
+        if (handle == nullptr) {                                                         \
+            handle = dlopen(HAL_LIBRARY_PATH_VENDOR LIB, dlMode);                        \
+        }                                                                                \
+        if (handle == nullptr) {                                                         \
+            handle = dlopen(HAL_LIBRARY_PATH_SYSTEM LIB, dlMode);                        \
+        }                                                                                \
+        if (handle == nullptr) {                                                         \
+            return iface;                                                                \
+        }                                                                                \
+        I##INTERFACE* (*generator)(const char* name);                                    \
+        *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE);                \
+        if (generator) {                                                                 \
+            iface = (*generator)(serviceName.c_str());                                   \
+        }                                                                                \
         return iface;                                                                    \
     }                                                                                    \
-    status_t I##INTERFACE::registerAsService(                                              \
-            const ::android::String16& serviceName,                                      \
-            const hidl_version &version)                                                 \
+    status_t I##INTERFACE::registerAsService(                                            \
+            const std::string &serviceName)                                              \
     {                                                                                    \
         sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this);                         \
         const sp<IServiceManager> sm = defaultServiceManager();                          \
-        return sm->addService(serviceName, binderIface, version);                        \
+        return sm->addService(String16(serviceName.c_str()), binderIface,                \
+                              I##INTERFACE::version);                                    \
     }
 
 }  // namespace hardware
diff --git a/include/hidl/Status.h b/include/hidl/Status.h
index aa8f1b2..59e4d65 100644
--- a/include/hidl/Status.h
+++ b/include/hidl/Status.h
@@ -147,20 +147,33 @@
 std::stringstream& operator<< (std::stringstream& stream, const Status& s);
 
 template<typename T> class Return {
+private:
+      T val {};
+      Status status {};
 public:
-      T val;
-      Status status;
-public:
-      Return(T v) : val(v), status(Status::ok()) { }
-      Return(Status s) : status(s) {
-          // TODO(malchev): Spew a LOG error here
-      }
-      ~Return() {
-          // TODO(malchev): Assert that status isOk() if it hasn't been checked
-      }
+      Return(T v) : val{v} {}
+      Return(Status s) : status(s) {}
       operator T() { return val; }
+      const Status& getStatus() const {
+          return status;
+      }
 };
 
+template<> class Return<void> {
+private:
+      Status status {};
+public:
+      Return() = default;
+      Return(Status s) : status(s) {}
+      const Status& getStatus() const {
+          return status;
+      }
+};
+
+static inline Return<void> Void() {
+    return Return<void>();
+}
+
 }  // namespace hardware
 }  // namespace android