audio: Remove HAL, UCM dependency on acdb and csd client modules

b/6815609

- acdb and csd client modules are linked into HAL, UCM
  at compile time.
- Remove the compile time dependency by loading the modules at
  runtime.

Change-Id: Iab9684a4564e5dccd8eb6e07017959886d2f57b1
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/alsa_sound/Android.mk b/alsa_sound/Android.mk
index 609b7dc..656758c 100644
--- a/alsa_sound/Android.mk
+++ b/alsa_sound/Android.mk
@@ -36,15 +36,19 @@
     libaudiopolicy_legacy \
 
 LOCAL_SHARED_LIBRARIES := \
-    libacdbloader \
     libcutils \
     libutils \
     libmedia \
     libhardware \
     libc        \
     libpower    \
-    libalsa-intf \
-    libcsd-client
+    libalsa-intf
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
 
 LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-alsa
 LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audcal
@@ -140,11 +144,15 @@
     ALSAControl.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-    libacdbloader \
     libcutils \
     liblog    \
-    libalsa-intf \
-    libcsd-client
+    libalsa-intf
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
 
 LOCAL_MODULE:= alsa.msm8960
 LOCAL_MODULE_TAGS := optional
diff --git a/alsa_sound/AudioHardwareALSA.cpp b/alsa_sound/AudioHardwareALSA.cpp
index 6a88074..54f386a 100644
--- a/alsa_sound/AudioHardwareALSA.cpp
+++ b/alsa_sound/AudioHardwareALSA.cpp
@@ -60,6 +60,14 @@
     android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
         return android_audio_legacy::AudioHardwareALSA::create();
     }
+#ifdef QCOM_ACDB_ENABLED
+    static int (*acdb_init)();
+    static void (*acdb_deallocate)();
+#endif
+#ifdef QCOM_CSDCLIENT_ENABLED
+    static int (*csd_start_playback)();
+    static int (*csd_stop_playback)();
+#endif
 }         // extern "C"
 
 namespace android_audio_legacy
@@ -73,7 +81,7 @@
 
 AudioHardwareALSA::AudioHardwareALSA() :
     mALSADevice(0),mVoipStreamCount(0),mVoipMicMute(false),mVoipBitRate(0)
-    ,mCallState(0)
+    ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL)
 {
     FILE *fp;
     char soundCardInfo[200];
@@ -107,11 +115,32 @@
             mFusion3Platform = false;
 
 #ifdef QCOM_ACDB_ENABLED
-            if ((acdb_loader_init_ACDB()) < 0) {
-                ALOGE("Failed to initialize ACDB");
+            mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
+            if (mAcdbHandle == NULL) {
+                ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
+            } else {
+                ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
+                acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
+                if (acdb_init == NULL) {
+                    ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
+                }else {
+                   acdb_init();
+                   acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
+                }
             }
 #endif
 
+#ifdef QCOM_CSDCLIENT_ENABLED
+             mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
+             if (mCsdHandle == NULL) {
+                 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
+             } else {
+                 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
+                 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
+                 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
+             }
+             mALSADevice->setCsdHandle(mCsdHandle);
+#endif
             if((fp = fopen("/proc/asound/cards","r")) == NULL) {
                 ALOGE("Cannot open /proc/asound/cards file to get sound card info");
             } else {
@@ -154,6 +183,12 @@
                 ALOGE("Failed to open ucm instance: %d", errno);
             } else {
                 ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
+                mUcMgr->acdb_handle = NULL;
+#ifdef QCOM_ACDB_ENABLED
+                if (mAcdbHandle) {
+                    mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
+                }
+#endif
             }
         } else {
             ALOGE("ALSA Module could not be opened!!!");
@@ -180,11 +215,26 @@
         mDeviceList.erase(it);
     }
 #ifdef QCOM_ACDB_ENABLED
-    acdb_loader_deallocate_ACDB();
+     if (acdb_deallocate == NULL) {
+        ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
+     } else {
+        acdb_deallocate();
+     }
+     if (mAcdbHandle) {
+        ::dlclose(mAcdbHandle);
+        mAcdbHandle = NULL;
+     }
 #endif
 #ifdef QCOM_USBAUDIO_ENABLED
     delete mAudioUsbALSA;
 #endif
+
+#ifdef QCOM_CSDCLEINT_ENABLED
+     if (mCsdHandle) {
+        ::dlclose(mCsdHandle);
+        mCsdHandle = NULL;
+     }
+#endif
 }
 
 status_t AudioHardwareALSA::initCheck()
