Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)

Bug: 166295507
Merged-In: I6a07c809d90b8e567a3e5027b2eb4c499eeedb1b
Change-Id: I326820c4a876960b20b9fad780399cd4c451b6c5
diff --git a/msm8998/gnss/Agps.cpp b/msm8998/gnss/Agps.cpp
index 32f3985..d88a6ba 100644
--- a/msm8998/gnss/Agps.cpp
+++ b/msm8998/gnss/Agps.cpp
@@ -454,15 +454,14 @@
 
     if (NULL != mAPN) {
         delete mAPN;
+        mAPN  = NULL;
     }
 
-    if(apn == NULL || len <= 0){
+    if(NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len){
         LOC_LOGD("Invalid apn len (%d) or null apn", len);
         mAPN = NULL;
         mAPNLen = 0;
-    }
-
-    if (NULL != apn) {
+    }else{
         mAPN = new char[len+1];
         memcpy(mAPN, apn, len);
         mAPN[len] = '\0';
diff --git a/msm8998/gnss/GnssAdapter.cpp b/msm8998/gnss/GnssAdapter.cpp
index 9809125..3386a63 100644
--- a/msm8998/gnss/GnssAdapter.cpp
+++ b/msm8998/gnss/GnssAdapter.cpp
@@ -2549,6 +2549,12 @@
                         new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
 
             LOC_LOGV("AgpsMsgAtlOpenSuccess");
+            if (mApnName == nullptr) {
+                LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
+                // Reporting the failure here
+                mAgpsManager->reportAtlClosed(mAgpsType);
+                return;
+            }
             memcpy(mApnName, apnName, apnLen);
             mApnName[apnLen] = 0;
         }
@@ -2565,8 +2571,16 @@
         }
     };
 
-    sendMsg( new AgpsMsgAtlOpenSuccess(
-            &mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType));
+    // Added inital length checks for apnlen check to avoid security issues
+    // In case of failure reporting the same
+    if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN ||
+            (strlen(apnName) != (unsigned)apnLen)) {
+        LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
+        mAgpsManager.reportAtlClosed(agpsType);
+    } else {
+        sendMsg( new AgpsMsgAtlOpenSuccess(
+                    &mAgpsManager, agpsType, apnName, apnLen, bearerType));
+    }
 }
 
 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
diff --git a/sdm845/android/Gnss.cpp b/sdm845/android/Gnss.cpp
index 1a7b8b0..025d1e0 100644
--- a/sdm845/android/Gnss.cpp
+++ b/sdm845/android/Gnss.cpp
@@ -27,7 +27,7 @@
 #include "Gnss.h"
 #include <LocationUtil.h>
 
-typedef void* (getLocationInterface)();
+typedef const GnssInterface* (getLocationInterface)();
 
 #define IMAGES_INFO_FILE "/sys/devices/soc0/images"
 #define DELIMITER ";"
@@ -124,7 +124,7 @@
     return mApi;
 }
 
-GnssInterface* Gnss::getGnssInterface() {
+const GnssInterface* Gnss::getGnssInterface() {
     static bool getGnssInterfaceFailed = false;
     if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
         LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__);
@@ -145,7 +145,7 @@
         if (NULL == getter) {
             getGnssInterfaceFailed = true;
         } else {
-            mGnssInterface = (GnssInterface*)(*getter)();
+            mGnssInterface = (const GnssInterface*)(*getter)();
         }
     }
     return mGnssInterface;
