Multihal 2.0 - Implement SubHal discovery

Collect the SubHal pointers discovered from dynamic libs contained
within the multi hal config file.

Bug: 136511617
Test: Compiled with mma -j and observed loading of modules

Change-Id: I148265722e70d4cd56671af9c6f1ff6dde355ae4
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index f0b33e4..dff28ab 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -44,4 +44,4 @@
     name: "android.hardware.sensors@2.0-subhal.header",
     vendor: true,
     export_include_dirs: ["include"],
-}
\ No newline at end of file
+}
diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/2.0/multihal/HalProxy.cpp
index 31f8a18..41c3548 100644
--- a/sensors/2.0/multihal/HalProxy.cpp
+++ b/sensors/2.0/multihal/HalProxy.cpp
@@ -18,12 +18,19 @@
 
 #include <android/hardware/sensors/2.0/types.h>
 
+#include <dlfcn.h>
+
+#include <fstream>
+#include <functional>
+
 namespace android {
 namespace hardware {
 namespace sensors {
 namespace V2_0 {
 namespace implementation {
 
+typedef ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);
+
 // TODO: Use this wake lock name as the prefix to all sensors HAL wake locks acquired.
 // constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
 
@@ -62,7 +69,39 @@
 };
 
 HalProxy::HalProxy() {
-    // TODO: Initialize all sub-HALs and discover sensors.
+    const char* kMultiHalConfigFilePath = "/vendor/etc/sensors/hals.conf";
+    std::ifstream subHalConfigStream(kMultiHalConfigFilePath);
+    if (!subHalConfigStream) {
+        LOG_FATAL("Failed to load subHal config file: %s", kMultiHalConfigFilePath);
+    } else {
+        std::string subHalLibraryFile;
+        while (subHalConfigStream >> subHalLibraryFile) {
+            void* handle = dlopen(subHalLibraryFile.c_str(), RTLD_NOW);
+            if (handle == nullptr) {
+                LOG_FATAL("dlopen failed for library: %s", subHalLibraryFile.c_str());
+            } else {
+                SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr =
+                        (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal");
+                if (sensorsHalGetSubHalPtr == nullptr) {
+                    LOG_FATAL("Failed to locate sensorsHalGetSubHal function for library: %s",
+                              subHalLibraryFile.c_str());
+                } else {
+                    std::function<SensorsHalGetSubHalFunc> sensorsHalGetSubHal =
+                            *sensorsHalGetSubHalPtr;
+                    uint32_t version;
+                    ISensorsSubHal* subHal = sensorsHalGetSubHal(&version);
+                    if (version != SUB_HAL_2_0_VERSION) {
+                        LOG_FATAL("SubHal version was not 2.0 for library: %s",
+                                  subHalLibraryFile.c_str());
+                    } else {
+                        ALOGI("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
+                        mSubHalList.push_back(subHal);
+                    }
+                }
+            }
+        }
+    }
+    // TODO: Discover sensors
 }
 
 HalProxy::~HalProxy() {
diff --git a/sensors/2.0/multihal/HalProxy.h b/sensors/2.0/multihal/HalProxy.h
index b9855a6..e5799fd 100644
--- a/sensors/2.0/multihal/HalProxy.h
+++ b/sensors/2.0/multihal/HalProxy.h
@@ -111,6 +111,11 @@
      * Callback to the sensors framework to inform it that new sensors have been added or removed.
      */
     sp<ISensorsCallback> mDynamicSensorsCallback;
+
+    /**
+     * SubHal object pointers that have been saved from vendor dynamic libraries.
+     */
+    std::vector<ISensorsSubHal*> mSubHalList;
 };
 
 }  // namespace implementation