@@ -336,10 +386,18 @@
         if (param.get(key, value) == NO_ERROR) {
             if (value == "true") {
                 ALOGV("Enabling Incall Music setting in the setparameter\n");
-                csd_client_start_playback();
+                if (csd_start_playback == NULL) {
+                    ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
+                } else {
+                    csd_start_playback();
+                }
             } else {
                 ALOGV("Disabling Incall Music setting in the setparameter\n");
-                csd_client_stop_playback();
+                if (csd_stop_playback == NULL) {
+                    ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
+                } else {
+                    csd_stop_playback();
+                }
             }
         }
     }
diff --git a/alsa_sound/AudioHardwareALSA.h b/alsa_sound/AudioHardwareALSA.h
index 3ceef99..049a300 100644
--- a/alsa_sound/AudioHardwareALSA.h
+++ b/alsa_sound/AudioHardwareALSA.h
@@ -29,6 +29,8 @@
 #include <system/audio.h>
 #include <hardware/audio.h>
 #include <utils/threads.h>
+#include <dlfcn.h>
+
 #ifdef QCOM_USBAUDIO_ENABLED
 #include <AudioUsbALSA.h>
 #endif
@@ -210,6 +212,9 @@
 #ifdef SEPERATED_AUDIO_INPUT
     void     (*setInput)(int);
 #endif
+#ifdef QCOM_CSDCLIENT_ENABLED
+    void     (*setCsdHandle)(void*);
+#endif
 };
 
 // ----------------------------------------------------------------------------
@@ -404,6 +409,11 @@
 private:
     void                resetFramesLost();
 
+#ifdef QCOM_CSDCLIENT_ENABLED
+    int                 start_csd_record(int);
+    int                 stop_csd_record(void);
+#endif
+
     unsigned int        mFramesLost;
     AudioSystem::audio_in_acoustics mAcoustics;
 
@@ -568,6 +578,8 @@
     int musbPlaybackState;
     int musbRecordingState;
 #endif
+    void *mAcdbHandle;
+    void *mCsdHandle;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/alsa_sound/AudioStreamInALSA.cpp b/alsa_sound/AudioStreamInALSA.cpp
index e63d606..6a04b83 100644
--- a/alsa_sound/AudioStreamInALSA.cpp
+++ b/alsa_sound/AudioStreamInALSA.cpp
@@ -39,7 +39,10 @@
 extern "C" {
 #ifdef QCOM_CSDCLIENT_ENABLED
 #include "csd_client.h"
+static int (*csd_start_record)(int);
+static int (*csd_stop_record)(void);
 #endif
+
 #ifdef QCOM_SSR_ENABLED
 #include "surround_filters_interface.h"
 #endif
@@ -67,8 +70,8 @@
         AudioSystem::audio_in_acoustics audio_acoustics) :
     ALSAStreamOps(parent, handle),
     mFramesLost(0),
-    mParent(parent),
-    mAcoustics(audio_acoustics)
+    mAcoustics(audio_acoustics),
+    mParent(parent)
 #ifdef QCOM_SSR_ENABLED
     , mFp_4ch(NULL),
     mFp_6ch(NULL),
@@ -129,7 +132,7 @@
 
     int n;
     status_t          err;
-    size_t            read = 0;
+    ssize_t            read = 0;
     char *use_case;
     int newMode = mParent->mode();
 
@@ -149,8 +152,8 @@
                         mParent->mALSADevice->setVocRecMode(INCALL_REC_STEREO);
                         strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
                                 sizeof(mHandle->useCase));
-                        csd_client_start_record(INCALL_REC_STEREO);
-                    } else 
+                        start_csd_record(INCALL_REC_STEREO);
+                    } else
 #endif
                     {
                         strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
@@ -162,8 +165,8 @@
                         mParent->mALSADevice->setVocRecMode(INCALL_REC_MONO);
                         strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
                                 sizeof(mHandle->useCase));