@@ -278,7 +278,7 @@
                                   double longitudeDegrees,
                                   float accuracyMeters)  {
     ENTRY_LOG_CALLFLOW();
-    GnssInterface* gnssInterface = getGnssInterface();
+    const GnssInterface* gnssInterface = getGnssInterface();
     if (nullptr != gnssInterface) {
         gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
         return true;
@@ -368,7 +368,7 @@
     ENTRY_LOG_CALLFLOW();
     callback->gnssNameCb(getVersionString());
     mGnssCbIface_1_1 = callback;
-    GnssInterface* gnssInterface = getGnssInterface();
+    const GnssInterface* gnssInterface = getGnssInterface();
     if (nullptr != gnssInterface) {
         OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
             odcpiRequestCb(odcpiRequest);
@@ -412,7 +412,7 @@
 
 Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
     ENTRY_LOG_CALLFLOW();
-    GnssInterface* gnssInterface = getGnssInterface();
+    const GnssInterface* gnssInterface = getGnssInterface();
     if (nullptr != gnssInterface) {
         Location location = {};
         convertGnssLocation(gnssLocation, location);
@@ -439,9 +439,9 @@
     }
 }
 
-IGnss* HIDL_FETCH_IGnss(const char* hal) {
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
     ENTRY_LOG_CALLFLOW();
-    IGnss* iface = nullptr;
+    V1_0::IGnss* iface = nullptr;
     iface = new Gnss();
     if (iface == nullptr) {
         LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
diff --git a/sdm845/android/Gnss.h b/sdm845/android/Gnss.h
index 4c0c8b0..15645eb 100644
--- a/sdm845/android/Gnss.h
+++ b/sdm845/android/Gnss.h
@@ -109,7 +109,7 @@
     GnssAPIClient* getApi();
     Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
     Return<bool> updateConfiguration(GnssConfig& gnssConfig);
-    GnssInterface* getGnssInterface();
+    const GnssInterface* getGnssInterface();
 
     // Callback for ODCPI request
     void odcpiRequestCb(const OdcpiRequestInfo& request);
@@ -140,10 +140,10 @@
     sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
     sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
     GnssConfig mPendingConfig;
-    GnssInterface* mGnssInterface = nullptr;
+    const GnssInterface* mGnssInterface = nullptr;
 };
 
-extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/sdm845/core/LocApiBase.cpp b/sdm845/core/LocApiBase.cpp
index d06fddf..a0bf9c4 100644
--- a/sdm845/core/LocApiBase.cpp
+++ b/sdm845/core/LocApiBase.cpp
@@ -31,6 +31,7 @@
 
 #include <dlfcn.h>
 #include <inttypes.h>
+#include <gps_extended_c.h>
 #include <LocApiBase.h>
 #include <LocAdapterBase.h>
 #include <log_util.h>
@@ -95,7 +96,10 @@
     }
     inline virtual void proc() const {
         mLocApi->close();
-        mLocApi->open(mLocApi->getEvtMask());
+        if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask())) {
+            // Notify adapters that engine up after SSR
+            mLocApi->handleEngineUpEvent();
+        }
     }
     inline void locallog() const {
         LOC_LOGV("LocSsrMsg");
@@ -107,13 +111,17 @@
 
 struct LocOpenMsg : public LocMsg {
     LocApiBase* mLocApi;
-    inline LocOpenMsg(LocApiBase* locApi) :
-            LocMsg(), mLocApi(locApi)
+    LocAdapterBase* mAdapter;
+    inline LocOpenMsg(LocApiBase* locApi, LocAdapterBase* adapter = nullptr) :
+            LocMsg(), mLocApi(locApi), mAdapter(adapter)
     {
         locallog();
     }
     inline virtual void proc() const {
-        mLocApi->open(mLocApi->getEvtMask());
+        if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask()) &&
+            nullptr != mAdapter) {
+            mLocApi->handleEngineUpEvent();
+        }
     }
     inline void locallog() const {
         LOC_LOGv("LocOpen Mask: %" PRIx64 "\n", mLocApi->getEvtMask());
@@ -201,7 +209,7 @@
     for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) {
         if (mLocAdapters[i] == NULL) {
             mLocAdapters[i] = adapter;
-            mMsgTask->sendMsg(new LocOpenMsg(this));
+            mMsgTask->sendMsg(new LocOpenMsg(this, adapter));
             break;
         }
     }
