[Feature] add GA346 baseline version

Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/multimedia/audio-tuning/audio-xml-parser/mt2635/UnitTest.c b/src/multimedia/audio-tuning/audio-xml-parser/mt2635/UnitTest.c
new file mode 100644
index 0000000..78dfd7f
--- /dev/null
+++ b/src/multimedia/audio-tuning/audio-xml-parser/mt2635/UnitTest.c
@@ -0,0 +1,564 @@
+#include "AudioParamParserPriv.h"
+
+typedef APP_STATUS(*TEST_FUN)(AppHandle *appHandle);
+
+typedef struct
+{
+    AppHandle *appHandle;
+    int times;
+    TEST_FUN fun;
+} ThreadParam;
+
+EXPORT APP_STATUS unitTest(AppHandle *appHandle)
+{
+    APP_STATUS res = APP_NO_ERROR;
+    APP_STATUS finalRes = APP_NO_ERROR;
+
+    printf("===APP internal unit test===\n");
+#if 0
+    res = testAppHandleInitUninit();
+    if (res == APP_ERROR)
+    {
+        finalRes = APP_ERROR;
+    }
+    printf("testAppHandleInitUninit: %s\n", res ? "pass" : "fail");
+#endif
+    res = testReadWriteParam(appHandle);
+    if (res == APP_ERROR)
+    {
+        finalRes = APP_ERROR;
+    }
+    printf("testReadWriteParam: %s\n", res ? "pass" : "fail");
+
+    res = testMemoryLeak(appHandle);
+    if (res == APP_ERROR)
+    {
+        finalRes = APP_ERROR;
+    }
+    printf("testMemoryLeak: %s\n", res ? "pass" : "fail");
+
+    res = testAudioTypeLock(appHandle);
+    if (res == APP_ERROR)
+    {
+        finalRes = APP_ERROR;
+    }
+    printf("testAudioTypeLock: %s\n", res ? "pass" : "fail");
+    printf("=============================\n");
+
+    return finalRes;
+}
+
+
+EXPORT void *commonThreadLoop(void *arg)
+{
+    ThreadParam threadParam = *(ThreadParam *)arg;
+    int i = 0 ;
+    for (i = 0; i < threadParam.times; i++)
+    {
+        (*threadParam.fun)(threadParam.appHandle);
+        INFO_LOG("2nd thread round = %d\n", i);
+    }
+    return NULL;
+}
+
+EXPORT void testDebugLevel()
+{
+    appSetDebugLevel(ERR_LEVEL);
+    ERR_LOG("error - pass\n");
+    WARN_LOG("warn - ok\n");
+    INFO_LOG("info - ok\n");
+    DEBUG_LOG("debug - ok\n");
+
+    appSetDebugLevel(WARN_LEVEL);
+    ERR_LOG("error - fail\n");
+    WARN_LOG("warn - pass\n");
+    INFO_LOG("info - ok\n");
+    DEBUG_LOG("debug - ok\n");
+
+    appSetDebugLevel(INFO_LEVEL);
+    ERR_LOG("error - fail\n");
+    WARN_LOG("warn - fail\n");
+    INFO_LOG("info - pass\n");
+    DEBUG_LOG("debug - ok\n");
+
+    appSetDebugLevel(DEBUG_LEVEL);
+    ERR_LOG("error - fail\n");
+    WARN_LOG("warn - fail\n");
+    INFO_LOG("info - fail\n");
+    DEBUG_LOG("debug - pass\n");
+}
+
+EXPORT void testHashParamTree()
+{
+    ParamTree *item;
+    ParamTree *ParamTreeHash = NULL, *tmp = NULL; /* Used for hash */
+    const char *key;
+
+    item = (ParamTree *)malloc(sizeof(ParamTree));
+    item->categoryPath = "NB,Normal,,";
+    item->paramId = 1;
+    HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
+
+    item = (ParamTree *)malloc(sizeof(ParamTree));
+    item->categoryPath = "WB,Normal,,";
+    item->paramId = 7;
+    HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
+
+    item = (ParamTree *)malloc(sizeof(ParamTree));
+    item->categoryPath = "NB,Normal,0,GSM,";
+    item->paramId = 1;
+    HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
+
+    item = (ParamTree *)malloc(sizeof(ParamTree));
+    item->categoryPath = "NB,HAC,0,GSM";
+    item->paramId = 0;
+    HASH_ADD_KEYPTR(hh, ParamTreeHash, item->categoryPath, strlen(item->categoryPath), item);
+
+    /* Find string */
+    key = "WB,,,";
+    HASH_FIND_STR(ParamTreeHash, key, item);
+    if (item) { printf("[%s] id is %d\n", key, item->paramId); }
+
+    /* Free hash table content */
+    HASH_ITER(hh, ParamTreeHash, item, tmp)
+    {
+        HASH_DEL(ParamTreeHash, item);
+        free(item);
+    }
+}
+
+EXPORT void testHashParamUnit()
+{
+    ParamUnit *item;
+    ParamUnit *ParamUnitHash = NULL, *tmp = NULL; /* Used for hash */
+    int key;
+
+    item = (ParamUnit *)malloc(sizeof(ParamUnit));
+    item->paramId = 0;
+    item->paramHash = (Param *) 0x1;
+    HASH_ADD_INT(ParamUnitHash, paramId, item);
+
+    item = (ParamUnit *)malloc(sizeof(ParamUnit));
+    item->paramId = 1;
+    item->paramHash = (Param *)0x2;
+    HASH_ADD_INT(ParamUnitHash, paramId, item);
+    item = (ParamUnit *)malloc(sizeof(ParamUnit));
+
+    item->paramId = 7;
+    item->paramHash = (Param *)0x3;
+    HASH_ADD_INT(ParamUnitHash, paramId, item);
+
+    /* Find string */
+    key = 0;
+    HASH_FIND_INT(ParamUnitHash, &key, item);
+    if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); }
+
+    key = 1;
+    HASH_FIND_INT(ParamUnitHash, &key, item);
+    if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); }
+
+    key = 7;
+    HASH_FIND_INT(ParamUnitHash, &key, item);
+    if (item) { INFO_LOG("[%d] Param is %p\n", key, item->paramHash); }
+
+    /* Free hash table content */
+    HASH_ITER(hh, ParamUnitHash, item, tmp)
+    {
+        HASH_DEL(ParamUnitHash, item);
+        free(item);
+    }
+}
+
+EXPORT void testHashParam()
+{
+    Param *item;
+    Param *paramHash = NULL, *tmp = NULL; /* Used for hash */
+    const char *key;
+
+    item = (Param *)malloc(sizeof(Param));
+    memset(item, 0, sizeof(Param));
+    item->name = "speech_mode_para";
+    item->data = "0x0011,0x2233,0x4455";
+    HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item);
+
+    item = (Param *)malloc(sizeof(Param));
+    memset(item, 0, sizeof(Param));
+    item->name = "uint_param";
+    item->data = "4294967295";
+    HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item);
+
+    item = (Param *)malloc(sizeof(Param));
+    memset(item, 0, sizeof(Param));
+    item->name = "float_param";
+    item->data = "0.1234567";
+    HASH_ADD_KEYPTR(hh, paramHash, item->name, strlen(item->name), item);
+
+    /* Find string */
+    key = "speech_mode_para";
+    HASH_FIND_STR(paramHash, key, item);
+    if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); }
+
+    key = "uint_param";
+    HASH_FIND_STR(paramHash, key, item);
+    if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); }
+
+    key = "float_param";
+    HASH_FIND_STR(paramHash, key, item);
+    if (item) { INFO_LOG("[%s] value is %s\n", key, (char *)item->data); }
+
+    /* Free hash table content */
+    HASH_ITER(hh, paramHash, item, tmp)
+    {
+        HASH_DEL(paramHash, item);
+        free(item);
+    }
+}
+
+void testCb(AppHandle *appHandle, const char *audioTypeName)
+{
+    printf("XML file changed. (cus folder = %s, audioType = %s)\n", appHandle->xmlCusDir, audioTypeName);
+}
+
+EXPORT void notifyCbTest(AppHandle *appHandle)
+{
+    NotifyCb *cb;
+
+    appHandleRegXmlChangedCb(appHandle, testCb);
+
+    LL_FOREACH(appHandle->noficyCbList, cb)
+    {
+        (*cb->cb)(appHandle, "OK");
+    }
+
+    appHandleUnregXmlChangedCb(appHandle, testCb);
+
+    LL_FOREACH(appHandle->noficyCbList, cb)
+    {
+        (*cb->cb)(appHandle, "FAIL");
+    }
+}
+
+EXPORT void inotifyTest(const char *path)
+{
+
+#ifndef WIN32
+#define INOTIFY_BUF_SIZE 512
+    /* inotify test */
+    int wd;
+    size_t len;
+    char buf[INOTIFY_BUF_SIZE];
+    char *ptr;
+    const struct inotify_event *event;
+
+    int fd = inotify_init();
+    if (fd < 0)
+    {
+        printf("inotify_init failed !!!");
+        exit(1);
+    }
+
+    printf("inotify path = %s\n", path);
+    wd = inotify_add_watch(fd, path, IN_CLOSE_WRITE);
+    if (wd < 0)
+    {
+        printf("inotify_add_watch failed !!!");
+        exit(1);
+    }
+
+    while (1)
+    {
+        len = read(fd, buf, sizeof(buf));
+        if (len < 0)
+        {
+            perror("read");
+            exit(EXIT_FAILURE);
+        }
+
+        /* Loop over all events in the buffer */
+        for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len)
+        {
+            event = (const struct inotify_event *) ptr;
+
+            /* Print event type */
+            if (event->mask & IN_OPEN)
+            {
+                printf("IN_OPEN: ");
+            }
+            if (event->mask & IN_CLOSE_NOWRITE)
+            {
+                printf("IN_CLOSE_NOWRITE: ");
+            }
+            if (event->mask & IN_CLOSE_WRITE)
+            {
+                printf("IN_CLOSE_WRITE: ");
+            }
+            if (event->mask & IN_ACCESS)
+            {
+                printf("IN_ACCESS: ");
+            }
+
+            /* Print the name of the file */
+
+            if (event->len)
+            {
+                printf("%s", event->name);
+            }
+
+            /* Print type of filesystem object */
+
+            if (event->mask & IN_ISDIR)
+            {
+                printf(" [directory]\n");
+            }
+            else
+            {
+                printf(" [file]\n");
+            }
+        }
+    }
+    inotify_rm_watch(fd, IN_CLOSE_NOWRITE);
+#endif
+}
+
+/***********************************
+ * Test Steps:
+ * 1. Create thread to read/write param
+ * 2. Check the lock is work well
+ * Crash/deadlock checking
+ **********************************/
+EXPORT APP_STATUS testAudioTypeLockFun(AppHandle *appHandle)
+{
+    /* Read param */
+    char *audioTypeName = "Speech";
+    char *categoryPath = "Band,NB,Profile,4_pole_Headset,VolIndex,3";
+    char *paramName = "speech_mode_para";
+    unsigned short shortArray1[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
+    unsigned short shortArray2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+    int arraySize = 7;
+    AudioType *audioType;
+    ParamUnit *paramUnit;
+    ParamInfo *paramInfo;
+    Param *param;
+
+    appHandle = appHandleGetInstance();
+
+    /* Query AudioType */
+    audioType = appHandleGetAudioTypeByName(appHandle, audioTypeName);
+    if (!audioType)
+    {
+        ERR_LOG("audioType is NULL\n");
+        return APP_ERROR;
+    }
+
+    /* Read Lock */
+    audioTypeReadLock(audioType, __FUNCTION__);
+
+    /* Query the ParamUnit */
+    paramUnit = audioTypeGetParamUnit(audioType, categoryPath);
+    if (!paramUnit)
+    {
+        ERR_LOG("paramUnit is NULL\n");
+        return APP_ERROR;
+    }
+
+    /* Query the param value */
+    param = paramUnitGetParamByName(paramUnit, paramName);
+    if (!param)
+    {
+        ERR_LOG("Error: Cannot query param value!\n");
+        return APP_ERROR;
+    }
+
+    /* Read unlock */
+    audioTypeUnlock(audioType);
+
+    utilUsleep(1);  // delay time make cpu scheduling to other thread
+
+    /* Write param */
+    paramInfo = audioTypeGetParamInfoByName(audioType, paramName);
+    if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray1, arraySize) == APP_ERROR)
+    {
+        ERR_LOG("Cannot update the param data!!\n");
+        return APP_ERROR;
+    }
+
+    utilUsleep(1);  // delay time make cpu scheduling to other thread
+
+    if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray2, arraySize) == APP_ERROR)
+    {
+        ERR_LOG("Cannot update the param data!!\n");
+        return APP_ERROR;
+    }
+
+    utilUsleep(1);  // delay time make cpu scheduling to other thread
+
+    /* Save XML */
+    audioTypeSaveAudioParamXml(audioType, XML_CUS_FOLDER_ON_DEVICE, 1);
+
+    utilUsleep(1);  // delay time make cpu scheduling to other thread
+
+    /* Reload XML */
+    appHandleReloadAudioType(appHandle, audioType->name);
+
+    return APP_NO_ERROR;
+}
+
+EXPORT APP_STATUS testAudioTypeLock(AppHandle *appHandle)
+{
+#ifndef WIN32
+    int i;
+    pthread_t appThread;
+    void *status;
+    ThreadParam threadParam;
+
+    threadParam.times = 50;
+    threadParam.appHandle = appHandle;
+    threadParam.fun = testAudioTypeLockFun;
+
+    if (pthread_create(&appThread, NULL, commonThreadLoop, &threadParam))
+    {
+        ERR_LOG("Create app thread fail!\n");
+        return APP_ERROR;
+    }
+
+    for (i = 0; i < threadParam.times; i++)
+    {
+        (*threadParam.fun)(appHandle);
+        INFO_LOG("Main thread test round = %d\n", i);
+    }
+
+    /* Waiting 2nd thread join */
+    pthread_join(appThread, &status);
+#else
+    INFO_LOG("Not test this UT on windows\n");
+#endif
+    return APP_NO_ERROR;
+}
+
+EXPORT APP_STATUS testAppHandleInitUninit()
+{
+    int times = 10;
+    int i;
+    for (i = 0; i < times; i++)
+    {
+        AppHandle testAppHandle;
+        appHandleInit(&testAppHandle);
+#ifdef WIN32
+        appHandleParseXml(&testAppHandle, XML_FOLDER_ON_TUNING_TOOL, XML_CUS_FOLDER_ON_TUNING_TOOL);
+#else
+        appHandleParseXml(&testAppHandle, XML_FOLDER_ON_DEVICE, XML_CUS_FOLDER_ON_DEVICE);
+#endif
+        appHandleUninit(&testAppHandle);
+    }
+    return APP_NO_ERROR;
+}
+
+/***********************************
+ * Test Steps:
+ * 1. Reload audio type xml 100 times
+ * Memory leak / crash checking
+ **********************************/
+EXPORT APP_STATUS testMemoryLeak(AppHandle *appHandle)
+{
+    int i = 0;
+    for (i = 0; i < 100; i++)
+    {
+        /* stress test query / release / create */
+        AudioType *audioType = appHandleGetAudioTypeByName(appHandle, "Speech");
+        audioType->allowReload = 1;
+        if (appHandleReloadAudioType(appHandle, "Speech") == APP_ERROR)
+        {
+            return APP_ERROR;
+        }
+    }
+
+    printf("Checking memory status and press enter key to continue\n");
+    getchar();
+    return APP_NO_ERROR;
+}
+
+/***********************************
+ * Test Steps:
+ * 1. Read param array
+ * 2. Update param array one item with 32767
+ * 3. Repeat array size times
+ * 4. Check the result
+ **********************************/
+APP_STATUS testReadWriteParam(AppHandle *appHandle)
+{
+    size_t i, j;
+    ParamUnit *paramUnit;
+    ParamInfo *paramInfo;
+    Param *param;
+    unsigned short *shortArray;
+    size_t arraySize = 1;  // The size will update by real array size latter
+
+    const char *audioTypeName = "Speech";
+    const char *paraName = "speech_mode_para";
+    const char *categoryPath = "Band,NB,Profile,Normal,VolIndex,2,Network,GSM";
+
+    AudioType *audioType = appHandleGetAudioTypeByName(appHandle, audioTypeName);
+
+    /* Test steps */
+    for (j = 0; j < arraySize; j++)
+    {
+        paramUnit = audioTypeGetParamUnit(audioType, categoryPath);
+        if (!paramUnit)
+        {
+            ERR_LOG("Cannot find paramUnit\n");
+            return APP_ERROR;
+        }
+
+        param = paramUnitGetParamByName(paramUnit, paraName);
+        if (!param)
+        {
+            ERR_LOG("Cannot query param value!\n");
+            return APP_ERROR;
+        }
+
+        shortArray = (unsigned short *)param->data;
+        arraySize = param->arraySize;
+        /*for(i = 0; i < param->arraySize; i++)
+        {
+            printf("[%d]0x%x\n", i, ((unsigned short*)param->data)[i])
+        }*/
+
+        shortArray[j] = 32767;
+
+        /* You should cache follow object in somewhere without query again */
+        paramInfo = audioTypeGetParamInfoByName(audioType, paraName);
+
+        /* The sph_in_fir param is short array type */
+        if (audioTypeSetParamData(audioType, categoryPath, paramInfo, (void *)shortArray, param->arraySize) == APP_ERROR)
+        {
+            return APP_ERROR;
+        }
+    }
+
+    /* Result check */
+    paramUnit = audioTypeGetParamUnit(audioType, categoryPath);
+    if (!paramUnit)
+    {
+        ERR_LOG("Cannot find paramUnit\n");
+        return APP_ERROR;
+    }
+
+    param = paramUnitGetParamByName(paramUnit, paraName);
+    if (!param)
+    {
+        ERR_LOG("Cannot query param value!\n");
+        return APP_ERROR;
+    }
+
+    shortArray = (unsigned short *)param->data;
+    for (i = 0; i < param->arraySize; i++)
+    {
+        if (shortArray[i] != 32767)
+        {
+            ERR_LOG("Verify short array[%lu] = %d != 32767\n", i, shortArray[i]);
+            return APP_ERROR;
+        }
+    }
+
+    return APP_NO_ERROR;
+}