-                        csd_client_start_record(INCALL_REC_MONO);
-                    } else 
+                        start_csd_record(INCALL_REC_MONO);
+                    } else
 #endif
                     {
                         strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
@@ -198,8 +201,8 @@
                         mParent->mALSADevice->setVocRecMode(INCALL_REC_STEREO);
                         strlcpy(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC,
                                 sizeof(mHandle->useCase));
-                        csd_client_start_record(INCALL_REC_STEREO);
-                    } else 
+                        start_csd_record(INCALL_REC_STEREO);
+                    } else
 #endif
                     {
                         strlcpy(mHandle->useCase, SND_USE_CASE_VERB_UL_DL_REC,
@@ -211,9 +214,9 @@
                        mParent->mALSADevice->setVocRecMode(INCALL_REC_MONO);
                        strlcpy(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC,
                                sizeof(mHandle->useCase));
-                       csd_client_start_record(INCALL_REC_MONO);
+                       start_csd_record(INCALL_REC_MONO);
                    } else
-#endif            
+#endif
                    {
                        strlcpy(mHandle->useCase, SND_USE_CASE_VERB_DL_REC,
                                sizeof(mHandle->useCase));
@@ -443,7 +446,7 @@
             else {
                 read += static_cast<ssize_t>((period_size));
                 read_pending -= period_size;
-                buffer += period_size;
+                buffer = ((uint8_t *)buffer) + period_size;
             }
 
         } while (mHandle->handle && read < bytes);
@@ -500,7 +503,7 @@
     if (mParent->mFusion3Platform) {
        if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) ||
            (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE))) {
-           csd_client_stop_record();
+           stop_csd_record();
        }
     }
 #endif
@@ -572,7 +575,7 @@
        if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) ||
            (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE))) {
            ALOGD(" into standby, stop record");
-           csd_client_stop_record();
+           stop_csd_record();
        }
     }
 #endif
@@ -843,4 +846,35 @@
 }
 #endif
 
+#ifdef QCOM_CSDCLIENT_ENABLED
+int AudioStreamInALSA::start_csd_record(int param)
+{
+    int err = NO_ERROR;
+
+    if (mParent->mCsdHandle != NULL) {
+        csd_start_record = (int (*)(int))::dlsym(mParent->mCsdHandle,"csd_client_start_record");
+        if (csd_start_record == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_client_start_record", dlerror());
+        } else {
+            err = csd_start_record(param);
+        }
+    }
+    return err;
+}
+
+int AudioStreamInALSA::stop_csd_record()
+{
+    int err = NO_ERROR;
+    if (mParent->mCsdHandle != NULL) {
+        csd_stop_record = (int (*)())::dlsym(mParent->mCsdHandle,"csd_client_stop_record");
+        if (csd_start_record == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_client_start_record", dlerror());
+        } else {
+            csd_stop_record();
+        }
+    }
+    return err;
+}
+#endif
+
 }       // namespace android_audio_legacy
diff --git a/alsa_sound/alsa_default.cpp b/alsa_sound/alsa_default.cpp
index 1754a82..fdc89da 100644
--- a/alsa_sound/alsa_default.cpp
+++ b/alsa_sound/alsa_default.cpp
@@ -24,9 +24,19 @@
 #include <linux/ioctl.h>
 #include "AudioHardwareALSA.h"
 #include <media/AudioRecord.h>
+#include <dlfcn.h>
 #ifdef QCOM_CSDCLIENT_ENABLED
 extern "C" {
 #include "csd_client.h"
+static int (*csd_disable_device)();
+static int (*csd_enable_device)(int, int, uint32_t);
+static int (*csd_volume)(int);
+static int (*csd_mic_mute)(int);
+static int (*csd_wide_voice)(uint8_t);
+static int (*csd_slow_talk)(uint8_t);
+static int (*csd_fens)(uint8_t);
+static int (*csd_start_voice)();
+static int (*csd_stop_voice)();
 }
 #endif
 
@@ -72,6 +82,9 @@
 
 static int input_source;
 #endif
+#ifdef QCOM_CSDCLIENT_ENABLED
+static void     s_set_csd_handle(void*);
+#endif
 
 static char mic_type[25];
 static char curRxUCMDevice[50];
@@ -86,12 +99,14 @@
 static int btsco_samplerate = 8000;
 static bool pflag = false;
 static ALSAUseCaseList mUseCaseList;
+static void *csd_handle;
 
 static hw_module_methods_t s_module_methods = {
     open            : s_device_open
 };
 