@@ -250,17 +258,15 @@
 
 void LocApiBase::handleEngineUpEvent()
 {
-    // This will take care of renegotiating the loc handle
-    mMsgTask->sendMsg(new LocSsrMsg(this));
-
-    LocDualContext::injectFeatureConfig(mContext);
-
     // loop through adapters, and deliver to all adapters.
     TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineUpEvent());
 }
 
 void LocApiBase::handleEngineDownEvent()
 {
+    // This will take care of renegotiating the loc handle
+    mMsgTask->sendMsg(new LocSsrMsg(this));
+
     // loop through adapters, and deliver to all adapters.
     TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineDownEvent());
 }
diff --git a/sdm845/core/LocApiBase.h b/sdm845/core/LocApiBase.h
index aec1846..b93b227 100644
--- a/sdm845/core/LocApiBase.h
+++ b/sdm845/core/LocApiBase.h
@@ -80,12 +80,12 @@
     friend struct LocOpenMsg;
     friend class ContextBase;
     const MsgTask* mMsgTask;
-    ContextBase *mContext;
     LocAdapterBase* mLocAdapters[MAX_ADAPTERS];
     uint64_t mSupportedMsg;
     uint8_t mFeaturesSupported[MAX_FEATURE_LENGTH];
 
 protected:
+    ContextBase *mContext;
     virtual enum loc_api_adapter_err
         open(LOC_API_ADAPTER_EVENT_MASK_T mask);
     virtual enum loc_api_adapter_err
diff --git a/sdm845/core/LocDualContext.cpp b/sdm845/core/LocDualContext.cpp
index 180d9dc..9851d61 100644
--- a/sdm845/core/LocDualContext.cpp
+++ b/sdm845/core/LocDualContext.cpp
@@ -55,7 +55,6 @@
 const MsgTask* LocDualContext::mMsgTask = NULL;
 ContextBase* LocDualContext::mFgContext = NULL;
 ContextBase* LocDualContext::mBgContext = NULL;
-ContextBase* LocDualContext::mInjectContext = NULL;
 // the name must be shorter than 15 chars
 const char* LocDualContext::mLocationHalName = "Loc_hal_worker";
 #ifndef USE_GLIB
@@ -91,11 +90,6 @@
         mFgContext = new LocDualContext(msgTask,
                                         mFgExclMask);
     }
-    if(NULL == mInjectContext) {
-        LOC_LOGD("%s:%d]: mInjectContext is FgContext", __func__, __LINE__);
-        mInjectContext = mFgContext;
-        injectFeatureConfig(mInjectContext);
-    }
     pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex);
 
     if (firstMsg) {
@@ -116,11 +110,6 @@
         mBgContext = new LocDualContext(msgTask,
                                         mBgExclMask);
     }
