[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/connectivity/gps/gnss_test/LICENSE b/src/connectivity/gps/gnss_test/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/connectivity/gps/gnss_test/Makefile.am b/src/connectivity/gps/gnss_test/Makefile.am
new file mode 100644
index 0000000..a0223c5
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/Makefile.am
@@ -0,0 +1,22 @@
+AUTOMAKE_OPTIONS=foreign subdir-objects
+bin_PROGRAMS = mnld_test fm_gnss
+
+
+AM_CFLAGS = -Imnld_client/inc \
+            -Imnld_fm/inc \
+            -I../gps_hal/inc \
+            -I../gps_hal/inc/hardware \
+            -DLIB_GNSS_HAL_DIR='"$(libdir)"'
+AM_CFLAGS+=$(DNS_FLAGS)
+
+mnld_test_SOURCES = mnld_client/src/mnld_client.c \
+            mnld_client/src/mnld_client_gps_cb.c
+
+mnld_test_LDADD = -lpthread -lrt -ldl -lgpshal
+
+fm_gnss_SOURCES = mnld_fm/src/mnld_fm.c \
+            mnld_fm/src/mnld_fm_gps_cb.c
+
+fm_gnss_LDADD = -lpthread -lrt -ldl -lgpshal
+
+DEFS+=-D__LINUX_OS__ -DMTK_GPS_DATA_PATH="\"/usr/share/gps/\""
diff --git a/src/connectivity/gps/gnss_test/configure.ac b/src/connectivity/gps/gnss_test/configure.ac
new file mode 100644
index 0000000..dc67558
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/configure.ac
@@ -0,0 +1,8 @@
+AC_INIT([gpstest], [1.0])
+AM_INIT_AUTOMAKE([foreign])
+AC_CONFIG_HEADER(defines.h)
+AC_PROG_CC
+AC_DISABLE_STATIC
+LT_INIT
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/src/connectivity/gps/gnss_test/mnld_client/inc/mnld_test.h b/src/connectivity/gps/gnss_test/mnld_client/inc/mnld_test.h
new file mode 100644
index 0000000..5ac1276
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_client/inc/mnld_test.h
@@ -0,0 +1,82 @@
+#ifndef __MNLD_TEST_H__
+#define __MNLD_TEST_H__
+
+#include"hal_mnl_interface_common.h"
+#include"gps_mtk.h"
+
+#define MNLD_TEST_CMD_OPEN "start"
+#define MNLD_TEST_CMD_CLOSE "stop"
+#define MNLD_TEST_CMD_NETWORK "network"
+#define MNLD_TEST_NETWORK_WIFI "wifi"
+#define MNLD_TEST_NETWORK_MOBILE "mobile"
+#define MNLD_TEST_NETWORK_ROAMING "roaming"
+#define MNLD_TEST_NETWORK_DISABLE "disable"
+
+#define MNL_VER_LEN 52
+#define MNL_UTC_TIME_LEN 11
+#define MNLD_TEST_TTFF_SESSION_BEGIN
+
+typedef enum{
+    MNLD_TEST_ACTION_UNKNOWN = -1,
+    MNLD_TEST_ACTION_GNSS_OPEN,
+    MNLD_TEST_ACTION_GNSS_CLOSE,
+    MNLD_TEST_ACTION_SET_NETWORK,
+    MNLD_TEST_ACTION_MAX
+} MNLD_TEST_ACTION;
+
+typedef enum{
+    MNLD_TEST_RESTART_TYPE_UNKNOWN = -1,
+    MNLD_TEST_RESTART_TYPE_HOT,
+    MNLD_TEST_RESTART_TYPE_WARM,
+    MNLD_TEST_RESTART_TYPE_COLD,
+    MNLD_TEST_RESTART_TYPE_FULL,
+    MNLD_TEST_RESTART_TYPE_MAX
+} MNLD_TEST_RESTART_TYPE;
+
+typedef enum{
+    CURR = 0,
+    MIN = 1,
+    MAX = 2,
+    MEAN = 3,
+    TTFF_NUM
+}MNLD_TEST_TTFF;
+
+typedef struct {
+    char chip_ver[12];
+    char mnl_ver[MNL_VER_LEN];
+    char clk_type;
+    char clk_buff;
+    int ttff[TTFF_NUM];//time-to-first_fix in ms
+    int fix_type;
+    GpsLocation_ext location;
+    char utc_time[MNL_UTC_TIME_LEN];
+}mnld_test_result;
+
+typedef struct{
+    char type_int;
+    char type_str[10];
+}clock_type;
+
+#define MNLD_TEST_CMD_CNT_MAX 5
+#define GPS_DELETE_EPHEMERIS        0x0001
+#define GPS_DELETE_ALMANAC          0x0002
+#define GPS_DELETE_POSITION         0x0004
+#define GPS_DELETE_TIME             0x0008
+#define GPS_DELETE_IONO             0x0010
+#define GPS_DELETE_UTC              0x0020
+#define GPS_DELETE_HEALTH           0x0040
+#define GPS_DELETE_SVDIR            0x0080
+#define GPS_DELETE_SVSTEER          0x0100
+#define GPS_DELETE_SADATA           0x0200
+#define GPS_DELETE_RTI              0x0400
+#define GPS_DELETE_CELLDB_INFO      0x8000
+#define GPS_DELETE_ALL              0xFFFF
+
+
+GpsCallbacks_ext* mnld_test__get_gps_callbacks(void);
+//GpsInterface* gps_device__get_gps_interface(struct gps_device_t* device);
+
+void mnld_test_show_test_result(mnld_test_result* result);
+void mnld_test_get_mnl_ver(void);
+
+#endif //__MNLD_TEST_H__
diff --git a/src/connectivity/gps/gnss_test/mnld_client/inc/mtk_auto_log.h b/src/connectivity/gps/gnss_test/mnld_client/inc/mtk_auto_log.h
new file mode 100644
index 0000000..a066a61
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_client/inc/mtk_auto_log.h
@@ -0,0 +1,186 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef MTK_AUTO_LOG_H
+#define MTK_AUTO_LOG_H
+
+/**
+ *  @enum LOG_LEVEL
+ *  @brief Define Log Level
+ */
+typedef enum {
+    L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifndef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gnss_mnld_test"
+#endif
+
+#include <string.h>
+
+int set_log_level(int *dst_level, int src_level);
+
+extern int log_dbg_level;
+#define LOG_IS_ENABLED(level) (log_dbg_level <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+#define  ANDROID_MNLD_PROP_SUPPORT 1
+
+#include <cutils/sockets.h>
+#include <log/log.h>     /*logging in logcat*/
+#include <cutils/android_filesystem_config.h>
+#include <cutils/properties.h>
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+        do {\
+                if (LOG_IS_ENABLED(loglevel)) {\
+                    switch (loglevel){\
+                        case L_ASSERT:\
+                        {\
+                            ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_ERROR:\
+                        {\
+                            ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_WARN:\
+                        {\
+                            ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_INFO:\
+                        {\
+                            ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_DEBUG:\
+                        {\
+                            ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_VERBOSE:\
+                        {\
+                            ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                    }\
+                }\
+        } while (0)
+
+#define LOGA(fmt, args...)    PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...)    PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...)    PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...)    PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...)    PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...)    PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define  TRC(f)       ALOGD("%s", __func__)
+
+#elif defined(__LINUX_OS__)
+
+#include <stdio.h>
+#define  ANDROID_MNLD_PROP_SUPPORT 0
+
+
+char time_buff[64];
+int get_time_str(char* buf, int len);
+
+#ifndef gettid
+#include <unistd.h>
+#include <sys/syscall.h>
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+        do {\
+                if (LOG_IS_ENABLED(loglevel)) {\
+                    get_time_str(time_buff, sizeof(time_buff));\
+                    printf("%ld %ld [%s]" LOG_TAG tag "%s %s %d "  fmt "\n",\
+                        getpid(), gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                    fflush(stdout);\
+                }\
+        } while (0)
+
+#define LOGA(fmt, args...)    PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...)    PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...)    PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...)    PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...)    PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...)    PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#define  TRC(f)       ((void)0)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+        do {\
+                if (LOG_IS_ENABLED(loglevel)) {\
+                    dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+                    printf(fmt "\n", ##args);
+                    fflush(stdout);\
+                }\
+        } while (0)
+
+#define LOGA(fmt, args...)    PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...)    PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...)    PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...)    PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...)    PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...)    PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#endif
+
+#endif
diff --git a/src/connectivity/gps/gnss_test/mnld_client/src/mnld_client.c b/src/connectivity/gps/gnss_test/mnld_client/src/mnld_client.c
new file mode 100644
index 0000000..6b86406
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_client/src/mnld_client.c
@@ -0,0 +1,636 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include "hal2mnl_interface.h"
+#include "gps_mtk.h"
+#include "mnld_test.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldtest"
+#endif
+
+int log_dbg_level = L_VERBOSE;
+
+#ifdef CONFIG_GPS_MT3303
+#define MNLD_TEST_CHIP_VER "MT3303"
+#else
+#define MNLD_TEST_CHIP_VER "MT6630"
+#endif
+#define MNLD_TEST_MNL_VER mnld_test_mnl_ver
+#define MNLD_TEST_CLOCK_TYPE 0xFF
+#define MNLD_TEST_CLOCK_BUFF 2
+
+/*Socket port nubmer*/
+#define PORT 7000
+/*The max length of socket receive buffer*/
+#define MNL_TEST_REC_BUFF_LEN 2048
+
+#define MNL_TEST_MNL_VER_PMTK "$PMTK705"
+#define mnld_test_printf printf
+
+GpsCallbacks_ext* mnld_test_cbs = NULL;
+GpsInterface_ext* mnld_test_gpsinfs = NULL;
+
+
+int valid_ttff_cnt = 0;
+int valid_ttff_sum = 0;
+
+int mnld_test_session_end = 0;
+int mnld_test_ttff = 0;
+int mnld_test_restart_cnt = 0;
+int mnld_test_restart_time = 0;
+int mnld_test_restart_interval = 0;
+
+int mnld_test_network_type = NETWORK_TYPE_WIFI;
+int mnld_test_network_on = 0;
+int mnld_test_network_roaming = 0;
+
+timer_t mnld_test_restart_timer = 0;
+MNLD_TEST_RESTART_TYPE mnld_test_restart_type = MNLD_TEST_RESTART_TYPE_HOT;
+struct timespec mnld_test_gnss_open_tm;
+char mnld_test_mnl_ver[MNL_VER_LEN];
+extern mnld_test_result mnld_test_result_body;
+
+clock_type mnld_test_clock_type[] = {
+    {0xFE,"Co-Clock"},
+    {0xFF,"TCXO"}
+};
+
+#define MNLD_TEST_NETWORK_TYPE_STR_LEN 8
+const char mnld_test_network_type_str[][MNLD_TEST_NETWORK_TYPE_STR_LEN] = {
+    {"mobile"},
+    {"wifi"}
+};
+
+void mnld_test_show_help(void)
+{
+    mnld_test_printf("MNLD client test :\r\n");
+    mnld_test_printf("------------------------------------------------------------------------------\r\n");
+    mnld_test_printf("The command to start GNSS test:\r\n");
+    mnld_test_printf("\tmnld_test start [start type] [restart times] [restart interval]\r\n");
+    mnld_test_printf("\t\t[start type]: \r\n\t\th/H: hot start;\r\n\t\tw/W: Warm start;\r\n\t\tc/C: Cold start;\r\n\t\tf/F: Full start\r\n");
+    mnld_test_printf("\t\t[restart times]: integer value, range is 0-1000, default is 0(no restart, always on). \r\n");
+    mnld_test_printf("\t\t[restart interval]: integer value, range is 0-3600, the unit is second; the default value is 60\r\n");
+    mnld_test_printf("------------------------------------------------------------------------------\r\n");
+    mnld_test_printf("The command to stop GNSS test:\r\n");
+    mnld_test_printf("\tmnld_test stop\r\n");
+    mnld_test_printf("------------------------------------------------------------------------------\r\n");
+    mnld_test_printf("The command to update network status:\r\n");
+    mnld_test_printf("\tmnld_test network [type] [roaming]\r\n");
+    mnld_test_printf("\t[type]: wifi, mobile, disable\r\n");
+    mnld_test_printf("\t[roaming]: roaming, the mobile network is in roaming state\r\n");
+}
+
+/*
+Function:mnld_test_socket_open
+Description:open and connect a INET socket by given port number
+Param:[IN] port, the port number of socket
+Param:[OUT] fd, the socket fd
+Return:NULL -- some thing is incorrect; Other value -- open and connect sokcet successfully
+*/
+int mnld_test_socket_open(int port)
+{
+    struct sockaddr_in servaddr;
+    int socketfd = 0;
+
+    if((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    {
+        LOGE("Create socket error:%d,%s\n", errno, strerror(errno));
+        return socketfd;
+    }
+
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons(port);
+    servaddr.sin_addr.s_addr = INADDR_ANY;
+
+    if( connect(socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 )
+    {
+        LOGE("connect error:%d,%s\n", errno, strerror(errno));
+        return -1;
+    }
+
+    return(socketfd);
+}
+
+#ifdef CONFIG_GPS_MT3303
+void mnld_test_get_mnl_ver(void )
+{
+    LOGI("GNSS chip is 3303, there is no MNL.");
+    strcpy(mnld_test_mnl_ver, "GNSS chip is 3303,there is no MNL");
+}
+#else
+#ifdef MTK_ADR_SUPPORT
+void mnld_test_get_mnl_ver(void )
+{
+    LOGI("ADR has used the port 7000, the mnl version is static.");
+    strcpy(mnld_test_mnl_ver, "MNL_VER_18070301ALPS05_5.5U_25");
+}
+#else
+void mnld_test_get_mnl_ver(void )
+{
+    int sock_fd = 0;
+    int rec_len = 0;
+    int raw_socket_connected = 1;
+    char rec_buff[MNL_TEST_REC_BUFF_LEN+1] = {0};
+    char *mnl_ver_addr = NULL;
+    int i = 0;
+    int got_mnl_ver = 0;
+    int retry_cnt = 0;
+
+    if((sock_fd = mnld_test_socket_open(PORT)) < 0 )
+    {
+        LOGE("Socket open error\n");
+        strcpy(mnld_test_mnl_ver,"UNKNOWN");
+        //raw_socket_connected = 0;
+    }else//    if(raw_socket_connected)
+    {
+        char *outbuff = "$PMTK605*31\r\n";
+        int cmd_sent = 0;
+        do{
+           // if((cmd_sent == 0) && send(sock_fd,outbuff,strlen(outbuff)+1, 0) == -1)
+            if((cmd_sent == 0) && hal2mnl_send_pmtk(outbuff,strlen(outbuff)) == -1)
+            {
+                cmd_sent = 0;
+                LOGE("Socket send error(%s)\n",strerror(errno));
+            }else{
+                cmd_sent = 1;
+                if((rec_len = recv(sock_fd, rec_buff, MNL_TEST_REC_BUFF_LEN, 0)) < 0)
+                {
+                    LOGE("Recieve error(%d):%s\n",errno, strerror(errno));
+                    usleep(20000);
+                }else{
+                    rec_buff[rec_len] = '\0';
+                    if(strncmp(rec_buff, MNL_TEST_MNL_VER_PMTK, strlen(MNL_TEST_MNL_VER_PMTK)) == 0)
+                    {
+                        mnl_ver_addr = strstr(rec_buff,"MNL_VER");
+                        strncpy(mnld_test_mnl_ver, mnl_ver_addr, strlen(mnl_ver_addr));
+                        for(i=0;i<strlen(mnld_test_mnl_ver);i++)
+                        {
+                            if(mnld_test_mnl_ver[i] == ',')
+                            {
+                                mnld_test_mnl_ver[i] = '\0';
+                                break;
+                            }
+                        }
+                        got_mnl_ver = 1;
+                        LOGD("\nRCV[%d]:%s\n", rec_len, rec_buff);
+                    }
+                    //Parser
+                }
+            }
+            if(retry_cnt ++ >= 5)
+            {
+                LOGE("Get mnl version fail\r\n");
+                strcpy(mnld_test_mnl_ver,"UNKNOWN");
+                break;
+            }
+        }while(!got_mnl_ver);
+        close(sock_fd);
+    }
+}
+#endif
+#endif
+
+void mnld_test_open_gnss(MNLD_TEST_RESTART_TYPE restart_type, GpsInterface_ext* gps_interface, GpsCallbacks_ext* gps_cbs)
+{
+    GpsCallbacks_ext* cbs = gps_cbs;
+    GpsInterface_ext* gpsinterface = gps_interface;
+    switch(restart_type) {
+        case MNLD_TEST_RESTART_TYPE_HOT:
+            LOGD("Hot Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_RTI);
+            break;
+        case MNLD_TEST_RESTART_TYPE_WARM:
+            LOGD("Warm Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS);
+            break;
+        case MNLD_TEST_RESTART_TYPE_COLD:
+            LOGD("Cold Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS |
+                GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+                GPS_DELETE_UTC | GPS_DELETE_HEALTH);
+            break;
+        case MNLD_TEST_RESTART_TYPE_FULL:
+            LOGD("Full Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_ALL);
+            break;
+        default:
+            LOGE("ERR: read unhandled value=[%d]\n", restart_type);
+            return;
+    }
+    if(gpsinterface != NULL && cbs != NULL)
+    {
+        gpsinterface->init(cbs);
+        //hal2mnl_update_network_state(1,NETWORK_TYPE_WIFI,0,"NULL");
+        //hal2mnl_update_network_state(mnld_test_network_on,mnld_test_network_type,mnld_test_network_roaming,"NULL");
+        gpsinterface->start();
+        memset(&(mnld_test_result_body.location),0,sizeof(GpsLocation));
+        mnld_test_result_body.fix_type = 0;
+        mnld_test_ttff = 0;
+        mnld_test_session_end = 0;
+       // usleep(500000);
+       // mnld_test_connect_mnl();
+    #ifndef MNLD_TEST_TTFF_SESSION_BEGIN
+        if(clock_gettime(CLOCK_BOOTTIME,&mnld_test_gnss_open_tm) == -1)
+        {
+            LOGE("Fail to get time(%s).",strerror(errno));
+        }
+    #endif
+    }else{
+        LOGE("param error:%d, %d",gpsinterface, cbs);
+    }
+}
+
+void mnld_test_close_gnss(GpsInterface_ext* gps_interface)
+{
+    GpsInterface_ext* gpsinterface = gps_interface;
+//    gpsinterface = gps_device__get_gps_interface("mnld_test stop");
+    if(gpsinterface != NULL)
+    {
+        gpsinterface->cleanup();
+        gpsinterface->stop();
+    }else{
+        LOGE("[%s]param error\r\n",__func__);
+    }
+
+}
+
+MNLD_TEST_RESTART_TYPE mnld_test_get_restart_type(char type_char)
+{
+    MNLD_TEST_RESTART_TYPE restart_type = MNLD_TEST_RESTART_TYPE_UNKNOWN;
+    switch(type_char)
+    {
+        case 'H':
+        case 'h':
+        restart_type = MNLD_TEST_RESTART_TYPE_HOT;
+        break;
+
+        case 'W':
+        case 'w':
+        restart_type = MNLD_TEST_RESTART_TYPE_WARM;
+        break;
+
+        case 'C':
+        case 'c':
+        restart_type = MNLD_TEST_RESTART_TYPE_COLD;
+        break;
+
+        case 'F':
+        case 'f':
+        restart_type = MNLD_TEST_RESTART_TYPE_FULL;
+        break;
+
+        default :
+        LOGE("Restart type error, use default hot start!\r\n");
+        restart_type = MNLD_TEST_RESTART_TYPE_UNKNOWN;
+        break;
+
+    }
+    return restart_type;
+}
+
+static void mnld_test_clear_stdin_buff() {
+    char c;
+    while((c = getchar()) != '\n' && c != EOF);
+}
+
+
+void mnld_test_gnss_restart(void)
+{
+    int retry_cnt = 0;
+    if(mnld_test_restart_cnt < mnld_test_restart_time)
+    {
+        mnld_test_restart_cnt++;
+        mnld_test_close_gnss(mnld_test_gpsinfs);
+        while(!mnld_test_session_end)
+        {
+            if(retry_cnt++>500)
+            {
+                LOGW("[%s] wait gnss close timeout\r\n",__func__);
+                break;
+            }
+            usleep(10000);
+        }
+        mnld_test_open_gnss(mnld_test_restart_type,mnld_test_gpsinfs,mnld_test_cbs);
+        start_timer(mnld_test_restart_timer,mnld_test_restart_interval*1000);
+    }else{
+        stop_timer(mnld_test_restart_timer);
+    }
+}
+
+char* mnld_test_get_clock_type_str(int clock_type_int)
+{
+    int i = 0;
+    int len = sizeof(mnld_test_clock_type)/sizeof(clock_type);
+
+    for(i=0;i<len;i++)
+    {
+        if(clock_type_int == mnld_test_clock_type[i].type_int)
+        {
+            break;
+        }
+    }
+
+    if(i < len)
+    {
+        return(mnld_test_clock_type[i].type_str);
+    }else{
+        return("Unknown");
+    }
+}
+
+void mnld_test_show_test_result(mnld_test_result* result)
+{
+    if(NULL != result)
+    {
+        memcpy(result->chip_ver,MNLD_TEST_CHIP_VER,sizeof(MNLD_TEST_CHIP_VER));
+        memcpy(result->mnl_ver,MNLD_TEST_MNL_VER,strlen(MNLD_TEST_MNL_VER));
+        result->clk_type = MNLD_TEST_CLOCK_TYPE;
+        result->clk_buff = MNLD_TEST_CLOCK_BUFF;
+
+        //system("clear");
+        LOGD("---------------------------------------------");
+        LOGD("Chip:%s",result->chip_ver);
+        LOGD("MNL Version:%s",result->mnl_ver);
+        LOGD("Clock Type:%s",mnld_test_get_clock_type_str(result->clk_type));
+        LOGD("Clock Buffer:%d",result->clk_buff);
+        LOGD("---------------------------------------------");
+        if(result->ttff[CURR] == 0)
+        {
+            LOGD("TTFF: - ");
+        }else{
+            LOGD("TTFF: %d ms",result->ttff[CURR]);
+        }
+
+        if(result->ttff[MIN] == 0)
+        {
+            LOGD("TTFF min: - ");
+        }else{
+            LOGD("TTFF min: %d ms",result->ttff[MIN]);
+        }
+
+        if(result->ttff[MAX] == 0)
+        {
+            LOGD("TTFF max: - ");
+        }else{
+            LOGD("TTFF max: %d ms",result->ttff[MAX]);
+        }
+
+        if(result->ttff[MEAN] == 0)
+        {
+            LOGD("TTFF mean: - ");
+        }else{
+            LOGD("TTFF mean: %d ms",result->ttff[MEAN]);
+        }
+        LOGD("---------------------------------------------");
+        LOGD("Fix Type: %d",result->fix_type);
+        LOGD("Flags: 0x%x",result->location.legacyLocation.flags);
+        LOGD("Latitude: %.10lf",result->location.legacyLocation.latitude);
+        LOGD("Longtitude: %.10lf",result->location.legacyLocation.longitude);
+        LOGD("Altitude: %.10lf",result->location.legacyLocation.altitude);
+        LOGD("Speed: %fm/s",result->location.legacyLocation.speed);
+        LOGD("Bearing: %f",result->location.legacyLocation.bearing);
+//        LOGD("Time stamp: %d",result->location.timestamp);
+        LOGD("horizontalAccuracyMeters: %f",result->location.horizontalAccuracyMeters);
+        LOGD("verticalAccuracyMeters: %f",result->location.verticalAccuracyMeters);
+        LOGD("speedAccuracyMetersPerSecond: %f",result->location.speedAccuracyMetersPerSecond);
+        LOGD("bearingAccuracyDegrees: %f",result->location.bearingAccuracyDegrees);
+        LOGD("Utc time: %s",result->utc_time);
+        LOGD("---------------------------------------------");
+        LOGD("GNSS testing(%d).",mnld_test_restart_cnt);
+    }
+}
+
+static int main_running = 1;
+static pthread_mutex_t main_mutex;
+static pthread_cond_t main_cond;
+
+void daemon_sighlr(int signo)
+{
+    if ((signo == SIGUSR1) || (signo == SIGINT) || (signo == SIGTERM)) {
+        LOGD("catch signal:%d, stop mnld_test\n", signo);
+        pthread_mutex_lock(&main_mutex);
+        main_running = 0;
+        mnld_test_close_gnss(mnld_test_gpsinfs);
+        pthread_mutex_unlock(&main_mutex);
+        pthread_cond_signal(&main_cond);
+    }
+    else if (signo == SIGPIPE || signo == SIGTTIN)
+        LOGD("catch signal:%d, ignore\n", signo);;
+}
+
+void main(int argc, char** argv)
+{
+    struct sigaction actions;
+
+    actions.sa_handler = daemon_sighlr;
+    sigemptyset(&actions.sa_mask);
+    actions.sa_flags = 0;
+    sigaction(SIGUSR1, &actions, NULL);
+    sigaction(SIGINT, &actions, NULL);
+    sigaction(SIGTTIN, &actions, NULL);
+    sigaction(SIGKILL, &actions, NULL);
+    sigaction(SIGTERM, &actions, NULL);
+
+    pthread_mutex_init(&main_mutex, NULL);
+    pthread_cond_init(&main_cond, NULL);
+
+    int exit_flag = 0;
+    int cnt = 0;
+    int index = 0;
+    int ret = 0;
+    char input_c = 0;
+    char *error;
+    struct gps_device_t_ext *gpsdev = NULL;
+    void *handle;
+    MNLD_TEST_ACTION action = MNLD_TEST_ACTION_UNKNOWN;
+
+    //Show the recieved command
+    for(index=0; index<argc; index++)
+    {
+        mnld_test_printf("%s ",argv[index]);
+    }
+    mnld_test_printf("\r\n");
+
+    if(argc >= 2 && argc <= MNLD_TEST_CMD_CNT_MAX)
+    {
+        if(!strncmp(argv[1], MNLD_TEST_CMD_OPEN, strlen(MNLD_TEST_CMD_OPEN)))//Open GNSS
+        {
+            action = MNLD_TEST_ACTION_GNSS_OPEN;
+            //re-init restart parameters
+            mnld_test_restart_time = 0;
+            mnld_test_restart_interval = 60;//Default is 60s
+            mnld_test_restart_type = MNLD_TEST_RESTART_TYPE_HOT;
+
+            switch(argc)
+            {
+                case 5://No break
+                mnld_test_restart_interval = atoi(&argv[4][0]);
+                case 4://No break
+                mnld_test_restart_time = atoi(&argv[3][0]);
+                case 3://No break
+                mnld_test_restart_type = mnld_test_get_restart_type(argv[2][0]);
+                case 2://No break
+                case 1://No break
+                default:
+                break;
+            }
+            LOGD("mnld_test start.\r\n");
+            if(mnld_test_restart_time > 1000)
+            {
+                LOGE("The max value of restart time is 1000, %d is over this range\r\n",mnld_test_restart_time);
+                mnld_test_restart_time = 1000;
+            }
+
+            if(mnld_test_restart_interval > 3600)
+            {
+                LOGE("The max value of restart interval is 3600s(1h), %d is over this range\r\n",mnld_test_restart_interval);
+                mnld_test_restart_interval = 3600;
+            }
+
+            if(mnld_test_restart_time <= 0)//No restart
+            {
+                mnld_test_restart_interval = 0;
+            }
+            LOGD("restart_time:%d, restart_interval:%ds,restart_type:%d\r\n",mnld_test_restart_time,mnld_test_restart_interval,mnld_test_restart_type);
+            exit_flag = 0;
+        }else if(!strncmp(argv[1],MNLD_TEST_CMD_CLOSE, strlen(MNLD_TEST_CMD_CLOSE))){//Close GNSS
+            action = MNLD_TEST_ACTION_GNSS_CLOSE;
+            LOGD("mnld_test stop.\r\n");
+            exit_flag = 0;
+        }else if(!strncmp(argv[1], MNLD_TEST_CMD_NETWORK, strlen(MNLD_TEST_CMD_NETWORK))){
+            LOGD("mnld_test set network.\r\n");
+            exit_flag = 0;
+            if(argc == 3)
+            {
+                if(!strncmp(argv[2], MNLD_TEST_NETWORK_WIFI, strlen(MNLD_TEST_NETWORK_WIFI)))
+                {
+                    mnld_test_network_type = NETWORK_TYPE_WIFI;
+                    mnld_test_network_on = 1;
+                    mnld_test_network_roaming = 0;
+                }else if(!strncmp(argv[2],MNLD_TEST_NETWORK_MOBILE, strlen(MNLD_TEST_NETWORK_MOBILE))){
+                    mnld_test_network_type = NETWORK_TYPE_MOBILE;
+                    mnld_test_network_on = 1;
+                    mnld_test_network_roaming = 0;
+                }else if(!strncmp(argv[2],MNLD_TEST_NETWORK_DISABLE, strlen(MNLD_TEST_NETWORK_DISABLE)))                {
+                    mnld_test_network_type = NETWORK_TYPE_WIFI;
+                    mnld_test_network_on = 0;
+                    mnld_test_network_roaming = 0;
+                }else{
+                    LOGW("Network set fail!Unknown command!(%d)\r\n", argc);
+                    mnld_test_show_help();
+                    exit_flag = 1;
+                }
+            }else if(argc == 4){
+                if(!strncmp(argv[2],MNLD_TEST_NETWORK_MOBILE, strlen(MNLD_TEST_NETWORK_MOBILE)) && !strncmp(argv[3],MNLD_TEST_NETWORK_ROAMING, strlen(MNLD_TEST_NETWORK_ROAMING)))
+                {
+                    mnld_test_network_type = NETWORK_TYPE_MOBILE;
+                    mnld_test_network_on = 1;
+                    mnld_test_network_roaming = 1;
+                }else{
+                    LOGW("Network set fail!Unknown command!(%d)\r\n", argc);
+                    mnld_test_show_help();
+                    exit_flag = 1;
+                }
+            }else{
+                LOGW("Network set fail! Error cmd count(%d).\r\n",argc);
+                mnld_test_show_help();
+                exit_flag = 1;
+            }
+
+            LOGD("network, type:%s, on:%d, roaming:%d.\r\n",mnld_test_network_type_str[mnld_test_network_type], mnld_test_network_on, mnld_test_network_roaming);
+            action = MNLD_TEST_ACTION_SET_NETWORK;
+        }else{
+            LOGE("Unknown command!\r\n");
+            mnld_test_show_help();
+            exit_flag = 1;
+        }
+    }else{
+        LOGE("Unknown command!\r\n");
+        mnld_test_show_help();
+        exit_flag = 1;
+    }
+
+    if(!exit_flag)
+    {
+        handle = dlopen(LIB_GNSS_HAL_DIR"/libgpshal.so.0", RTLD_LAZY);
+        if (!handle) {
+            fprintf(stderr, "%s\n", dlerror());
+            exit(EXIT_FAILURE);
+        }
+
+        gpsdev = (struct gps_device_t_ext *)dlsym(handle, "linux_gps_device");
+        if ((error = dlerror()) != NULL) {
+            fprintf(stderr, "%s\n", error);
+            exit(EXIT_FAILURE);
+        }
+        mnld_test_gpsinfs = (GpsInterface_ext*)gpsdev->get_gps_interface(gpsdev);
+
+        mnld_test_cbs = mnld_test__get_gps_callbacks();//&mnld_test_gps_callbacks;
+        switch(action)
+        {
+            case MNLD_TEST_ACTION_GNSS_OPEN:
+
+            valid_ttff_cnt = 0;
+            valid_ttff_sum = 0;
+
+            memset(&mnld_test_result_body,0,sizeof(mnld_test_result));
+            mnld_test_open_gnss(mnld_test_restart_type,mnld_test_gpsinfs,mnld_test_cbs);
+            //system("clear");
+            if(mnld_test_restart_interval != 0)
+            {
+                mnld_test_restart_timer = init_timer(mnld_test_gnss_restart);
+                start_timer(mnld_test_restart_timer,mnld_test_restart_interval*1000);
+            }
+            pthread_mutex_lock(&main_mutex);
+            while(main_running) {
+                LOGI("main thread going....\n");
+                pthread_cond_wait(&main_cond, &main_mutex);
+                LOGI("some signal catched, go to exit!!!\n");
+            }
+            pthread_mutex_unlock(&main_mutex);
+            exit_flag = 1;
+            break;
+
+            case MNLD_TEST_ACTION_GNSS_CLOSE:
+            mnld_test_close_gnss(mnld_test_gpsinfs);
+
+            exit_flag = 1;
+            break;
+
+            case MNLD_TEST_ACTION_SET_NETWORK:
+
+            ret = hal2mnl_update_network_state(mnld_test_network_on,mnld_test_network_type,mnld_test_network_roaming,"NULL");
+            if(-1 == ret)
+            {
+                LOGE("Network set fail!\r\n");
+            }else{
+                LOGD("Network set successfully! type: %s,on:%d,roaming:%d\r\n",mnld_test_network_type_str[mnld_test_network_type],mnld_test_network_on,mnld_test_network_roaming);
+            }
+            exit_flag = 1;
+            break;
+
+            default:
+            LOGW("Unknown action(%d)\r\n",action);
+            mnld_test_show_help();
+            break;
+        }
+
+    }
+    pthread_cond_destroy(&main_cond);
+    pthread_mutex_destroy(&main_mutex);
+}
diff --git a/src/connectivity/gps/gnss_test/mnld_client/src/mnld_client_gps_cb.c b/src/connectivity/gps/gnss_test/mnld_client/src/mnld_client_gps_cb.c
new file mode 100644
index 0000000..71609ff
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_client/src/mnld_client_gps_cb.c
@@ -0,0 +1,255 @@
+#include<pthread.h>
+#include<stdio.h>
+#include<unistd.h>
+#include<errno.h>
+#include<string.h>
+
+#include"mnld_test.h"
+#include"mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+extern struct timespec mnld_test_gnss_open_tm;
+extern int mnld_test_ttff;
+extern int mnld_test_session_end;
+GpsLocation_ext location_rslt;
+mnld_test_result mnld_test_result_body;
+
+void mnld_test_gps_location_callback(GpsLocation_ext* location)
+{
+
+//    memset(&result,0,sizeof(mnld_test_result));
+    if(location->legacyLocation.size == sizeof(GpsLocation_ext))
+    {
+        LOGD("===============Update Location Info==================");
+        LOGD("flags:0x%x", location->legacyLocation.flags);
+        LOGD("latitude:%.10lf", location->legacyLocation.latitude);
+        LOGD("longitude:%.10lf", location->legacyLocation.longitude);
+        LOGD("altitude:%.10lf", location->legacyLocation.altitude);
+        LOGD("speed:%f", location->legacyLocation.speed);
+        LOGD("bearing:%f", location->legacyLocation.bearing);
+        LOGD("timestamp:%d", location->legacyLocation.timestamp);
+        LOGD("horizontalAccuracyMeters:%f", location->horizontalAccuracyMeters);
+        LOGD("verticalAccuracyMeters:%f", location->verticalAccuracyMeters);
+        LOGD("speedAccuracyMetersPerSecond:%f", location->speedAccuracyMetersPerSecond);
+        LOGD("bearingAccuracyDegrees:%f", location->bearingAccuracyDegrees);
+        memcpy(&(mnld_test_result_body.location), location, sizeof(GpsLocation_ext));
+    }else {
+        LOGE("GpsLocation_ext size is wrong");
+    }
+#if 0
+        memcpy(&(result.location), location, sizeof(GpsLocation_ext));
+        if((location->flags & GPS_LOCATION_HAS_ACCURACY) && (mnld_test_ttff == 0))
+        {
+            struct timespec fix_tm;
+            if(clock_gettime(CLOCK_BOOTTIME,&fix_tm) == -1)
+            {
+                result.ttff = 0;
+                LOGE("[%s]Fail to get time(%s)\r\n",__func__,strerror(errno));
+            }else{
+                LOGD("Flags:0x%x,start time:%ds,%dns; ttff time:%ds,%dns\r\n",result.location.flags,mnld_test_gnss_open_tm.tv_sec,mnld_test_gnss_open_tm.tv_nsec,fix_tm.tv_sec,fix_tm.tv_nsec);
+                result.ttff = (fix_tm.tv_sec-mnld_test_gnss_open_tm.tv_sec)*1000+((fix_tm.tv_nsec-mnld_test_gnss_open_tm.tv_nsec)/1000000);
+                mnld_test_ttff = result.ttff;
+                LOGD("TTFF:%dms",mnld_test_ttff);
+            }
+        }else{
+            result.ttff = mnld_test_ttff;
+        }
+        result.location.timestamp = location->timestamp;
+        LOGD("ts:%d,result.timestamp:%ld\r\n",location->timestamp,result.location.timestamp);
+        mnld_test_show_test_result(&result);
+    }else{
+        LOGE("[%s]size error!\r\n", __func__);
+    }
+#endif
+    
+}
+
+void mnld_test_gps_status_callback(GpsStatus* status)
+{
+    if(status->size == sizeof(GpsStatus))
+    {
+        LOGD("GPS Status:%d", status->status);
+        if(status->status == GPS_STATUS_SESSION_BEGIN)
+        {
+            mnld_test_ttff = 0;
+            mnld_test_session_end = 0;
+//          usleep(500000);
+            mnld_test_get_mnl_ver();
+        #ifdef MNLD_TEST_TTFF_SESSION_BEGIN
+            if(clock_gettime(CLOCK_BOOTTIME,&mnld_test_gnss_open_tm) == -1)
+            {
+                LOGE("Fail to get time(%s).", strerror(errno));
+            }
+        #endif
+        }
+
+        if(status->status == GPS_STATUS_SESSION_END)
+        {
+            mnld_test_session_end = 1;
+        }
+    }else{
+        LOGE("size error!");
+    }
+}
+
+void mnld_test_gps_sv_status_callback(GpsSvStatus* sv_info)
+{
+    LOGD("gps sv status");
+}
+
+#define NMEA_GGA "GGA"
+#define NMEA_GSA "GSA"
+#define NMEA_ACC "ACCURACY"
+extern int valid_ttff_cnt;
+extern int valid_ttff_sum;
+void mnld_test_gps_nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
+{
+//    LOGD("%d",timestamp);
+
+    //$GPGSA,A,3,...
+    if( strncmp(nmea+3,NMEA_GSA,strlen(NMEA_GSA)) == 0 )
+    {
+        mnld_test_result_body.fix_type = *(nmea+9) - '0';
+        if(mnld_test_result_body.fix_type == 1)
+        {
+            mnld_test_result_body.fix_type = 0;
+        }
+ 
+        if((mnld_test_ttff == 0) && mnld_test_result_body.fix_type != 0)
+        {
+            struct timespec fix_tm;
+
+            if(clock_gettime(CLOCK_BOOTTIME,&fix_tm) == -1)
+            {
+                mnld_test_result_body.ttff[CURR] = 0;
+                LOGE("[%s]Fail to get time(%s)\r\n",__func__,strerror(errno));
+            }else{
+               // LOGD("Flags:0x%x,start time:%ds,%dns; ttff time:%ds,%dns\r\n",mnld_test_result_body.location.flags,mnld_test_gnss_open_tm.tv_sec,mnld_test_gnss_open_tm.tv_nsec,fix_tm.tv_sec,fix_tm.tv_nsec);
+                mnld_test_ttff = (fix_tm.tv_sec-mnld_test_gnss_open_tm.tv_sec)*1000+((fix_tm.tv_nsec-mnld_test_gnss_open_tm.tv_nsec)/1000000);
+                mnld_test_result_body.ttff[CURR] = mnld_test_ttff;
+                valid_ttff_cnt++;
+                valid_ttff_sum+=mnld_test_result_body.ttff[CURR];
+
+                mnld_test_result_body.ttff[MEAN] = valid_ttff_sum/valid_ttff_cnt;
+                //Find the MIN TTFF
+                if((mnld_test_result_body.ttff[MIN] == 0 ) || (mnld_test_result_body.ttff[MIN] > mnld_test_result_body.ttff[CURR]))
+                {
+                    mnld_test_result_body.ttff[MIN] = mnld_test_result_body.ttff[CURR];
+                }
+                // Find the MAX TTFF
+                if(mnld_test_result_body.ttff[MAX] < mnld_test_result_body.ttff[CURR])
+                {
+                    mnld_test_result_body.ttff[MAX] = mnld_test_result_body.ttff[CURR];
+                }
+                LOGD("TTFF:%dms",mnld_test_ttff);
+            }
+
+        }else{
+            mnld_test_result_body.ttff[CURR] = mnld_test_ttff;
+        }
+    }
+
+    if(mnld_test_result_body.fix_type != 0)
+    {
+        //GNGGA,hhmmss.mss,...
+        if(strncmp(nmea+3,NMEA_GGA,strlen(NMEA_GGA)) == 0)
+        {
+            strncpy(mnld_test_result_body.utc_time, nmea+7, MNL_UTC_TIME_LEN);
+            mnld_test_result_body.utc_time[MNL_UTC_TIME_LEN-1] = '\0';
+        }
+    }else{
+        memset(mnld_test_result_body.utc_time, 0, MNL_UTC_TIME_LEN);
+        mnld_test_result_body.utc_time[0] = '-';
+    }
+
+    if(strncmp(nmea+3,NMEA_ACC,strlen(NMEA_ACC)) == 0)
+    {
+        mnld_test_result_body.location.legacyLocation.timestamp = timestamp;
+        mnld_test_show_test_result(&mnld_test_result_body);
+    }
+    
+}
+
+void mnld_test_gps_set_capabilities(uint32_t capabilities)
+{
+
+    LOGD("gps set capabilities");
+}
+
+void mnld_test_gps_acquire_wakelock(void)
+{
+
+    LOGD("gps acquire wakelock");
+}
+
+void mnld_test_gps_release_wakelock(void)
+{
+
+    LOGD("gps release wakelock");
+}
+
+void mnld_test_gps_request_utc_time(void)
+{
+
+    LOGD("gps request utc time");
+}
+
+void mnld_test_set_system_info_cb(const GnssSystemInfo* info)
+{
+    LOGD("set system info");
+}
+
+void mnld_test_gnss_sv_status_cb(GnssSvStatus_ext* sv_info)
+{
+    LOGD("gnss sv status");
+}
+
+pthread_t mnld_test_gps_create_thread(const char* name, void (*start)(void *), void* arg)
+{
+    pthread_t ntid = 0;
+    int ret = 0;
+
+    ret = pthread_create(&ntid, NULL, start, arg);
+
+    if(ret != 0)
+    {
+        LOGE("thread %s create fail(%s)!", name, strerror(errno));
+        ntid = 0;
+    }else{
+        LOGD("tread %s create success!", name);
+    }
+
+    return ntid;
+}
+
+void mnld_test_gnss_set_name_cb(const char* name, int length)
+{
+    LOGD("gnss set name");
+}
+
+void mnld_test_gnss_request_location_cb(bool independentFromGnss)
+{
+    LOGD("gnss request location");
+}
+
+GpsCallbacks_ext mnld_test_gps_callbacks = {
+    .size = sizeof(GpsCallbacks_ext),
+    .location_cb = mnld_test_gps_location_callback,
+    .status_cb = mnld_test_gps_status_callback,
+    .sv_status_cb = mnld_test_gps_sv_status_callback,
+    .nmea_cb = mnld_test_gps_nmea_callback,
+    .set_capabilities_cb = mnld_test_gps_set_capabilities,
+    .acquire_wakelock_cb = mnld_test_gps_acquire_wakelock,
+    .release_wakelock_cb = mnld_test_gps_release_wakelock,
+    .create_thread_cb = mnld_test_gps_create_thread,
+    .request_utc_time_cb = mnld_test_gps_request_utc_time,
+    .set_system_info_cb = mnld_test_set_system_info_cb,
+    .gnss_sv_status_cb = mnld_test_gnss_sv_status_cb,
+    .set_name_cb = mnld_test_gnss_set_name_cb,
+    .request_location_cb = mnld_test_gnss_request_location_cb,
+};
+
+GpsCallbacks_ext* mnld_test__get_gps_callbacks(void)
+{
+    return &mnld_test_gps_callbacks;
+}
diff --git a/src/connectivity/gps/gnss_test/mnld_fm/inc/mnld_fm.h b/src/connectivity/gps/gnss_test/mnld_fm/inc/mnld_fm.h
new file mode 100644
index 0000000..67bd5d8
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_fm/inc/mnld_fm.h
@@ -0,0 +1,50 @@
+#ifndef __MNLD_FM_H__
+#define __MNLD_FM_H__
+
+#include"hal_mnl_interface_common.h"
+#include"gps_mtk.h"
+
+typedef enum{
+    MNLD_FM_TEST_OPEN = 0,
+    MNLD_FM_TEST_OPENED,
+    MNLD_FM_TEST_ENGINE_STARTED,
+    MNLD_FM_TEST_SV_SEARCHED,
+    MNLD_FM_TEST_STAGE_MAX
+} MNLD_FM_TEST_STAGE;
+
+typedef struct {
+    int sv_num;
+    int sv_list[GNSS_MAX_SVS];
+    MNLD_FM_TEST_STAGE test_stage;
+}mnld_fm_test_result;
+
+typedef enum{
+    MNLD_FM_RESTART_TYPE_UNKNOWN = -1,
+    MNLD_FM_RESTART_TYPE_HOT,
+    MNLD_FM_RESTART_TYPE_WARM,
+    MNLD_FM_RESTART_TYPE_COLD,
+    MNLD_FM_RESTART_TYPE_FULL,
+    MNLD_FM_RESTART_TYPE_MAX
+} MNLD_FM_RESTART_TYPE;
+
+
+#define MNLD_FM_CMD_CNT_MIN 1
+#define MNLD_FM_CMD_CNT_MAX 2
+#define GPS_DELETE_EPHEMERIS        0x0001
+#define GPS_DELETE_ALMANAC          0x0002
+#define GPS_DELETE_POSITION         0x0004
+#define GPS_DELETE_TIME             0x0008
+#define GPS_DELETE_IONO             0x0010
+#define GPS_DELETE_UTC              0x0020
+#define GPS_DELETE_HEALTH           0x0040
+#define GPS_DELETE_SVDIR            0x0080
+#define GPS_DELETE_SVSTEER          0x0100
+#define GPS_DELETE_SADATA           0x0200
+#define GPS_DELETE_RTI              0x0400
+#define GPS_DELETE_CELLDB_INFO      0x8000
+#define GPS_DELETE_ALL              0xFFFF
+
+GpsCallbacks_ext* mnld_fm__get_gps_callbacks(void);
+//GpsInterface* gps_device__get_gps_interface(struct gps_device_t* device);
+
+#endif //__MNLD_FM_H__
diff --git a/src/connectivity/gps/gnss_test/mnld_fm/inc/mtk_auto_log.h b/src/connectivity/gps/gnss_test/mnld_fm/inc/mtk_auto_log.h
new file mode 100644
index 0000000..f76f173
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_fm/inc/mtk_auto_log.h
@@ -0,0 +1,180 @@
+/*
+* Copyright Statement:
+*
+* This software/firmware and related documentation ("MediaTek Software") are
+* protected under relevant copyright laws. The information contained herein is
+* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+* the prior written permission of MediaTek inc. and/or its licensors, any
+* reproduction, modification, use or disclosure of MediaTek Software, and
+* information contained herein, in whole or in part, shall be strictly
+* prohibited.
+*
+* MediaTek Inc. (C) 2017. All rights reserved.
+*
+* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*/
+#ifndef MTK_AUTO_LOG_H
+#define MTK_AUTO_LOG_H
+
+/**
+ *  @enum LOG_LEVEL
+ *  @brief Define Log Level
+ */
+typedef enum {
+    L_VERBOSE = 0, L_DEBUG, L_INFO, L_WARN, L_ERROR, L_ASSERT, L_SUPPRESS
+} LOG_LEVEL;
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+#ifdef LOGD
+#undef LOGD
+#endif
+#ifdef LOGW
+#undef LOGW
+#endif
+#ifdef LOGE
+#undef LOGE
+#endif
+
+#ifndef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld"
+#endif
+
+#include <string.h>
+
+int set_log_level(int *dst_level, int src_level);
+
+extern int log_dbg_level;
+#define LOG_IS_ENABLED(level) (log_dbg_level <= level)
+
+#define FILE_NAME(x) strrchr(x, '/')?strrchr(x, '/') + 1 : x
+
+#if defined(__ANDROID_OS__)
+
+#include <cutils/sockets.h>
+#include <log/log.h>     /*logging in logcat*/
+
+#define PRINT_LOG(loglevel, fmt, args...) \
+        do {\
+                if (LOG_IS_ENABLED(loglevel)) {\
+                    switch (loglevel){\
+                        case L_ASSERT:\
+                        {\
+                            ALOG_ASSERT("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_ERROR:\
+                        {\
+                            ALOGE("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_WARN:\
+                        {\
+                            ALOGW("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_INFO:\
+                        {\
+                            ALOGI("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_DEBUG:\
+                        {\
+                            ALOGD("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                        case L_VERBOSE:\
+                        {\
+                            ALOGV("%s %s %d " fmt, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                            break;\
+                        }\
+                    }\
+                }\
+        } while (0)
+
+#define LOGA(fmt, args...)    PRINT_LOG(L_ASSERT, fmt, ##args)
+#define LOGE(fmt, args...)    PRINT_LOG(L_ERROR, fmt, ##args)
+#define LOGW(fmt, args...)    PRINT_LOG(L_WARN, fmt, ##args)
+#define LOGI(fmt, args...)    PRINT_LOG(L_INFO, fmt, ##args)
+#define LOGD(fmt, args...)    PRINT_LOG(L_DEBUG, fmt, ##args)
+#define LOGV(fmt, args...)    PRINT_LOG(L_VERBOSE, fmt, ##args)
+
+#define  TRC(f)       ALOGD("%s", __func__)
+
+#elif defined(__LINUX_OS__)
+
+#include <stdio.h>
+
+char time_buff[64];
+int get_time_str(char* buf, int len);
+
+#ifndef gettid
+#include <unistd.h>
+#include <sys/syscall.h>
+#define gettid() syscall(__NR_gettid)
+#define getpid() syscall(__NR_getpid)
+#endif
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+        do {\
+                if (LOG_IS_ENABLED(loglevel)) {\
+                    get_time_str(time_buff, sizeof(time_buff));\
+                    printf("%ld %ld [%s]" LOG_TAG tag "%s %s %d "  fmt "\n",\
+                        getpid(), gettid(),time_buff, FILE_NAME(__FILE__), __FUNCTION__, __LINE__, ##args);\
+                    fflush(stdout);\
+                }\
+        } while (0)
+
+#define LOGA(fmt, args...)    PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...)    PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...)    PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...)    PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...)    PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...)    PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#define  TRC(f)       ((void)0)
+
+#elif defined(__TIZEN_OS__)
+
+#include <dlog/dlog.h>
+
+#define PRINT_LOG(loglevel, tag, fmt, args...) \
+        do {\
+                if (LOG_IS_ENABLED(loglevel)) {\
+                    dlog_print(DLOG_DEBUG, fmt "\n", ##args);\
+                    printf(fmt "\n", ##args);
+                    fflush(stdout);\
+                }\
+        } while (0)
+
+#define LOGA(fmt, args...)    PRINT_LOG(L_ASSERT, "[ASSERT]: ", fmt, ##args)
+#define LOGE(fmt, args...)    PRINT_LOG(L_ERROR, "[ERROR]: ", fmt, ##args)
+#define LOGW(fmt, args...)    PRINT_LOG(L_WARN, "[WARNING]: ", fmt, ##args)
+#define LOGI(fmt, args...)    PRINT_LOG(L_INFO, "[INFO]: ", fmt, ##args)
+#define LOGD(fmt, args...)    PRINT_LOG(L_DEBUG, "[DEBUG]: ", fmt, ##args)
+#define LOGV(fmt, args...)    PRINT_LOG(L_VERBOSE, "[VERBOSE]: ", fmt, ##args)
+
+#endif
+
+#endif
diff --git a/src/connectivity/gps/gnss_test/mnld_fm/src/mnld_fm.c b/src/connectivity/gps/gnss_test/mnld_fm/src/mnld_fm.c
new file mode 100644
index 0000000..e3f54ec
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_fm/src/mnld_fm.c
@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include "hal2mnl_interface.h"
+#include "mnld_fm.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnldfm"
+#endif
+
+int log_dbg_level = L_VERBOSE;
+
+GpsCallbacks_ext* mnld_fm_cbs = NULL;
+GpsInterface_ext* mnld_fm_gpsinfs = NULL;
+
+timer_t mnld_fm_test_timer = 0;
+MNLD_FM_RESTART_TYPE mnld_fm_restart_type = MNLD_FM_RESTART_TYPE_HOT;
+extern mnld_fm_test_result mnld_fm_test_result_body;
+int mnld_fm_test_timeout = 0;
+int mnld_fm_test_wait_time = 10;//wait time , second
+
+void mnld_fm_show_help(void)
+{
+    printf("MNLD factory mode test :\r\n");
+    printf("------------------------------------------------------------------------------\r\n");
+    printf("For GNSS factory mode test or HW check.\r\n");
+    printf("------------------------------------------------------------------------------\r\n");
+    printf("The command to start MNLD factory mode test:\r\n");
+    printf("\tfm_gnss\r\n");
+}
+
+void mnld_fm_open_gnss(MNLD_FM_RESTART_TYPE restart_type, GpsInterface_ext* gps_interface, GpsCallbacks_ext* gps_cbs)
+{
+    GpsCallbacks_ext* cbs = gps_cbs;
+    GpsInterface_ext* GpsInterface_ext = gps_interface;
+
+    switch(restart_type) {
+        case MNLD_FM_RESTART_TYPE_HOT:
+            LOGD("Hot Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_RTI);
+            break;
+        case MNLD_FM_RESTART_TYPE_WARM:
+            LOGD("Warm Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS);
+            break;
+        case MNLD_FM_RESTART_TYPE_COLD:
+            LOGD("Cold Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_EPHEMERIS |
+                GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO |
+                GPS_DELETE_UTC | GPS_DELETE_HEALTH);
+            break;
+        case MNLD_FM_RESTART_TYPE_FULL:
+            LOGD("Full Start\n");
+            hal2mnl_gps_delete_aiding_data(GPS_DELETE_ALL);
+            break;
+        default:
+            LOGE("ERR: read unhandled value=[%d]\n", restart_type);
+            return;
+    }
+
+    if(GpsInterface_ext != NULL && cbs != NULL)
+    {
+        GpsInterface_ext->init(cbs);
+        //hal2mnl_update_network_state(1,NETWORK_TYPE_WIFI,0,"NULL");
+        //hal2mnl_update_network_state(mnld_fm_network_on,mnld_fm_network_type,mnld_fm_network_roaming,"NULL");
+        GpsInterface_ext->start();
+    }else{
+        LOGE("[%s]param error:%d, %d\r\n",GpsInterface_ext, cbs);
+    }
+}
+
+void mnld_fm_close_gnss(GpsInterface_ext* gps_interface)
+{
+    GpsInterface_ext* GpsInterface_ext = gps_interface;
+//    GpsInterface_ext = gps_device__get_gps_interface("mnld_fm stop");
+    if(GpsInterface_ext != NULL)
+    {
+        GpsInterface_ext->cleanup();
+        GpsInterface_ext->stop();
+    }else{
+        LOGE("param error");
+    }
+
+}
+
+void mnld_fm_test_timeout_hdlr(void)
+{
+    mnld_fm_test_timeout = 1;
+}
+
+void main(int argc, char** argv)
+{
+    int exit_flag = 0;
+    int wait_time = 0;
+    int idx = 0;
+    char *error;
+    struct gps_device_t_ext *gpsdev = NULL;
+    void *handle;
+
+    //Show the recieved command
+    for(idx=0; idx<argc; idx++)
+    {
+        printf("%s ",argv[idx]);
+    }
+    printf("\r\n");
+
+    if(argc == MNLD_FM_CMD_CNT_MIN)
+    {
+        exit_flag = 0;
+    }else{
+        LOGE("Unknown command!");
+        mnld_fm_show_help();
+        exit_flag = 1;
+    }
+
+    if(!exit_flag)
+    {
+        handle = dlopen(LIB_GNSS_HAL_DIR"/libgpshal.so.0", RTLD_LAZY);
+        if (!handle) {
+            fprintf(stderr, "%s\n", dlerror());
+            exit(EXIT_FAILURE);
+        }
+
+        gpsdev = (struct gps_device_t_ext *)dlsym(handle, "linux_gps_device");
+        if ((error = dlerror()) != NULL) {
+            fprintf(stderr, "%s\n", error);
+            exit(EXIT_FAILURE);
+        }
+        mnld_fm_gpsinfs = (GpsInterface_ext*)gpsdev->get_gps_interface(gpsdev);
+
+        mnld_fm_cbs = mnld_fm__get_gps_callbacks();//&mnld_fm_gps_callbacks;
+        mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_OPEN;
+        mnld_fm_test_result_body.sv_num = 0;
+        memset(mnld_fm_test_result_body.sv_list, 0, GNSS_MAX_SVS);
+        mnld_fm_test_timeout = 0;
+
+        mnld_fm_open_gnss(mnld_fm_restart_type,mnld_fm_gpsinfs,mnld_fm_cbs);
+        if (mnld_fm_test_result_body.test_stage < MNLD_FM_TEST_OPENED) {  //Resolve timing issue, if stage value is bigger than opend no need to set to opened any more
+            mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_OPENED;
+        }
+        //system("clear");
+        LOGD("GNSS opened for factory mode testing...");
+       // mnld_fm_test_timer = init_timer(mnld_fm_test_timeout_hdlr);
+       // start_timer(mnld_fm_test_timer,mnld_fm_restart_interval*1000);
+        do{
+            usleep(1000);
+            wait_time++;
+            if(wait_time >= mnld_fm_test_wait_time*1000)
+            {
+                mnld_fm_test_timeout = 1;
+                LOGW("GNSS factory mode test timeout...");
+                break;
+            }
+        }while(mnld_fm_test_result_body.sv_num < 2);
+        system("clear");
+        LOGD("GNSS factory mode test stage:%d, sv num:%d!",mnld_fm_test_result_body.test_stage, mnld_fm_test_result_body.sv_num);
+        if(mnld_fm_test_result_body.sv_num >= 2 /*&& mnld_fm_test_result_body.test_stage >= MNLD_FM_TEST_SV_SEARCHED*/)
+        {
+            printf("GNSS factory mode test PASS!\r\nSearched %d satellites:",mnld_fm_test_result_body.sv_num);
+            for(idx=0; idx<mnld_fm_test_result_body.sv_num; idx++)
+            {
+                printf(" %d",mnld_fm_test_result_body.sv_list[idx]);
+            }
+            printf("\r\n");
+            exit_flag = 1;
+        }else{
+            switch(mnld_fm_test_result_body.test_stage)
+            {
+                case MNLD_FM_TEST_OPEN:
+                    LOGD("GNSS factory mode test open FAIL!");
+                    break;
+                case MNLD_FM_TEST_OPENED:
+                    LOGD("GNSS factory mode test engine start FAIL!");
+                    break;
+                case MNLD_FM_TEST_ENGINE_STARTED:
+                    LOGD("GNSS factory mode test sv search FAIL(sv num:%d)!",mnld_fm_test_result_body.sv_num);
+                    break;
+                case MNLD_FM_TEST_SV_SEARCHED:
+                    LOGD("GNSS factory mode test sv search FAIL(sv num:%d)!",mnld_fm_test_result_body.sv_num);
+                    break;
+                default:
+                    LOGD("GNSS factory mode test FAIL(stage:%d, sv num:%d)!",mnld_fm_test_result_body.test_stage, mnld_fm_test_result_body.sv_num);
+                    break;
+            }
+        }
+        LOGD("Test Time: %dms",wait_time);
+        mnld_fm_close_gnss(mnld_fm_gpsinfs);
+        exit_flag = 1;
+
+    }
+}
diff --git a/src/connectivity/gps/gnss_test/mnld_fm/src/mnld_fm_gps_cb.c b/src/connectivity/gps/gnss_test/mnld_fm/src/mnld_fm_gps_cb.c
new file mode 100644
index 0000000..6ba3519
--- /dev/null
+++ b/src/connectivity/gps/gnss_test/mnld_fm/src/mnld_fm_gps_cb.c
@@ -0,0 +1,173 @@
+#include<pthread.h>
+#include<stdio.h>
+#include<unistd.h>
+#include<errno.h>
+#include<string.h>
+
+#include"mnld_fm.h"
+#include"mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld_fm_test"
+#endif
+
+mnld_fm_test_result mnld_fm_test_result_body;
+
+void mnld_fm_gps_location_callback(GpsLocation_ext* location)
+{
+
+//    memset(&result,0,sizeof(mnld_fm_result));
+    if(location->legacyLocation.size == sizeof(GpsLocation_ext))
+    {
+        LOGD("===============Update Location Info==================");
+        LOGD("flags:0x%x", location->legacyLocation.flags);
+        LOGD("latitude:%.10lf", location->legacyLocation.latitude);
+        LOGD("longitude:%.10lf", location->legacyLocation.longitude);
+        LOGD("altitude:%.10lf", location->legacyLocation.altitude);
+        LOGD("speed:%f", location->legacyLocation.speed);
+        LOGD("bearing:%f", location->legacyLocation.bearing);
+        LOGD("timestamp:%d", location->legacyLocation.timestamp);
+        LOGD("horizontalAccuracyMeters:%f", location->horizontalAccuracyMeters);
+        LOGD("verticalAccuracyMeters:%f", location->verticalAccuracyMeters);
+        LOGD("speedAccuracyMetersPerSecond:%f", location->speedAccuracyMetersPerSecond);
+        LOGD("bearingAccuracyDegrees:%f", location->bearingAccuracyDegrees);
+    }else {
+        LOGE("GpsLocation_ext size is wrong");
+    }
+}
+
+void mnld_fm_gps_status_callback(GpsStatus* status)
+{
+    if(status->size == sizeof(GpsStatus))
+    {
+        LOGD("GPS Status:%d\r\n", status->status);
+        if(status->status == GPS_STATUS_SESSION_BEGIN)
+        {
+            mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_ENGINE_STARTED;
+        }
+
+    }else{
+        LOGE("size error!");
+    }
+}
+
+void mnld_fm_gps_sv_status_callback(GpsSvStatus* sv_info)
+{
+    int idx = 0;
+    mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_SV_SEARCHED;
+    for(idx=0; idx < sv_info->num_svs; idx++)
+    {
+        mnld_fm_test_result_body.sv_list[idx] = sv_info->sv_list[idx].prn;
+    }
+    mnld_fm_test_result_body.sv_num = sv_info->num_svs;
+    LOGD("%d",mnld_fm_test_result_body.sv_num);
+}
+
+void mnld_fm_gps_nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
+{
+//    LOGD("%d",timestamp);
+}
+
+void mnld_fm_gps_set_capabilities(uint32_t capabilities)
+{
+
+    LOGD("gps set capabilities");
+}
+
+void mnld_fm_gps_acquire_wakelock(void)
+{
+
+    LOGD("gps acquire wakelock");
+}
+
+void mnld_fm_gps_release_wakelock(void)
+{
+
+    LOGD("gps release wakelock");
+}
+
+void mnld_fm_gps_request_utc_time(void)
+{
+
+    LOGD("gps request utc time");
+}
+
+void mnld_fm_set_system_info_cb(const GnssSystemInfo* info)
+{
+    LOGD("set system info");
+}
+
+#define BEIDOU_SVID_OFFSET 200
+#define GALILEO_SVID_OFFSET 300
+#define GLNOASS_SVID_OFFSET 64
+void mnld_fm_gnss_sv_status_cb(GnssSvStatus_ext* sv_info)
+{
+    int idx = 0;
+    mnld_fm_test_result_body.test_stage = MNLD_FM_TEST_SV_SEARCHED;
+    for(idx=0; idx < sv_info->num_svs; idx++)
+    {
+        mnld_fm_test_result_body.sv_list[idx] = sv_info->gnss_sv_list[idx].legacySvInfo.svid;
+        if(sv_info->gnss_sv_list[idx].legacySvInfo.constellation == GNSS_CONSTELLATION_BEIDOU) {
+            mnld_fm_test_result_body.sv_list[idx] += BEIDOU_SVID_OFFSET;
+        } else if(sv_info->gnss_sv_list[idx].legacySvInfo.constellation == GNSS_CONSTELLATION_GALILEO) {
+            mnld_fm_test_result_body.sv_list[idx] += GALILEO_SVID_OFFSET;
+        } else if(sv_info->gnss_sv_list[idx].legacySvInfo.constellation == GNSS_CONSTELLATION_GLONASS) {
+            mnld_fm_test_result_body.sv_list[idx] += GLNOASS_SVID_OFFSET;
+        }
+    }
+    mnld_fm_test_result_body.sv_num = sv_info->num_svs;
+    LOGD("%d",mnld_fm_test_result_body.sv_num);
+}
+
+
+pthread_t mnld_fm_gps_create_thread(const char* name, void (*start)(void *), void* arg)
+{
+    pthread_t ntid = 0;
+    int ret = 0;
+
+    ret = pthread_create(&ntid, NULL, start, arg);
+
+    if(ret != 0)
+    {
+        LOGE("thread %s create fail(%s)!\r\n", name, strerror(errno));
+        ntid = 0;
+    }else{
+        LOGD("tread %s create success!\r\n", name);
+    }
+
+    return ntid;
+}
+
+void mnld_fm_gnss_set_name_cb(const char* name, int length)
+{
+    LOGD("gnss set name");
+}
+
+void mnld_fm_gnss_request_location_cb(bool independentFromGnss)
+{
+    LOGD("gnss request location");
+}
+
+GpsCallbacks_ext mnld_fm_gps_callbacks = {
+    .size = sizeof(GpsCallbacks_ext),
+    .location_cb = mnld_fm_gps_location_callback,
+    .status_cb = mnld_fm_gps_status_callback,
+    .sv_status_cb = mnld_fm_gps_sv_status_callback,
+    .nmea_cb = mnld_fm_gps_nmea_callback,
+    .set_capabilities_cb = mnld_fm_gps_set_capabilities,
+    .acquire_wakelock_cb = mnld_fm_gps_acquire_wakelock,
+    .release_wakelock_cb = mnld_fm_gps_release_wakelock,
+    .create_thread_cb = mnld_fm_gps_create_thread,
+    .request_utc_time_cb = mnld_fm_gps_request_utc_time,
+    .set_system_info_cb = mnld_fm_set_system_info_cb,
+    .gnss_sv_status_cb = mnld_fm_gnss_sv_status_cb,
+    .set_name_cb = mnld_fm_gnss_set_name_cb,
+    .request_location_cb = mnld_fm_gnss_request_location_cb,
+};
+
+GpsCallbacks_ext* mnld_fm__get_gps_callbacks(void)
+{
+    return &mnld_fm_gps_callbacks;
+}