-extern "C" hw_module_t HAL_MODULE_INFO_SYM = {
+extern "C" {
+hw_module_t HAL_MODULE_INFO_SYM = {
     tag             : HARDWARE_MODULE_TAG,
     version_major   : 1,
     version_minor   : 0,
@@ -102,6 +117,7 @@
     dso             : 0,
     reserved        : {0,},
 };
+}
 
 static int s_device_open(const hw_module_t* module, const char* name,
         hw_device_t** device)
@@ -145,7 +161,9 @@
 #ifdef SEPERATED_AUDIO_INPUT
     dev->setInput = s_setInput;
 #endif
-
+#ifdef QCOM_CSDCLIENT_ENABLED
+    dev->setCsdHandle = s_set_csd_handle;
+#endif
     *device = &dev->common;
 
     property_get("persist.audio.handset.mic",value,"0");
@@ -420,10 +438,14 @@
 
 #ifdef QCOM_CSDCLIENT_ENABLED
     if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
-        err = csd_client_disable_device();
-        if (err < 0)
-        {
-            ALOGE("csd_client_disable_device, failed, error %d", err);
+        if (csd_disable_device == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
+        } else {
+            err = csd_disable_device();
+            if (err < 0)
+            {
+                ALOGE("csd_client_disable_device, failed, error %d", err);
+            }
         }
     }
 #endif
@@ -537,10 +559,14 @@
 
 #ifdef QCOM_CSDCLIENT_ENABLED
         ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
-        err = csd_client_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
-        if (err < 0)
-        {
-            ALOGE("csd_client_disable_device failed, error %d", err);
+        if (csd_enable_device == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
+        } else {
+            err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
+            if (err < 0)
+            {
+                ALOGE("csd_client_disable_device failed, error %d", err);
+            }
         }
 #endif
     }
@@ -875,10 +901,14 @@
 
     if (platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-        err = csd_client_start_voice();
-        if (err < 0) {
-            ALOGE("s_start_voice_call: csd_client error %d\n", err);
-            goto Error;
+        if (csd_start_voice == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
+        } else {
+            err = csd_start_voice();
+            if (err < 0){
+                ALOGE("s_start_voice_call: csd_client error %d\n", err);
+                goto Error;
+            }
         }
 #endif
     }
@@ -1065,9 +1095,13 @@
              !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
             platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-            err = csd_client_stop_voice();
-            if (err < 0) {
-                ALOGE("s_close: csd_client error %d\n", err);
+            if (csd_stop_voice == NULL) {
+                ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
+            } else {
+                err = csd_stop_voice();
+                if (err < 0) {
+                    ALOGE("s_close: csd_client error %d\n", err);
+                }
             }
 #endif
         }
@@ -1476,9 +1510,13 @@
 
     if (platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-        err = csd_client_volume(vol);
-        if (err < 0) {
-            ALOGE("s_set_voice_volume: csd_client error %d", err);
+        if (csd_volume == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
+        } else {
+            err = csd_volume(vol);
+            if (err < 0) {
+                ALOGE("s_set_voice_volume: csd_client error %d", err);
+            }
         }
 #endif
     }
@@ -1513,9 +1551,13 @@
 
     if (platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-        err = csd_client_mic_mute(state);
-        if (err < 0) {
-            ALOGE("s_set_mic_mute: csd_client error %d", err);
+        if (csd_mic_mute == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
+        } else {
+            err=csd_mic_mute(state);
+            if (err < 0) {
+                ALOGE("s_set_mic_mute: csd_client error %d", err);
+            }
         }
 #endif
     }
@@ -1593,9 +1635,13 @@
 
     if (platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-        err == csd_client_wide_voice(flag);
-        if (err < 0) {
-            ALOGE("s_enable_wide_voice: csd_client error %d", err);
+        if (csd_wide_voice == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
+        } else {
+            err = csd_wide_voice(flag);
+            if (err < 0) {
+                ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
+            }
         }
 #endif
     }
@@ -1626,9 +1672,13 @@
 
     if (platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-        err = csd_client_fens(flag);
-        if (err < 0) {
-            ALOGE("s_enable_fens: csd_client error %d", err);
+        if (csd_fens == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
+        } else {
+            err = csd_fens(flag);
+            if (err < 0) {
+                ALOGE("s_enable_fens: csd_client error %d", err);
+            }
         }
 #endif
     }
@@ -1650,9 +1700,13 @@
 
     if (platform_is_Fusion3()) {
 #ifdef QCOM_CSDCLIENT_ENABLED
-        err = csd_client_slow_talk(flag);
-        if (err < 0) {
-            ALOGE("s_enable_slow_talk: csd_client error %d", err);
+        if (csd_slow_talk == NULL) {
+            ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
+        } else {
+            err = csd_slow_talk(flag);
+            if (err < 0) {
+                ALOGE("s_enable_slow_talk: csd_client error %d", err);
+            }
         }
 #endif
     }
@@ -1681,4 +1735,23 @@
     ALOGD("s_setInput() : input_source = %d",input_source);
 }
 #endif
+
+#ifdef QCOM_CSDCLIENT_ENABLED
+static void  s_set_csd_handle(void* handle)
+{
+    csd_handle = static_cast<void*>(handle);
+    ALOGI("%s csd_handle: %p", __func__, csd_handle);
+
+    csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
+    csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
+    csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
+    csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
+    csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
+    csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
+    csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
+    csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
+    csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
+}
+#endif
+
 }