-    if(NULL == mInjectContext) {
-        LOC_LOGD("%s:%d]: mInjectContext is BgContext", __func__, __LINE__);
-        mInjectContext = mBgContext;
-        injectFeatureConfig(mInjectContext);
-    }
     pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex);
 
     if (firstMsg) {
@@ -132,13 +121,9 @@
 
 void LocDualContext :: injectFeatureConfig(ContextBase *curContext)
 {
-    LOC_LOGD("%s:%d]: Enter", __func__, __LINE__);
-    if(curContext == mInjectContext) {
-        LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config",
-                 __func__, __LINE__, ((LocDualContext *)mInjectContext)->mLBSProxy);
-        ((LocDualContext *)mInjectContext)->mLBSProxy->injectFeatureConfig(curContext);
-    }
-    LOC_LOGD("%s:%d]: Exit", __func__, __LINE__);
+    LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config",
+             __func__, __LINE__, ((LocDualContext *)curContext)->mLBSProxy);
+    ((LocDualContext *)curContext)->mLBSProxy->injectFeatureConfig(curContext);
 }
 
 LocDualContext::LocDualContext(const MsgTask* msgTask,
diff --git a/sdm845/core/LocDualContext.h b/sdm845/core/LocDualContext.h
index 3b3ce2c..edfbfb7 100644
--- a/sdm845/core/LocDualContext.h
+++ b/sdm845/core/LocDualContext.h
@@ -40,7 +40,6 @@
     static const MsgTask* mMsgTask;
     static ContextBase* mFgContext;
     static ContextBase* mBgContext;
-    static ContextBase* mInjectContext;
     static const MsgTask* getMsgTask(LocThread::tCreate tCreator,
                                      const char* name, bool joinable = true);
     static const MsgTask* getMsgTask(const char* name, bool joinable = true);
diff --git a/sdm845/gnss/Agps.cpp b/sdm845/gnss/Agps.cpp
index f2ca8e4..32a4310 100644
--- a/sdm845/gnss/Agps.cpp
+++ b/sdm845/gnss/Agps.cpp
@@ -452,15 +452,14 @@
 
     if (NULL != mAPN) {
         delete mAPN;
+        mAPN  = NULL;
     }
 
-    if (apn == NULL || len <= 0) {
+    if (NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len) {
         LOC_LOGD("Invalid apn len (%d) or null apn", len);
         mAPN = NULL;
         mAPNLen = 0;
-    }
-
-    if (NULL != apn) {
+    } else {
         mAPN = new char[len+1];
         if (NULL != mAPN) {
             memcpy(mAPN, apn, len);
diff --git a/sdm845/gnss/GnssAdapter.cpp b/sdm845/gnss/GnssAdapter.cpp
index a404bbb..7a0a520 100644
--- a/sdm845/gnss/GnssAdapter.cpp
+++ b/sdm845/gnss/GnssAdapter.cpp
@@ -655,14 +655,14 @@
         int32_t length = -1;
         const char noHost[] = "NONE";
 
-        locErr = LOCATION_ERROR_INVALID_PARAMETER;
-
         if ((NULL == server) || (server[0] == 0) ||
                 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
             serverUrl[0] = '\0';
             length = 0;
         } else if (port > 0) {
             length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
+        } else {
+            locErr = LOCATION_ERROR_INVALID_PARAMETER;
         }
 
         if (length >= 0 && strncasecmp(getServerUrl().c_str(),
@@ -1374,8 +1374,8 @@
 GnssAdapter::gnssSvTypeConfigUpdate()
 {
     LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
-    LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
-             mGnssSvTypeConfig.blacklistedSvTypesMask, mGnssSvTypeConfig.enabledSvTypesMask);
+    LOC_LOGd("size %zu constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
+             mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask, mGnssSvTypeConfig.enabledSvTypesMask);
 
     if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
         GnssSvIdConfig blacklistConfig = {};
@@ -1412,7 +1412,6 @@
             }
         }
     } else {
-        LOC_LOGE("Invalid GnssSvTypeConfig size");
         err = LOCATION_ERROR_SUCCESS;
     }
 
@@ -3601,6 +3600,8 @@
             LOC_LOGV("AgpsMsgAtlOpenSuccess");
             if (mApnName == nullptr) {
                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
+                // Reporting the failure here
+                mAgpsManager->reportAtlClosed(mAgpsType);
                 return;
             }
             memcpy(mApnName, apnName, apnLen);
@@ -3617,9 +3618,16 @@
             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
         }
     };
-
-    sendMsg( new AgpsMsgAtlOpenSuccess(
-            &mAgpsManager, agpsType, apnName, apnLen, bearerType));
+    // Added inital length checks for apnlen check to avoid security issues
+    // In case of failure reporting the same
+    if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN ||
+            (strlen(apnName) != (unsigned)apnLen)) {
+        LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
+        mAgpsManager.reportAtlClosed(agpsType);
+    } else {
+        sendMsg( new AgpsMsgAtlOpenSuccess(
+                    &mAgpsManager, agpsType, apnName, apnLen, bearerType));
+    }
 }
 
 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
diff --git a/sdm845/location/LocationAPI.cpp b/sdm845/location/LocationAPI.cpp
index 5547f1a..7e931dd 100644
--- a/sdm845/location/LocationAPI.cpp
+++ b/sdm845/location/LocationAPI.cpp
@@ -34,8 +34,12 @@
 #include <log_util.h>
 #include <pthread.h>
 #include <map>
+#include <loc_misc_utils.h>
 
