sdm: Add DynLib utility for dynamic library lifecycle management.

- Add DynLib utility to automatically unload libraries upon
  destruction of the utility object.

CRs-Fixed: 1029997
Change-Id: I4e13ad984949db170498fe1ec5c133fa4a798bdd
diff --git a/sdm/include/utils/sys.h b/sdm/include/utils/sys.h
index ae75967..c06b7f8 100644
--- a/sdm/include/utils/sys.h
+++ b/sdm/include/utils/sys.h
@@ -26,6 +26,7 @@
 #define __SYS_H__
 
 #include <sys/eventfd.h>
+#include <dlfcn.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -75,6 +76,20 @@
   static eventfd eventfd_;
 };
 
+class DynLib {
+ public:
+  ~DynLib();
+  bool Open(const char *lib_name);
+  bool Sym(const char *func_name, void **func_ptr);
+  const char * Error() { return ::dlerror(); }
+  operator bool() const { return lib_ != NULL; }
+
+ private:
+  void Close();
+
+  void *lib_ = NULL;
+};
+
 }  // namespace sdm
 
 #endif  // __SYS_H__
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index f24a920..c9792db 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -37,7 +37,7 @@
 
 namespace sdm {
 
-void *ColorManagerProxy::color_lib_ = NULL;
+DynLib ColorManagerProxy::color_lib_;
 CreateColorInterface ColorManagerProxy::create_intf_ = NULL;
 DestroyColorInterface ColorManagerProxy::destroy_intf_ = NULL;
 HWResourceInfo ColorManagerProxy::hw_res_info_;
@@ -79,14 +79,10 @@
   DisplayError error = kErrorNone;
 
   // Load color service library and retrieve its entry points.
-  color_lib_ = ::dlopen(COLORMGR_LIBRARY_NAME, RTLD_NOW);
-  if (color_lib_) {
-    *(reinterpret_cast<void **>(&create_intf_)) = ::dlsym(color_lib_, CREATE_COLOR_INTERFACE_NAME);
-    *(reinterpret_cast<void **>(&destroy_intf_)) =
-        ::dlsym(color_lib_, DESTROY_COLOR_INTERFACE_NAME);
-    if (!create_intf_ || !destroy_intf_) {
+  if (color_lib_.Open(COLORMGR_LIBRARY_NAME)) {
+    if (!color_lib_.Sym(CREATE_COLOR_INTERFACE_NAME, reinterpret_cast<void **>(&create_intf_)) ||
+        !color_lib_.Sym(DESTROY_COLOR_INTERFACE_NAME, reinterpret_cast<void **>(&destroy_intf_))) {
       DLOGW("Fail to retrieve = %s from %s", CREATE_COLOR_INTERFACE_NAME, COLORMGR_LIBRARY_NAME);
-      ::dlclose(color_lib_);
       error = kErrorResources;
     }
   } else {
@@ -100,8 +96,7 @@
 }
 
 void ColorManagerProxy::Deinit() {
-  if (color_lib_)
-    ::dlclose(color_lib_);
+  color_lib_.~DynLib();
 }
 
 ColorManagerProxy::ColorManagerProxy(DisplayType type, HWInterface *intf,
diff --git a/sdm/libs/core/color_manager.h b/sdm/libs/core/color_manager.h
index 9f9eb40..728b82f 100644
--- a/sdm/libs/core/color_manager.h
+++ b/sdm/libs/core/color_manager.h
@@ -34,6 +34,7 @@
 #include <core/sdm_types.h>
 #include <utils/locker.h>
 #include <private/color_interface.h>
+#include <utils/sys.h>
 #include <utils/debug.h>
 #include "hw_interface.h"
 
@@ -78,7 +79,7 @@
                     const HWPanelInfo &info);
 
  private:
-  static void *color_lib_;
+  static DynLib color_lib_;
   static CreateColorInterface create_intf_;
   static DestroyColorInterface destroy_intf_;
   static HWResourceInfo hw_res_info_;
diff --git a/sdm/libs/core/core_impl.cpp b/sdm/libs/core/core_impl.cpp
index 82f578e..da85c9e 100644
--- a/sdm/libs/core/core_impl.cpp
+++ b/sdm/libs/core/core_impl.cpp
@@ -48,28 +48,22 @@
   DisplayError error = kErrorNone;
 
   // Try to load extension library & get handle to its interface.
-  extension_lib_ = ::dlopen(EXTENSION_LIBRARY_NAME, RTLD_NOW);
-  if (extension_lib_) {
-    void **create_sym = reinterpret_cast<void **>(&create_extension_intf_);
-    void **destroy_sym = reinterpret_cast<void **>(&destroy_extension_intf_);
-
-    *create_sym = ::dlsym(extension_lib_, CREATE_EXTENSION_INTERFACE_NAME);
-    *destroy_sym = ::dlsym(extension_lib_, DESTROY_EXTENSION_INTERFACE_NAME);
-
-    if (!create_extension_intf_ || !destroy_extension_intf_) {
-      DLOGE("Unable to load symbols, error = %s", ::dlerror());
-      ::dlclose(extension_lib_);
+  if (extension_lib_.Open(EXTENSION_LIBRARY_NAME)) {
+    if (!extension_lib_.Sym(CREATE_EXTENSION_INTERFACE_NAME,
+                            reinterpret_cast<void **>(&create_extension_intf_)) ||
+        !extension_lib_.Sym(DESTROY_EXTENSION_INTERFACE_NAME,
+                            reinterpret_cast<void **>(&destroy_extension_intf_))) {
+      DLOGE("Unable to load symbols, error = %s", extension_lib_.Error());
       return kErrorUndefined;
     }
 
     error = create_extension_intf_(EXTENSION_VERSION_TAG, &extension_intf_);
     if (error != kErrorNone) {
-      DLOGE("Unable to create interface, error = %s", ::dlerror());
-      ::dlclose(extension_lib_);
+      DLOGE("Unable to create interface");
       return error;
     }
   } else {
-    DLOGW("Unable to load = %s, error = %s", EXTENSION_LIBRARY_NAME, ::dlerror());
+    DLOGW("Unable to load = %s, error = %s", EXTENSION_LIBRARY_NAME, extension_lib_.Error());
   }
 
   error = HWInfoInterface::Create(&hw_info_intf_);
@@ -118,11 +112,6 @@
     delete hw_resource_;
   }
 
-  if (extension_lib_) {
-    destroy_extension_intf_(extension_intf_);
-    ::dlclose(extension_lib_);
-  }
-
   return error;
 }
 
@@ -142,11 +131,6 @@
     delete hw_resource_;
   }
 
-  if (extension_lib_) {
-    destroy_extension_intf_(extension_intf_);
-    ::dlclose(extension_lib_);
-  }
-
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/core_impl.h b/sdm/libs/core/core_impl.h
index 97e8655..2d0e2d2 100644
--- a/sdm/libs/core/core_impl.h
+++ b/sdm/libs/core/core_impl.h
@@ -29,6 +29,7 @@
 #include <private/extension_interface.h>
 #include <private/color_interface.h>
 #include <utils/locker.h>
+#include <utils/sys.h>
 
 #include "hw_interface.h"
 #include "comp_manager.h"
@@ -68,7 +69,7 @@
   CompManager comp_mgr_;
   HWInfoInterface *hw_info_intf_ = NULL;
   RotatorInterface *rotator_intf_ = NULL;
-  void *extension_lib_ = NULL;
+  DynLib extension_lib_;
   ExtensionInterface *extension_intf_ = NULL;
   CreateExtensionInterface create_extension_intf_ = NULL;
   DestroyExtensionInterface destroy_extension_intf_ = NULL;
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index 9dbb1c8..601d597 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -300,11 +300,9 @@
   }
 
   // Disable destination scalar count to 0 if extension library is not present
-  void *extension_lib = ::dlopen("libsdmextension.so", RTLD_NOW);
-  if (!extension_lib) {
+  DynLib extension_lib;
+  if (!extension_lib.Open("libsdmextension.so")) {
     hw_resource->hw_dest_scalar_info.count = 0;
-  } else {
-    ::dlclose(extension_lib);
   }
 
   DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
diff --git a/sdm/libs/hwc/cpuhint.cpp b/sdm/libs/hwc/cpuhint.cpp
index ccf55bf..551fa24 100644
--- a/sdm/libs/hwc/cpuhint.cpp
+++ b/sdm/libs/hwc/cpuhint.cpp
@@ -38,13 +38,6 @@
 
 namespace sdm {
 
-CPUHint::~CPUHint() {
-  if (lib_handle_) {
-    dlclose(lib_handle_);
-    lib_handle_ = NULL;
-  }
-}
-
 DisplayError CPUHint::Init(HWCDebugHandler *debug_handler) {
   char path[PROPERTY_VALUE_MAX];
   if (debug_handler->GetProperty("ro.vendor.extension_library", path) != kErrorNone) {
@@ -61,19 +54,17 @@
 
   DLOGI("CPU Hint Pre-enable Window %d", pre_enable_window);
   pre_enable_window_ = pre_enable_window;
-  lib_handle_ = dlopen(path, RTLD_NOW);
 
-  if (lib_handle_) {
-    *(reinterpret_cast<void **>(&fn_lock_acquire_)) = dlsym(lib_handle_, "perf_lock_acq");
-    *(reinterpret_cast<void **>(&fn_lock_release_)) = dlsym(lib_handle_, "perf_lock_rel");
-    if (!fn_lock_acquire_ || !fn_lock_release_) {
+  if (vendor_ext_lib_.Open(path)) {
+    if (!vendor_ext_lib_.Sym("perf_lock_acq", reinterpret_cast<void **>(&fn_lock_acquire_)) ||
+        !vendor_ext_lib_.Sym("perf_lock_rel", reinterpret_cast<void **>(&fn_lock_release_))) {
       DLOGW("Failed to load symbols for Vendor Extension Library");
       return kErrorNotSupported;
     }
     DLOGI("Successfully Loaded Vendor Extension Library symbols");
     enabled_ = true;
   } else {
-    DLOGW("Failed to open %s : %s", path, dlerror());
+    DLOGW("Failed to open %s : %s", path, vendor_ext_lib_.Error());
   }
 
   return kErrorNone;
diff --git a/sdm/libs/hwc/cpuhint.h b/sdm/libs/hwc/cpuhint.h
index a4a7758..e758763 100644
--- a/sdm/libs/hwc/cpuhint.h
+++ b/sdm/libs/hwc/cpuhint.h
@@ -31,6 +31,7 @@
 #define __CPUHINT_H__
 
 #include <core/sdm_types.h>
+#include <utils/sys.h>
 
 namespace sdm {
 
@@ -38,7 +39,6 @@
 
 class CPUHint {
  public:
-  ~CPUHint();
   DisplayError Init(HWCDebugHandler *debug_handler);
   void Set();
   void Reset();
@@ -51,7 +51,7 @@
   int frame_countdown_ = 0;
   int lock_handle_ = 0;
   bool lock_acquired_ = false;
-  void *lib_handle_ = NULL;
+  DynLib vendor_ext_lib_;
   int (*fn_lock_acquire_)(int handle, int duration, int *hints, int num_args) = NULL;
   int (*fn_lock_release_)(int value) = NULL;
 };
diff --git a/sdm/libs/hwc/hwc_color_manager.cpp b/sdm/libs/hwc/hwc_color_manager.cpp
index 7c12ec0..8e11fce 100644
--- a/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/sdm/libs/hwc/hwc_color_manager.cpp
@@ -92,15 +92,12 @@
   HWCColorManager *color_mgr = new HWCColorManager();
 
   if (color_mgr) {
-    void *&color_lib = color_mgr->color_apis_lib_;
     // Load display API interface library. And retrieve color API function tables.
-    color_lib = ::dlopen(DISPLAY_API_INTERFACE_LIBRARY_NAME, RTLD_NOW);
-    if (color_lib) {
-      color_mgr->color_apis_ = ::dlsym(color_lib, DISPLAY_API_FUNC_TABLES);
-      if (!color_mgr->color_apis_) {
+    DynLib &color_apis_lib = color_mgr->color_apis_lib_;
+    if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
+      if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
         DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
               DISPLAY_API_INTERFACE_LIBRARY_NAME);
-        ::dlclose(color_lib);
         delete color_mgr;
         return NULL;
       }
@@ -112,18 +109,14 @@
     DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
 
     // Load diagclient library and invokes its entry point to pass in display APIs.
-    void *&diag_lib = color_mgr->diag_client_lib_;
-    diag_lib = ::dlopen(QDCM_DIAG_CLIENT_LIBRARY_NAME, RTLD_NOW);
-    if (diag_lib) {
-      *(reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) =
-          ::dlsym(diag_lib, INIT_QDCM_DIAG_CLIENT_NAME);
-      *(reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_)) =
-          ::dlsym(diag_lib, DEINIT_QDCM_DIAG_CLIENT_NAME);
-
-      if (!color_mgr->qdcm_diag_init_ || !color_mgr->qdcm_diag_deinit_) {
+    DynLib &diag_client_lib = color_mgr->diag_client_lib_;
+    if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
+      if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
+        !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
         DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
               QDCM_DIAG_CLIENT_LIBRARY_NAME);
-        ::dlclose(diag_lib);
       } else {
         // invoke Diag Client entry point to initialize.
         color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
@@ -152,12 +145,6 @@
   if (qdcm_diag_deinit_) {
     qdcm_diag_deinit_();
   }
-  if (diag_client_lib_) {
-    ::dlclose(diag_client_lib_);
-  }
-  if (color_apis_lib_) {
-    ::dlclose(color_apis_lib_);
-  }
   delete this;
 }
 
diff --git a/sdm/libs/hwc/hwc_color_manager.h b/sdm/libs/hwc/hwc_color_manager.h
index 2541e21..981b14a 100644
--- a/sdm/libs/hwc/hwc_color_manager.h
+++ b/sdm/libs/hwc/hwc_color_manager.h
@@ -36,6 +36,7 @@
 #include <binder/BinderService.h>
 #include <core/sdm_types.h>
 #include <utils/locker.h>
+#include <utils/sys.h>
 
 namespace sdm {
 
@@ -125,8 +126,8 @@
   static uint32_t Get8BitsARGBColorValue(const PPColorFillParams &params);
 
  private:
-  void *color_apis_lib_ = NULL;
-  void *diag_client_lib_ = NULL;
+  DynLib color_apis_lib_;
+  DynLib diag_client_lib_;
   void *color_apis_ = NULL;
   QDCMDiagInit qdcm_diag_init_ = NULL;
   QDCMDiagDeInit qdcm_diag_deinit_ = NULL;
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 89b4918..3075cbb 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -92,15 +92,12 @@
   HWCColorManager *color_mgr = new HWCColorManager();
 
   if (color_mgr) {
-    void *&color_lib = color_mgr->color_apis_lib_;
     // Load display API interface library. And retrieve color API function tables.
-    color_lib = ::dlopen(DISPLAY_API_INTERFACE_LIBRARY_NAME, RTLD_NOW);
-    if (color_lib) {
-      color_mgr->color_apis_ = ::dlsym(color_lib, DISPLAY_API_FUNC_TABLES);
-      if (!color_mgr->color_apis_) {
+    DynLib &color_apis_lib = color_mgr->color_apis_lib_;
+    if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
+      if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
         DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
               DISPLAY_API_INTERFACE_LIBRARY_NAME);
-        ::dlclose(color_lib);
         delete color_mgr;
         return NULL;
       }
@@ -112,18 +109,14 @@
     DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
 
     // Load diagclient library and invokes its entry point to pass in display APIs.
-    void *&diag_lib = color_mgr->diag_client_lib_;
-    diag_lib = ::dlopen(QDCM_DIAG_CLIENT_LIBRARY_NAME, RTLD_NOW);
-    if (diag_lib) {
-      *(reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) =
-          ::dlsym(diag_lib, INIT_QDCM_DIAG_CLIENT_NAME);
-      *(reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_)) =
-          ::dlsym(diag_lib, DEINIT_QDCM_DIAG_CLIENT_NAME);
-
-      if (!color_mgr->qdcm_diag_init_ || !color_mgr->qdcm_diag_deinit_) {
+    DynLib &diag_client_lib = color_mgr->diag_client_lib_;
+    if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
+      if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
+        !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
         DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
               QDCM_DIAG_CLIENT_LIBRARY_NAME);
-        ::dlclose(diag_lib);
       } else {
         // invoke Diag Client entry point to initialize.
         color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
@@ -152,12 +145,6 @@
   if (qdcm_diag_deinit_) {
     qdcm_diag_deinit_();
   }
-  if (diag_client_lib_) {
-    ::dlclose(diag_client_lib_);
-  }
-  if (color_apis_lib_) {
-    ::dlclose(color_apis_lib_);
-  }
   delete this;
 }
 
diff --git a/sdm/libs/utils/sys.cpp b/sdm/libs/utils/sys.cpp
index 6dddcfb..0ce524e 100644
--- a/sdm/libs/utils/sys.cpp
+++ b/sdm/libs/utils/sys.cpp
@@ -62,5 +62,33 @@
 
 #endif  // SDM_VIRTUAL_DRIVER
 
+DynLib::~DynLib() {
+  Close();
+}
+
+bool DynLib::Open(const char *lib_name) {
+  Close();
+  lib_ = ::dlopen(lib_name, RTLD_NOW);
+
+  return (*this);
+}
+
+bool DynLib::Sym(const char *func_name, void **func_ptr) {
+  if (lib_) {
+    *func_ptr = ::dlsym(lib_, func_name);
+  } else {
+    *func_ptr = NULL;
+  }
+
+  return (*func_ptr != NULL);
+}
+
+void DynLib::Close() {
+  if (lib_) {
+    ::dlclose(lib_);
+    lib_ = NULL;
+  }
+}
+
 }  // namespace sdm