-typedef void* (getLocationInterface)();
+typedef const GnssInterface* (getGnssInterface)();
+typedef const FlpInterface* (getFlpInterface)();
+typedef const GeofenceInterface* (getGeofenceInterface)();
+
 typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
 typedef struct {
     LocationClientMap clientData;
@@ -51,6 +55,17 @@
 static bool gFlpLoadFailed = false;
 static bool gGeofenceLoadFailed = false;
 
+template <typename T1, typename T2>
+static const T1* loadLocationInterface(const char* library, const char* name) {
+    void* libhandle = nullptr;
+    T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name);
+    if (nullptr == getter) {
+        return (const T1*) getter;
+    }else {
+        return (*getter)();
+    }
+}
+
 static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
 {
     return (locationCallbacks.gnssLocationInfoCb != nullptr ||
@@ -78,31 +93,6 @@
             locationCallbacks.geofenceStatusCb != nullptr);
 }
 
-static void* loadLocationInterface(const char* library, const char* name) {
-    LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name);
-    if (NULL == library || NULL == name) {
-        return NULL;
-    }
-    getLocationInterface* getter = NULL;
-    const char *error = NULL;
-    dlerror();
-    void *handle = dlopen(library, RTLD_NOW);
-    if (NULL == handle || (error = dlerror()) != NULL)  {
-        LOC_LOGW("dlopen for %s failed, error = %s", library, error);
-    } else {
-        getter = (getLocationInterface*)dlsym(handle, name);
-        if ((error = dlerror()) != NULL)  {
-            LOC_LOGW("dlsym for %s::%s failed, error = %s", library, name, error);
-            getter = NULL;
-        }
-    }
-
-    if (NULL == getter) {
-        return (void*)getter;
-    } else {
-        return (*getter)();
-    }
-}
 
 LocationAPI*
 LocationAPI::createInstance(LocationCallbacks& locationCallbacks)
@@ -121,7 +111,8 @@
     if (isGnssClient(locationCallbacks)) {
         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
             gData.gnssInterface =
-                (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
+                (GnssInterface*)loadLocationInterface<GnssInterface,
+                    getGnssInterface>("libgnss.so", "getGnssInterface");
             if (NULL == gData.gnssInterface) {
                 gGnssLoadFailed = true;
                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
@@ -141,7 +132,8 @@
     if (isFlpClient(locationCallbacks)) {
         if (NULL == gData.flpInterface && !gFlpLoadFailed) {
             gData.flpInterface =
-                (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
+                (FlpInterface*)loadLocationInterface<FlpInterface,
+                   getFlpInterface>("libflp.so", "getFlpInterface");
             if (NULL == gData.flpInterface) {
                 gFlpLoadFailed = true;
                 LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
@@ -161,7 +153,8 @@
     if (isGeofenceClient(locationCallbacks)) {
         if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
             gData.geofenceInterface =
-                (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface");
+               (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
+                getGeofenceInterface>("libgeofence.so", "getGeofenceInterface");
             if (NULL == gData.geofenceInterface) {
                 gGeofenceLoadFailed = true;
                 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
@@ -235,7 +228,8 @@
     if (isGnssClient(locationCallbacks)) {
         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
             gData.gnssInterface =
-                (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
+                (GnssInterface*)loadLocationInterface<GnssInterface,
+                    getGnssInterface>("libgnss.so", "getGnssInterface");
             if (NULL == gData.gnssInterface) {
                 gGnssLoadFailed = true;
                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
@@ -252,7 +246,8 @@
     if (isFlpClient(locationCallbacks)) {
         if (NULL == gData.flpInterface && !gFlpLoadFailed) {
             gData.flpInterface =
-                (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
+                (FlpInterface*)loadLocationInterface<FlpInterface,
+                    getFlpInterface>("libflp.so", "getFlpInterface");
             if (NULL == gData.flpInterface) {
                 gFlpLoadFailed = true;
                 LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
@@ -269,7 +264,8 @@
     if (isGeofenceClient(locationCallbacks)) {
         if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
             gData.geofenceInterface =
-                (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface");
+                (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
+                getGeofenceInterface>("libgeofence.so", "getGeofenceInterface");
             if (NULL == gData.geofenceInterface) {
                 gGeofenceLoadFailed = true;
                 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
@@ -535,7 +531,8 @@
     if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
             gData.gnssInterface =
-                (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
+                (GnssInterface*)loadLocationInterface<GnssInterface,
+                    getGnssInterface>("libgnss.so", "getGnssInterface");
             if (NULL == gData.gnssInterface) {
                 gGnssLoadFailed = true;
                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
diff --git a/sdm845/utils/Android.mk b/sdm845/utils/Android.mk
index d469371..40c3bbb 100644
--- a/sdm845/utils/Android.mk
+++ b/sdm845/utils/Android.mk
@@ -9,6 +9,7 @@
 
 ## Libs
 LOCAL_SHARED_LIBRARIES := \
+    libdl \
     libutils \
     libcutils \
     liblog \
diff --git a/sdm845/utils/Makefile.am b/sdm845/utils/Makefile.am
index 3801fdd..57dc7f0 100644
--- a/sdm845/utils/Makefile.am
+++ b/sdm845/utils/Makefile.am
@@ -60,7 +60,7 @@
 libgps_utils_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
 endif
 
-libgps_utils_la_LIBADD = $(CUTILS_LIBS)
+libgps_utils_la_LIBADD = $(CUTILS_LIBS) -ldl
 
 #Create and Install libraries
 lib_LTLIBRARIES = libgps_utils.la
diff --git a/sdm845/utils/loc_misc_utils.cpp b/sdm845/utils/loc_misc_utils.cpp
index b7c8406..70fdbc3 100644
--- a/sdm845/utils/loc_misc_utils.cpp
+++ b/sdm845/utils/loc_misc_utils.cpp
@@ -30,6 +30,7 @@
 #define LOG_TAG "LocSvc_misc_utils"
 #include <stdio.h>
 #include <string.h>
+#include <dlfcn.h>
 #include <log_util.h>
 #include <loc_misc_utils.h>
 #include <ctype.h>
@@ -112,3 +113,33 @@
 err:
     return;
 }
+
+inline void logDlError(const char* failedCall) {
+    const char * err = dlerror();
+    LOC_LOGe("%s error: %s", failedCall, (nullptr == err) ? "unknown" : err);
+}
+
+void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName)
+{
+    void* sym = nullptr;
+    if ((nullptr != libHandle || nullptr != libName) && nullptr != symName) {
+        if (nullptr == libHandle) {
+            libHandle = dlopen(libName, RTLD_NOW);
+            if (nullptr == libHandle) {
+                logDlError("dlopen");
+            }
+        }
+        // NOT else, as libHandle gets assigned 5 line above
+        if (nullptr != libHandle) {
+            sym = dlsym(libHandle, symName);
+            if (nullptr == sym) {
+                logDlError("dlsym");
+            }
+        }
+    } else {
+        LOC_LOGe("Either libHandle (%p) or libName (%p) must not be null; "
+                 "symName (%p) can not be null.", libHandle, libName, symName);
+    }
+
+    return sym;
+}
diff --git a/sdm845/utils/loc_misc_utils.h b/sdm845/utils/loc_misc_utils.h
index 7d66d84..fad1b6d 100644
--- a/sdm845/utils/loc_misc_utils.h
+++ b/sdm845/utils/loc_misc_utils.h
@@ -92,6 +92,34 @@
    N/A
 ===========================================================================*/
 void loc_util_trim_space(char *org_string);
+
+/*===========================================================================
+FUNCTION dlGetSymFromLib
+
+DESCRIPTION
+   Handy function to get a pointer to a symbol from a library.
+
+   If libHandle is not null, it will be used as the handle to the library. In
+   that case libName wll not be used;
+   libHandle is an in / out parameter.
+   If libHandle is null, libName will be used to dlopen.
+   Either libHandle or libName must not be nullptr.
+   symName must not be null.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+   pointer to symName. Could be nullptr if
+       Parameters are incorrect; or
+       libName can not be opened; or
+       symName can not be found.
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName);
+
 #ifdef __cplusplus
 }
 #endif