[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/connectivity/gps/Android.mk b/src/connectivity/gps/Android.mk
new file mode 100644
index 0000000..b8694f8
--- /dev/null
+++ b/src/connectivity/gps/Android.mk
@@ -0,0 +1,63 @@
+# 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) 2016. 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.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+ifeq ($(MTK_GPS_SUPPORT), true)
+$(warning [gps]BOARD_MEDIATEK_USES_GPS = $(BOARD_MEDIATEK_USES_GPS))
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(MTK_GPS_CHIP), MT3303)
+LOCAL_CFLAGS += -DCONFIG_GPS_MT3303
+endif
+
+ifneq (,$(filter MT6771 MT6775,$(MTK_PLATFORM)))
+MNLD_BUILD_MAKEFILE := $(LOCAL_PATH)/mtk_mnld_5_5/Android.mk
+else
+MNLD_BUILD_MAKEFILE := $(LOCAL_PATH)/mtk_mnld/Android.mk
+endif
+
+ALL_MAKEFILES := $(wildcard $(LOCAL_PATH)/*/Android.mk)
+MNLD_FOLDERS := $(wildcard $(LOCAL_PATH)/mtk_mnld*/Android.mk)
+ALL_EXCLUDE_MNLD_MAKEFILES := $(filter-out $(MNLD_FOLDERS),$(wildcard $(LOCAL_PATH)/*/Android.mk))
+
+$(warning ALL_MAKEFILES=$(ALL_MAKEFILES))
+$(warning MNLD_FOLDERS=$(MNLD_FOLDERS))
+$(warning ALL_EXCLUDE_MNLD_MAKEFILES=$(ALL_EXCLUDE_MNLD_MAKEFILES))
+$(warning MNLD_BUILD_MAKEFILE=$(MNLD_BUILD_MAKEFILE))
+
+include $(ALL_EXCLUDE_MNLD_MAKEFILES)
+include $(MNLD_BUILD_MAKEFILE)
+
+#include $(call all-makefiles-under,$(LOCAL_PATH))
+
+LOCAL_INIT_RC := gps.rc
+endif
diff --git a/src/connectivity/gps/flp_hal/inc/data_coder.h b/src/connectivity/gps/flp_hal/inc/data_coder.h
new file mode 100644
index 0000000..fc66d2f
--- /dev/null
+++ b/src/connectivity/gps/flp_hal/inc/data_coder.h
@@ -0,0 +1,32 @@
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char        get_byte(char* buff, int* offset, int src_len);
+short       get_short(char* buff, int* offset, int src_len);
+int         get_int(char* buff, int* offset, int src_len);
+long long   get_long(char* buff, int* offset, int src_len);
+float       get_float(char* buff, int* offset, int src_len);
+double      get_double(char* buff, int* offset, int src_len);
+char*       get_string(char* buff, int* offset, int src_len);
+char*       get_string2(char* buff, int* offset, int src_len);
+int         get_binary(char* buff, int* offset, char* output, int src_len, int des_len);
+
+void put_byte(char* buff, int* offset, const char input);
+void put_short(char* buff, int* offset, const short input);
+void put_int(char* buff, int* offset, const int input);
+void put_long(char* buff, int* offset, const long long input);
+void put_float(char* buff, int* offset, const float input);
+void put_double(char* buff, int* offset, const double input);
+void put_string(char* buff, int* offset, const char* input);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/flp_hal/inc/flphal_interface.h b/src/connectivity/gps/flp_hal/inc/flphal_interface.h
new file mode 100644
index 0000000..062e40a
--- /dev/null
+++ b/src/connectivity/gps/flp_hal/inc/flphal_interface.h
@@ -0,0 +1,114 @@
+#ifndef __HAL2FLP_INTERFACE_H__

+#define __HAL2FLP_INTERFACE_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <stdint.h>

+#include <hardware/fused_location.h>

+

+//======================================================

+// FLP -> FLP HAL

+//======================================================

+#define FLP_TO_MNL "flp_to_mnl"

+#define MNL_TO_FLP "mnl_to_flp"

+

+/*****************************************************************************

+ * FLP Return Value for APIs

+ *****************************************************************************/

+#define MTK_FLP_SUCCESS     (0)

+#define MTK_FLP_ERROR       (-1)

+#define MTK_FLP_TIMEOUT     (-2)

+

+#ifndef MTK_FLP_TRUE

+#define MTK_FLP_TRUE                (1)

+#endif

+

+#ifndef MTK_FLP_FALSE

+#define MTK_FLP_FALSE               (0)

+#endif

+

+#define HAL_FLP_BUFF_SIZE   (1 * 1024)

+

+#ifdef __aarch64__

+#define MTK_64_PLATFORM

+#endif

+

+

+/*************************************************

+  Message Table for MTK FLP

+*************************************************/

+typedef enum{

+    MTK_FLP_MSG_SYS_FLPD_RESET_NTF = 100,

+

+    //HAL messages

+    MTK_FLP_MSG_HAL_INIT_CMD = 200,

+    MTK_FLP_MSG_HAL_START_CMD,

+    MTK_FLP_MSG_HAL_STOP_CMD,

+    MTK_FLP_MSG_HAL_STOP_RSP,

+    MTK_FLP_MSG_HAL_SET_OPTION_CMD,

+    MTK_FLP_MSG_HAL_INJECT_LOC_CMD,

+    MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF,

+    MTK_FLP_MSG_HAL_DIAG_REPORT_DATA_NTF,

+

+    MTK_FLP_MSG_HSB_REPORT_LOC_NTF = 300,

+    MTK_FLP_MSG_OFL_REPORT_LOC_NTF,

+

+    MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF = 400,

+    MTK_FLP_MSG_HAL_REQUEST_LOC_NTF,

+    MTK_FLP_MSG_HAL_FLUSH_LOC_NTF,

+    MTK_FLP_MSG_HAL_REPORT_STATUS_NTF,

+    MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF,  //for Offload geofence use

+    MTK_FLP_MSG_OFL_GEOFENCE_CMD,

+

+    MTK_FLP_MSG_DC_START_CMD = 500,

+    MTK_FLP_MSG_DC_STOP_CMD,

+    MTK_FLP_MSG_CONN_SCREEN_STATUS,     //for AP to connsys screen on/off status exchange

+    MTK_FLP_MSG_END,

+}MTK_FLP_MSG_TYPE;

+

+typedef enum {

+    MTK_FLP_IDLE_MODE = -1,

+    MTK_FLP_BATCH_SLEEP_ON_FIFO_FULL = 0,

+    MTK_FLP_BATCH_WAKE_ON_FIFO_FULL = 1,

+} MTK_FLP_BATCH_MODE_T;

+

+typedef struct {

+    int type;

+    int length;

+} MTK_FLP_MSG_T;

+

+typedef struct {

+    double max_power_allocation_mW;

+    unsigned int sources_to_use;

+    int flags;

+    int64_t period_ns;

+} MTK_FLP_BATCH_OPTION_T;

+

+

+typedef FlpDiagnosticCallbacks (*FlpDiagCB)();

+typedef void (* timer_callback)();

+

+int mnl2flphal_flp_init();

+int isflp_thread_exist() ;

+void flphal2mnl_flp_init();

+int flphal2mnl_flp_start(int id, FlpBatchOptions* options);

+int flphal2mnl_flp_reboot_done_ntf();

+int flphal2mnl_update_batching_options(int id, FlpBatchOptions* options);

+int flphal2mnl_stop_batching(int id) ;

+void flphal2mnl_get_batched_location(int last_n_locations);

+int flphal2mnl_inject_location(FlpLocation* location);

+int flphal2mnl_diag_inject_data(char* data, int length);

+void flphal2mnl_flush_batched_locations() ;

+int flp_send2mnl(const char* buff, int len);

+

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/src/connectivity/gps/flp_hal/src/data_coder.c b/src/connectivity/gps/flp_hal/src/data_coder.c
new file mode 100644
index 0000000..ab67b38
--- /dev/null
+++ b/src/connectivity/gps/flp_hal/src/data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char get_byte(char* buff, int* offset, int src_len) {
+    char ret = 0;
+    if (*offset >= 0 && *offset < src_len) {
+        ret = buff[*offset];
+        *offset += 1;
+    }
+    return ret;
+}
+
+short get_short(char* buff, int* offset, int src_len) {
+    short ret = 0;
+    ret |= get_byte(buff, offset, src_len) & 0xff;
+    ret |= (get_byte(buff, offset, src_len) << 8);
+    return ret;
+}
+
+int get_int(char* buff, int* offset, int src_len) {
+    int ret = 0;
+    ret |= get_short(buff, offset, src_len) & 0xffff;
+    ret |= (get_short(buff, offset, src_len) << 16);
+    return ret;
+}
+
+long long get_long(char* buff, int* offset, int src_len) {
+    long long ret = 0;
+    ret |= get_int(buff, offset, src_len) & 0xffffffffL;
+    ret |= ((long long)get_int(buff, offset, src_len) << 32);
+    return ret;
+}
+
+float get_float(char* buff, int* offset, int src_len) {
+    float ret;
+    int tmp = get_int(buff, offset, src_len);
+    ret = *((float*)&tmp);
+    return ret;
+}
+
+double get_double(char* buff, int* offset, int src_len) {
+    double ret;
+    long long tmp = get_long(buff, offset, src_len);
+    ret = *((double*)&tmp);
+    return ret;
+}
+
+char* get_string(char* buff, int* offset, int src_len) {
+    char ret = get_byte(buff, offset, src_len);
+    if (ret == 0) {
+        return NULL;
+    } else {
+        char* p = NULL;
+        int len = get_int(buff, offset, src_len);
+        if (*offset < 0 || *offset >= src_len) {
+            *offset = 0;
+        }
+        if ((len > src_len - *offset) || len < 0) {
+            len = src_len - *offset;
+        }
+        if (len <= 0) {
+            return NULL;
+        }
+        p = &buff[*offset];
+        p[len-1] = 0;
+        *offset += len;
+        return p;
+    }
+}
+
+char* get_string2(char* buff, int* offset, int src_len) {
+    char* output = get_string(buff, offset, src_len);
+    if (output == NULL) {
+        return "";
+    } else {
+        return output;
+    }
+}
+
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+    int len = 0;
+    if (*offset >= 0 && *offset <= src_len) {
+        len = get_int(buff, offset, src_len);
+        if (len > MIN((src_len-(*offset)), des_len)) {
+            len = MIN((src_len-(*offset)), des_len);
+        }
+        if (len > 0) {
+            memcpy(output, &buff[*offset], len);
+            *offset += len;
+        }
+    }
+    return len;
+}
+
+//===============================================================
+// put
+void put_byte(char* buff, int* offset, const char input) {
+    *((char*)&buff[*offset]) = input;
+    *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+    put_byte(buff, offset, input & 0xff);
+    put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+    put_short(buff, offset, input & 0xffff);
+    put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+    put_int(buff, offset, input & 0xffffffffL);
+    put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+    int* data = (int*)&input;
+    put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+    long long* data = (long long*)&input;
+    put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+    if (input == NULL) {
+        put_byte(buff, offset, 0);
+    } else {
+        int len = strlen(input) + 1;
+        put_byte(buff, offset, 1);
+        put_int(buff, offset, len);
+        memcpy(&buff[*offset], input, len);
+        *offset += len;
+    }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+    put_int(buff, offset, len);
+    if (len > 0) {
+        memcpy(&buff[*offset], input, len);
+        *offset += len;
+    }
+}
+
diff --git a/src/connectivity/gps/flp_hal/src/flp2hal_interface.c b/src/connectivity/gps/flp_hal/src/flp2hal_interface.c
new file mode 100644
index 0000000..a69a698
--- /dev/null
+++ b/src/connectivity/gps/flp_hal/src/flp2hal_interface.c
@@ -0,0 +1,320 @@
+

+#include <unistd.h>

+#include <fcntl.h>

+#include <sys/socket.h>

+#include <sys/types.h>

+#include <sys/stat.h>

+#include <sys/un.h>

+#include "flphal_interface.h"

+#include "data_coder.h"

+#include "mtk_auto_log.h"

+

+#if defined(__ANDROID_OS__)

+#include <cutils/android_filesystem_config.h>

+#endif

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flphal"

+#endif

+

+

+/**********************************************************

+ *  Define                                                *

+ **********************************************************/

+typedef void*(*threadptr)(void*);

+#define MNLD_STRNCPY(dst,src,size) do{\

+                                       strncpy((char *)(dst), (src), (size - 1));\

+                                      (dst)[size - 1] = '\0';\

+                                     }while(0)

+

+/**********************************************************

+ *  Function Declaration                                  *

+ **********************************************************/

+void mnl2flphal_jni_thread(void);

+extern void mtk_mnl2flp_hal_response (MTK_FLP_MSG_T *prmsg);

+

+/**********************************************************

+ *  Global vars                                           *

+ **********************************************************/

+static pthread_t    hal_jni_thread_id;

+static int  g_ThreadExitJniSocket = 0, isflp_exist = 0;

+static char g_flp2mnl_path[128] = FLP_TO_MNL;

+int  g_server_socket_fd;

+

+/**********************************************************

+ *  Socket Function                                       *

+ **********************************************************/

+static int safe_recvfrom(int sockfd, char* buf, int len) {

+    int ret = 0;

+    int retry = 10;

+

+    while ((ret = recvfrom(sockfd, buf, len, 0, NULL, NULL)) == -1) {

+        //LOGW("ret=%d len=%d\n", ret, len);

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("sendto reason=[%s]\n", strerror(errno));

+        break;

+    }

+    return ret;

+}

+

+// -1 means failure

+static int safe_sendto(int sockfd, const char* dest, const char* buf, int size) {

+    int len = 0;

+    struct sockaddr_un soc_addr;

+    int retry = 10;

+

+    memset(&soc_addr, 0, sizeof(soc_addr));

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, dest,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+

+    while ((len = sendto(sockfd, buf, size, 0,  (const struct sockaddr *)&soc_addr, sizeof(soc_addr))) == -1) {

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("sendto dest=[%s] len=%d reason=[%s]\n",

+        dest, size, strerror(errno));

+        break;

+    }

+    return len;

+}

+

+int flp_send2mnl(const char* buff, int len) {

+    int ret = 0;

+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+    if (safe_sendto(sockfd, g_flp2mnl_path, buff, len) < 0) {

+        LOGE("flp_send2mnl safe_sendto failed\n");

+        ret = -1;

+    }

+    close(sockfd);

+    return ret;

+}

+

+static int bind_udp_socket(char* path) {

+    int sockfd;

+    struct sockaddr_un soc_addr;

+

+    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+    if (sockfd < 0) {

+        LOGE("socket failed reason=[%s]\n", strerror(errno));

+        return -1;

+    }

+

+    memset(&soc_addr, 0, sizeof(soc_addr));

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, path,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+    unlink(soc_addr.sun_path);

+    if (bind(sockfd, (struct sockaddr *)&soc_addr, sizeof(soc_addr)) < 0) {

+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));

+        close(sockfd);

+        return -1;

+    }

+

+    return sockfd;

+}

+

+int isflp_thread_exist() {

+    return isflp_exist;

+}

+

+

+/*************************************************************/

+/* create thread to collect response from mnl to FLP HAL     */

+/*************************************************************/

+int mnl2flphal_flp_init() {

+    int ret;

+

+    //Init client socket thread

+    if(isflp_exist) {

+        LOGE("flp thread exist");

+        return MTK_FLP_SUCCESS;

+    }

+    ret = pthread_create(&hal_jni_thread_id, NULL, (threadptr)mnl2flphal_jni_thread, NULL);

+    if(ret < 0) {

+        LOGE("Create client thread error\n");

+        return MTK_FLP_ERROR;

+    }

+    isflp_exist = 1;

+    return MTK_FLP_SUCCESS;

+}

+

+/*************************************************************/

+/*  mnl to FLP HAL socket, -1 means failure                  */

+/*************************************************************/

+int create_mnl2flphal_fd() {

+    int fd = bind_udp_socket(MNL_TO_FLP);

+    return fd;

+}

+

+/*************************************************************/

+/*  rearrange location structure in 64-bit platform          */

+/*************************************************************/

+#ifdef MTK_64_PLATFORM

+void mnl2flphal_loc_rearrange(char *loc_in, FlpLocation *loc_out) {

+    char ratio = 2; //32 to 64-bits

+    char padding_diff = 4;

+    int sizeof_loc_in = sizeof(FlpLocation) - sizeof(size_t)/ratio - padding_diff;

+

+    if((loc_out == NULL)||(loc_in == NULL)) {

+        LOGE("mnl2flphal_loc_rearrange is NULL");

+        return;

+    }

+

+    memset(loc_out, 0, sizeof(FlpLocation));

+    loc_out->size = sizeof(FlpLocation);

+    memcpy(&loc_out->flags, loc_in + sizeof(size_t)/ratio, sizeof(uint16_t));

+    memcpy(&loc_out->latitude, loc_in + sizeof(size_t), sizeof_loc_in - sizeof(size_t));

+}

+#endif

+

+/*************************************************************/

+/*  Handle message from mnl to FLP HAL                       */

+/*************************************************************/

+int mnl2flphal_hdlr (char *buff) {

+    char data[1024] ={0};

+    MTK_FLP_MSG_T *prmsg = NULL;

+    int offset = 0;

+    int ret = MTK_FLP_ERROR, len;

+    unsigned int cmd, msg_len;

+#ifdef MTK_64_PLATFORM

+    char loc_in[128] = {0};

+    FlpLocation loc_out;

+#else

+    FlpLocation loc_in = {0};

+#endif

+    MTK_FLP_MSG_T *prmsg_loc = NULL;

+

+    if(buff == NULL) {

+        LOGE("mnl2flphal_hdlr, recv prmsg is null pointer\r\n");

+        return MTK_FLP_ERROR;

+    }

+

+    len = get_binary(buff, &offset, data, HAL_FLP_BUFF_SIZE, sizeof(data));

+    if((len > 0) && (len<=1024)) {

+        prmsg = (MTK_FLP_MSG_T *)&data[0];

+    } else {

+        LOGE("len err:%d",len);

+        return ret;

+    }

+    cmd = prmsg->type;

+    msg_len = prmsg->length;

+

+    LOGD("msg_len, recv prmsg, type %u, len %d\r\n", cmd, msg_len);

+    switch (cmd) {

+        case MTK_FLP_MSG_SYS_FLPD_RESET_NTF:

+        case MTK_FLP_MSG_HAL_REQUEST_LOC_NTF:

+        case MTK_FLP_MSG_HAL_FLUSH_LOC_NTF:

+        case MTK_FLP_MSG_HAL_REPORT_STATUS_NTF:

+            //Send sys init to trigger flpd attach mnld

+            mtk_mnl2flp_hal_response((MTK_FLP_MSG_T *)prmsg);

+            break;

+        case MTK_FLP_MSG_HSB_REPORT_LOC_NTF:

+        case MTK_FLP_MSG_OFL_REPORT_LOC_NTF:

+#ifndef MTK_64_PLATFORM

+            if(msg_len % sizeof(FlpLocation) != 0) {

+                LOGE("REPORT_LOC_NTF: Data length ERROR, %d, %d",msg_len,sizeof(FlpLocation));

+                return MTK_FLP_ERROR;

+            }

+            memcpy( &loc_in, ((char *)prmsg + sizeof(MTK_FLP_MSG_T)), sizeof(FlpLocation));

+            if(loc_in.accuracy < 0.000001) {

+                LOGE("invalid_LOC_NTF: loc accuracy = %f",loc_in.accuracy);

+                return MTK_FLP_ERROR;

+            }

+            mtk_mnl2flp_hal_response((MTK_FLP_MSG_T *)prmsg);

+#else

+            memcpy( loc_in, ((char *)prmsg + sizeof(MTK_FLP_MSG_T)), 128*sizeof(char));

+            mnl2flphal_loc_rearrange(loc_in, &loc_out);

+            if(loc_out.accuracy < 0.000001) {

+                LOGE("invalid_LOC_NTF: loc accuracy = %f",loc_out.accuracy);

+                return MTK_FLP_ERROR;

+            }

+            //reform location ntf msg

+            prmsg_loc = malloc(sizeof(MTK_FLP_MSG_T)+ sizeof(FlpLocation));

+            if(prmsg_loc == NULL) {

+                LOGE("mnl2flphal_hdlr malloc failed");

+                return MTK_FLP_ERROR;

+            }

+            prmsg_loc->type = cmd;

+            prmsg_loc->length = sizeof(FlpLocation);

+            memcpy(((char*)prmsg_loc) + sizeof(MTK_FLP_MSG_T), &loc_out, sizeof(FlpLocation));

+            mtk_mnl2flp_hal_response(prmsg_loc);

+            free(prmsg_loc);

+#endif

+            break;

+        default:

+            LOGE("Uknown  received type:0x%02x", cmd);

+            break;

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+/*************************************************************/

+/*  mnl to FLP HAL main thread                               */

+/*************************************************************/

+void mnl2flphal_jni_thread(void) {

+    int ret = MTK_FLP_SUCCESS;

+    int offset = 0;

+    int read_len;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T flp_header;

+

+    LOGD("mtk_flp_hal_jni_thread, Create\n");

+

+    g_server_socket_fd = create_mnl2flphal_fd();

+

+    ///TODO: add system timer function here

+    //mtk_flp_sys_timer_create(FLP_TIMER_ID_CHECKCNN);

+    //Send SYS_INIT to HAL

+    flp_header.type = MTK_FLP_MSG_HAL_INIT_CMD;

+    flp_header.length = 0;

+    put_binary(buff, &offset, (const char*)&flp_header, sizeof(MTK_FLP_MSG_T));

+    ret = flp_send2mnl(buff, offset);

+    if(ret < 0) {

+        LOGE("MTK_HAL2FLP send error return error");

+    }

+

+    if (g_server_socket_fd >= 0) {

+        while(!g_ThreadExitJniSocket) {

+            // - recv msg from socket interface

+            read_len = safe_recvfrom(g_server_socket_fd, buff, sizeof(buff));

+            if ((read_len <= 0) || (read_len > HAL_FLP_BUFF_SIZE)) {

+                LOGE("mnl2flp safe_recvfrom failed read_len=%d", read_len);

+                continue;

+            }

+

+            if (!g_ThreadExitJniSocket) {

+                // Process received message

+                mnl2flphal_hdlr(buff);

+            } else {

+                LOGE("mtk_flp_hal_jni_thread, read msg fail,exit socket thread\n");

+                //read msg fail...

+                g_ThreadExitJniSocket = 1;

+            }

+        }

+    }

+

+    //close socket

+    LOGD("Closing server_fd,%d\r\n",g_server_socket_fd);

+    if(g_server_socket_fd >= 0) {

+        close(g_server_socket_fd);

+    }

+    LOGD("mtk_flp_hal_jni_thread, exit\n");

+    g_ThreadExitJniSocket = 1;

+    pthread_exit(NULL);

+

+    return;

+}

+

+

diff --git a/src/connectivity/gps/flp_hal/src/flpinf.c b/src/connectivity/gps/flp_hal/src/flpinf.c
new file mode 100644
index 0000000..52bea65
--- /dev/null
+++ b/src/connectivity/gps/flp_hal/src/flpinf.c
@@ -0,0 +1,560 @@
+#include <cutils/sockets.h>

+#include <sys/time.h>

+#include <time.h>

+#include <hardware/fused_location.h>

+#include "flphal_interface.h"

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flphal"

+#endif

+

+/**********************************************************

+ *  Define                                                *

+ **********************************************************/

+#define MTK_FLP_BATCH_SIZE  30

+#define UNICODE_BUF_LEN 2048

+#define FLP_BATCHED_LOCATION_FLUSH_HANDLER_TIMEOUT       (200)

+

+

+/**********************************************************

+ *  Global vars                                           *

+ **********************************************************/

+static FlpCallbacks *mtkFlpCallbacks;

+static FlpDiagnosticCallbacks *mtkFlpDiagCallbacks;

+static FlpBatchOptions  gFusedOptions;

+static int FlpCapability = 0;

+static int FlpLastStatus = 2;

+static FlpLocation  FlpLocBuffer[MTK_FLP_BATCH_SIZE];

+static int          FlpLocNum=0;

+static int          FlpLocBegin=0;

+static int          FlpLocEnd=0;

+static char         fgtimerStarted = 0;

+static char         fgtimerInit = 0;

+static timer_t batch_loc_timer;

+

+

+extern struct hw_module_t HAL_MODULE_INFO_SYM;

+static void mtk_flp_flush_loc();

+static void flp_timeout_handler();

+

+/*********************************************************/

+/* Timer Functions                                       */

+/*********************************************************/

+// -1 means failure

+timer_t init_timer_id(timer_callback cb, int id) {

+    struct sigevent sevp;

+    timer_t timerid;

+

+    memset(&sevp, 0, sizeof(sevp));

+    sevp.sigev_value.sival_int = id;

+    sevp.sigev_notify = SIGEV_THREAD;

+    sevp.sigev_notify_function = cb;

+

+    if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {

+        LOGE("timer_create  failed reason=[%s]", strerror(errno));

+        return (timer_t)-1;

+    }

+    LOGD("timer create ok\n");

+    return timerid;

+}

+

+// -1 means failure

+timer_t init_timer(timer_callback cb) {

+    return init_timer_id(cb, 0);

+}

+

+// -1 means failure

+int start_timer(timer_t timerid, int milliseconds) {

+    struct itimerspec expire;

+    expire.it_interval.tv_sec = 0;

+    expire.it_interval.tv_nsec = 0;

+    expire.it_value.tv_sec = milliseconds/1000;

+    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;

+    return timer_settime(timerid, 0, &expire, NULL);

+}

+

+// -1 means failure

+int stop_timer(timer_t timerid) {

+    return start_timer(timerid, 0);

+}

+

+/*********************************************************/

+/* FLP Location Diagnostic Interface implementation      */

+/*********************************************************/

+void mtk_flp_diag_init(FlpDiagnosticCallbacks* callbacks) {

+    TRC();

+    if(callbacks == NULL) {

+        return;

+    }

+    mtkFlpDiagCallbacks = callbacks;

+}

+

+int mtk_flp_diag_inject_data(char* data, int length) {

+    TRC();

+    return flphal2mnl_diag_inject_data(data,length);

+}

+

+/*********************************************************/

+/* FLP Device Context Interface implementation           */

+/*********************************************************/

+int  mtk_flp_dev_inject_device_context(uint32_t enabledMask) {

+    UNUSED(enabledMask);

+    return MTK_FLP_SUCCESS;

+}

+

+/*********************************************************/

+/* FLP Location Interface implementation                 */

+/*********************************************************/

+int mtk_flp_init(FlpCallbacks* callbacks) {

+    int ret = MTK_FLP_ERROR;

+    TRC();

+    if(callbacks == NULL) {

+        return ret;

+    }

+    mtkFlpCallbacks = callbacks;

+    if(mtkFlpCallbacks == NULL) {

+        LOGE("mtkFlpCallbacks == NULL");

+        return ret;

+    }

+

+    if(mtkFlpCallbacks->set_thread_event_cb) {

+        LOGE("mtkFlpCallbacks.set_thread_event_cb");

+        mtkFlpCallbacks->set_thread_event_cb(ASSOCIATE_JVM);

+    } else {

+        LOGE("set_thread_event_cb not set!!");

+    }

+

+    if(mtkFlpCallbacks->flp_capabilities_cb) {

+        LOGE("mtkFlpCallbacks.flp_capabilities_cb");

+        FlpCapability = (int)(CAPABILITY_GNSS);

+        mtkFlpCallbacks->flp_capabilities_cb(FlpCapability);

+    } else {

+        LOGE("mtkFlpCallbacks.flp_capabilities_cb not set!!");

+    }

+    if(!fgtimerInit) {

+    batch_loc_timer = init_timer(flp_timeout_handler);

+        fgtimerInit = 1;

+    }

+

+    flphal2mnl_flp_init();

+    ret = mnl2flphal_flp_init();

+    return ret;

+}

+

+int mtk_flp_get_batch_size() {

+    TRC();

+    return MTK_FLP_BATCH_SIZE;

+}

+

+int mtk_flp_start_batching(int id, FlpBatchOptions* options) {

+    TRC();

+    memcpy(&gFusedOptions,options,sizeof(FlpBatchOptions));

+    return flphal2mnl_flp_start(id, options);

+}

+

+int mtk_flp_update_batching_options(int id, FlpBatchOptions* options) {

+    TRC();

+    return flphal2mnl_update_batching_options(id, options);

+}

+

+int mtk_flp_stop_batching(int id) {

+    TRC();

+    return flphal2mnl_stop_batching(id);

+}

+

+void mtk_flp_cleanup() {

+    TRC();

+    mtkFlpDiagCallbacks = NULL;

+    mtkFlpCallbacks = NULL;

+}

+

+void mtk_flp_get_batched_location(int last_n_locations) {

+    TRC();

+    flphal2mnl_get_batched_location(last_n_locations);

+}

+

+int  mtk_flp_inject_location(FlpLocation* location) {

+    TRC();

+    return flphal2mnl_inject_location(location);

+}

+

+static const FlpDiagnosticInterface mtkFlpDiagnosticInterface = {

+    sizeof(FlpDiagnosticInterface),

+    mtk_flp_diag_init,

+    mtk_flp_diag_inject_data,

+};

+

+static const FlpDeviceContextInterface mtkFlpDeviceContextInterface = {

+    sizeof(FlpDeviceContextInterface),

+    mtk_flp_dev_inject_device_context,

+};

+

+const void* mtk_flp_get_extension(const char* name) {

+    TRC();

+    if(!strcmp(name, FLP_DIAGNOSTIC_INTERFACE)) {

+        return &mtkFlpDiagnosticInterface;

+    } else if(!strcmp(name, FLP_DEVICE_CONTEXT_INTERFACE)) {

+        return &mtkFlpDeviceContextInterface;

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+void mtk_flp_flush_batched_locations() {

+    TRC();

+    flphal2mnl_flush_batched_locations();

+}

+

+static void flp_timeout_handler() {

+    //flush location

+    mtk_flp_flush_loc();

+    stop_timer(batch_loc_timer);

+    fgtimerStarted  =0;

+    LOGD("ofl_batch_timeout\n");

+}

+

+/*********************************************************/

+/* FLP Location check and debug print                    */

+/*********************************************************/

+

+static char mtk_flp_sys_dbg_check_loc(FlpLocation *loc) {

+    if(loc->size < sizeof(FlpLocation)) {

+        LOGE("Wrong location size:%zu, %zu", loc->size, sizeof(FlpLocation));

+        return 0;

+    }

+    if(loc->longitude>180 || loc->longitude < -180 || loc->latitude >90 || loc->latitude<-90) {

+        LOGE("Wrong location value, longitude:%f, latitude:%f", loc->longitude, loc->latitude);

+        return 0;

+    }

+    return 1;

+}

+

+static void mtk_flp_sys_dbg_dump_loc(FlpLocation *loc) {

+    #if 0

+    LOGD("Location(%x):LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",

+    loc, loc->longitude, loc->latitude, loc->altitude, loc->accuracy,

+    loc->speed, loc->bearing, loc->flags, loc->sources_used, loc->timestamp);

+    #endif

+

+    if(mtk_flp_sys_dbg_check_loc(loc) != 1) {

+        LOGE("ERROR dumping location!!!!");

+        return;

+    }

+}

+

+static void mtk_flp_dump_locations(int n, FlpLocation** locs) {

+    int i;

+    TRC();

+    for(i = 0; i < n; i++){

+        mtk_flp_sys_dbg_dump_loc(locs[i]);

+    }

+}

+

+/*********************************************************/

+/* FLP Location ring buffer preparation                  */

+/*********************************************************/

+static int FlpLocRingIsFull(void) {

+    return (FlpLocNum==MTK_FLP_BATCH_SIZE);

+}

+

+static int FlpLocRingIsEmpty(void) {

+    return (FlpLocNum==0);

+}

+

+//Add one location to the Ring buffer.  Remove oldest when full.

+static void FlpLocRingAdd(FlpLocation *p) {

+    if(p == NULL) {

+        LOGE("Adding NULL");

+        return;

+    }

+    mtk_flp_sys_dbg_dump_loc(p);

+    memcpy(&FlpLocBuffer[FlpLocBegin], p, sizeof(FlpLocation));

+

+    //LOGD("LocRing Add to %d(%x),%d", FlpLocBegin, &FlpLocBuffer[FlpLocBegin],FlpLocNum);

+

+    FlpLocBegin++;

+    if(FlpLocBegin == MTK_FLP_BATCH_SIZE) {

+        FlpLocBegin = 0;

+    }

+

+    if( FlpLocNum < MTK_FLP_BATCH_SIZE) {       //if already not full yet.

+        FlpLocNum++;

+    } else {                                       //if full. drop oldest

+        FlpLocEnd++;

+        if(FlpLocEnd == MTK_FLP_BATCH_SIZE) {

+            FlpLocEnd = 0;

+        }

+    }

+}

+

+//Remove a location from tail.

+static int FlpLocRingRemove(FlpLocation **p) {

+    if(FlpLocRingIsEmpty()) {

+        LOGE("Ring empty!!!");

+        return MTK_FLP_ERROR;

+    }

+    *p = &FlpLocBuffer[FlpLocEnd];

+

+    FlpLocNum--;

+    FlpLocEnd++;

+    if(FlpLocEnd == MTK_FLP_BATCH_SIZE) {

+        FlpLocEnd = 0;

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+//return the number of locations.

+static int FlpLocRingRemoveN(FlpLocation **p, int N) {

+    int idx=0;

+    if(N<=0) {

+        LOGE("Wrong N");

+        return 0;

+    }

+

+    while(!FlpLocRingIsEmpty()) {

+        FlpLocRingRemove(&p[idx]);

+        idx++;

+        if(idx == N) {

+            break;

+        }

+    }

+    return idx;

+}

+

+

+//get the value of last N location without removing it.

+static int FlpLocRingPeekLastN(FlpLocation **p, int N) {

+    int b,e,num,cur_num=0;

+

+    b = FlpLocBegin;

+    e = FlpLocEnd;

+    num = FlpLocNum;

+

+    while(cur_num < N && num > 0) {

+        b--;

+        if(b < 0) {

+            b = MTK_FLP_BATCH_SIZE-1;

+        }

+        mtk_flp_sys_dbg_dump_loc(&FlpLocBuffer[b]);

+        p[cur_num] = &FlpLocBuffer[b];  //copy pointer only. not content.

+        //LOGD("LocRing Peek to %d(%x)", b, &FlpLocBuffer[b]);

+        num--;

+        cur_num++;

+    }

+    return cur_num;

+}

+

+/*********************************************************/

+/* FLP Location, status & NTF Callback                   */

+/*********************************************************/

+static void mtk_flp_report_loc(MTK_FLP_MSG_T *prmsg) {

+    int loc_num = 0;

+    int i;

+    FlpLocation* ptr = NULL;

+    FlpLocation *locs[MTK_FLP_BATCH_SIZE];

+

+    //TRC();

+    //add locations to ring buffer every time location is reported

+    loc_num = prmsg->length/sizeof(FlpLocation);

+    if(prmsg->type == MTK_FLP_MSG_OFL_REPORT_LOC_NTF) {

+        for(i = 0; i < loc_num; i++) {

+            ptr = (FlpLocation* )((unsigned char*)prmsg + sizeof(MTK_FLP_MSG_T) + i*sizeof(FlpLocation));

+            LOGD("report loc %d/%d", i,loc_num);

+            FlpLocRingAdd(ptr);

+        }

+        if(!fgtimerStarted) {

+            start_timer(batch_loc_timer,FLP_BATCHED_LOCATION_FLUSH_HANDLER_TIMEOUT);

+            fgtimerStarted = 1;

+            LOGD("start timer\n");

+        }

+    } else if (prmsg->type == MTK_FLP_MSG_HSB_REPORT_LOC_NTF) {

+        for(i = 0; i < loc_num; i++) {

+            ptr = (FlpLocation* )((unsigned char*)prmsg + sizeof(MTK_FLP_MSG_T) + i*sizeof(FlpLocation));

+            LOGD("report loc %d/%d", i,loc_num);

+            FlpLocRingAdd(ptr);

+        }

+

+        //LOGD("report loc, flag:%x", gFusedOptions.flags);

+        if(!FlpLocRingIsFull()) {

+            //LOGD("Location Ring not FULL");

+            return;

+        }

+        if(gFusedOptions.flags == MTK_FLP_BATCH_WAKE_ON_FIFO_FULL) { //flush data when fifo full

+            loc_num = FlpLocRingPeekLastN(locs, MTK_FLP_BATCH_SIZE);

+            LOGD("wakeOnFifoFull_TRUE: %d", loc_num);

+            if(mtkFlpCallbacks!=NULL) {

+                mtkFlpCallbacks->location_cb(loc_num, locs);

+            }

+            loc_num = FlpLocRingRemoveN( locs, MTK_FLP_BATCH_SIZE);

+            FlpLocBegin = 0;

+            FlpLocEnd = 0;

+            FlpLocNum = 0;

+        }

+    }

+}

+

+static void mtk_flp_request_loc(int req_num) {

+    int loc_num = 0, i = 0;

+    FlpLocation *locs[MTK_FLP_BATCH_SIZE];

+

+    TRC();

+    if( req_num <0 ) {

+        LOGE("request_loc size error, %d",req_num);

+        return;

+    } else if(req_num>MTK_FLP_BATCH_SIZE) {

+        req_num = MTK_FLP_BATCH_SIZE;

+    }

+    loc_num = FlpLocRingPeekLastN(locs, req_num);

+    mtk_flp_dump_locations(loc_num, locs);

+    for (i = 0; i < loc_num; i++) {

+        if(mtkFlpCallbacks!=NULL) {

+            mtkFlpCallbacks->location_cb(1, &locs[i]);

+        }

+    }

+}

+

+static void mtk_flp_flush_loc() {

+    int loc_num = 0, i = 0;

+    FlpLocation *locs[MTK_FLP_BATCH_SIZE];

+

+    loc_num = FlpLocRingPeekLastN(locs, MTK_FLP_BATCH_SIZE);

+    if(loc_num < 1) {

+        LOGD("no loc out\n");

+        return;

+    } else {

+        LOGD("loc out %d\n",loc_num);

+    }

+

+    if(mtkFlpCallbacks!=NULL) {

+        mtkFlpCallbacks->location_cb(loc_num, locs);

+    }

+    loc_num = FlpLocRingRemoveN(locs, MTK_FLP_BATCH_SIZE);

+    FlpLocBegin = 0;

+    FlpLocEnd = 0;

+    FlpLocNum = 0;

+}

+

+static void mtk_flp_report_status(int status) {

+    //LOGD("report status: %d", status);

+    if(FlpLastStatus != status) {

+        LOGD("status change from: %d to %d", FlpLastStatus, status);

+        if(mtkFlpCallbacks!=NULL) {

+            mtkFlpCallbacks->flp_status_cb(status);

+        }

+        FlpLastStatus = status;

+    }

+}

+

+

+/*********************************************************/

+/* FLP to HAL msg handler                                */

+/*********************************************************/

+void mtk_mnl2flp_hal_response (MTK_FLP_MSG_T *prmsg) {

+    int *param=NULL;

+

+    if(prmsg == NULL) {

+        LOGE("mtk_mnl2flp_hal_response, recv prmsg is null pointer\r\n");

+        return;

+    }

+    switch (prmsg->type) {

+        case MTK_FLP_MSG_SYS_FLPD_RESET_NTF:

+            flphal2mnl_flp_reboot_done_ntf();

+            // AP/ofl switch, drop batched data

+            FlpLocBegin = 0;

+            FlpLocEnd = 0;

+            FlpLocNum = 0;

+            break;

+        case MTK_FLP_MSG_HAL_REQUEST_LOC_NTF:

+            if(prmsg->length == 0 ) {

+                LOGE("mtk_mnl2flp_hal_response msg error\r\n");

+                return;

+            }

+            param = (int*)((char*)prmsg+sizeof(MTK_FLP_MSG_T));

+            mtk_flp_request_loc( *param);

+            break;

+        case MTK_FLP_MSG_HAL_FLUSH_LOC_NTF:

+            mtk_flp_flush_loc();

+            break;

+        case MTK_FLP_MSG_HAL_REPORT_STATUS_NTF:

+            param = (int*)((char*)prmsg+sizeof(MTK_FLP_MSG_T));

+            mtk_flp_report_status(*param);

+            break;

+        case MTK_FLP_MSG_HSB_REPORT_LOC_NTF:

+        case MTK_FLP_MSG_OFL_REPORT_LOC_NTF:

+            mtk_flp_report_loc(prmsg);

+            break;

+        default:

+            break;

+    }

+}

+

+

+const FlpLocationInterface  mtkFlpInterface = {

+    sizeof(FlpLocationInterface),

+    mtk_flp_init,

+    mtk_flp_get_batch_size,

+    mtk_flp_start_batching,

+    mtk_flp_update_batching_options,

+    mtk_flp_stop_batching,

+    mtk_flp_cleanup,

+    mtk_flp_get_batched_location,

+    mtk_flp_inject_location,

+    mtk_flp_get_extension,

+    mtk_flp_flush_batched_locations,

+};

+

+

+//=========================================================

+// Between

+//     FLP Interface

+//     Hardware Module Interface

+

+static const FlpLocationInterface* mtk_flp_get_flp_interface (

+    __unused struct flp_device_t* device) {

+    TRC();

+    UNUSED(device);

+    return &mtkFlpInterface;

+}

+

+static const struct flp_device_t flp_device = {

+    .common = {                           // hw_device_t

+        .tag     = HARDWARE_DEVICE_TAG,

+        .version = 0,

+        .module  = &HAL_MODULE_INFO_SYM,

+        .reserved = {0},

+        .close   = NULL

+    },

+    .get_flp_interface = mtk_flp_get_flp_interface

+};

+

+//=========================================================

+// Implementation of

+//     Hardware Module Interface

+

+static int open_flp (

+    __unused const struct hw_module_t* module,

+    __unused char const* id,

+    struct hw_device_t** device) {

+    *device = (struct hw_device_t*)&flp_device;

+    return 0;

+}

+

+static struct hw_module_methods_t flp_module_methods = {

+    .open = open_flp

+};

+

+struct hw_module_t HAL_MODULE_INFO_SYM = {

+    .tag = HARDWARE_MODULE_TAG,

+    .version_major = 1,

+    .version_minor = 0,

+    .id = FUSED_LOCATION_HARDWARE_MODULE_ID,

+    .name = "Hardware FLP Module",

+    .author = "The MTK FLP Source Project",

+    .methods = NULL,

+    .dso     = NULL,

+    .reserved = {0}

+};

+

+

+

diff --git a/src/connectivity/gps/flp_hal/src/hal2flp_interface.c b/src/connectivity/gps/flp_hal/src/hal2flp_interface.c
new file mode 100644
index 0000000..ac2c243
--- /dev/null
+++ b/src/connectivity/gps/flp_hal/src/hal2flp_interface.c
@@ -0,0 +1,402 @@
+#include <inttypes.h>

+

+#include "flphal_interface.h"

+#include "data_coder.h"

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flphal"

+#endif

+

+/**********************************************************

+ *  Define                                                *

+ **********************************************************/

+#define FLP_OPTION_MAX  10

+#define GEOFENCE_INJECT_LOC_ENUM 600

+#define MTK_GFC2HAL "mtk_gfc2hal"

+

+/**********************************************************

+ *  Global vars                                           *

+ **********************************************************/

+static FlpBatchOptions  gFlpOptions[FLP_OPTION_MAX];

+static FlpBatchOptions  gFusedOptions;

+static int gFlpFirstBatch = 1;

+

+/**********************************************************

+ *  Function Declaration                                  *

+ **********************************************************/

+static void mtk_flp_dump_options(FlpBatchOptions* options);

+static void mtk_flp_set_options(int id, FlpBatchOptions* options);

+static void mtk_flp_update_options();

+

+/*********************************************************/

+/* FLP Location Interface implementation                 */

+/*********************************************************/

+void flphal2mnl_flp_init() {

+    memset(gFlpOptions, 0, FLP_OPTION_MAX*sizeof(FlpBatchOptions));

+    return;

+}

+

+int flphal2mnl_flp_start(int id, FlpBatchOptions* options) {

+    int  ret, offset = 0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *flp_header = NULL;

+

+    if((options == NULL) || (!isflp_thread_exist())) {

+        LOGE("isflp_thread_exist:%d",isflp_thread_exist());

+        return MTK_FLP_ERROR;

+    }

+

+    mtk_flp_set_options(id, options);

+    mtk_flp_update_options();

+    if(options->sources_to_use == 0) {

+        LOGD("mtk flp start zero sources");

+        return MTK_FLP_SUCCESS;

+    }

+    if(gFlpFirstBatch == 1) {

+        LOGD("first instance, add id = %d", id);

+        flp_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(FlpBatchOptions));

+        if(flp_header== NULL) {

+            LOGE("flp start malloc failed");

+            return MTK_FLP_ERROR;

+        }

+        flp_header->type = MTK_FLP_MSG_HAL_START_CMD;

+        flp_header->length = sizeof(FlpBatchOptions);

+        memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&gFusedOptions, sizeof(FlpBatchOptions));

+        put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+        ret = flp_send2mnl(buff, offset);

+        free(flp_header);

+        if(ret < 0) {

+            LOGE("MTK_HAL2FLP send error return error");

+            return MTK_FLP_ERROR;

+        }

+        gFlpFirstBatch = 0;

+    } else {

+        LOGD("update instance, add id = %d", id);

+        flp_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(FlpBatchOptions));

+        if(flp_header== NULL) {

+            LOGE("flp start malloc failed");

+            return MTK_FLP_ERROR;

+        }

+        flp_header->type = MTK_FLP_MSG_HAL_SET_OPTION_CMD;

+        flp_header->length = sizeof(FlpBatchOptions);

+        memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&gFusedOptions, sizeof(FlpBatchOptions));

+        put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+        ret = flp_send2mnl(buff, offset);

+        free(flp_header);

+        if(ret < 0) {

+            LOGE("MTK_HAL2FLP send error return error");

+            return MTK_FLP_ERROR;

+        }

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+int flphal2mnl_flp_reboot_done_ntf() {

+    int  ret, offset = 0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *flp_header = NULL;

+

+    if(!gFlpFirstBatch) {

+        LOGD("FLP HAL RECOVER: send start cmd");

+        flp_header = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(FlpBatchOptions));

+        if(flp_header== NULL) {

+            LOGE("flp reboot malloc failed");

+            return MTK_FLP_ERROR;

+        }

+        flp_header->type = MTK_FLP_MSG_HAL_START_CMD;

+        flp_header->length = sizeof(FlpBatchOptions);

+        memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&gFusedOptions, sizeof(FlpBatchOptions));

+        put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+        ret = flp_send2mnl(buff, offset);

+        free(flp_header);

+        if(ret < 0) {

+            LOGE("MTK_HAL2FLP send error return error");

+            return MTK_FLP_ERROR;

+        }

+    } else {

+        LOGD("FLP HAL RECOVER: No need send start flp cmd");

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+int flphal2mnl_update_batching_options(int id, FlpBatchOptions* options) {

+    int ret, offset = 0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *flp_header = NULL;

+

+    if((options == NULL)||(!isflp_thread_exist())) {

+        LOGE("isflp_thread_exist:%d",isflp_thread_exist());

+        return MTK_FLP_ERROR;

+    }

+    mtk_flp_set_options(id, options);

+    mtk_flp_update_options();

+

+    //LOGD("update instance, update id = %d", id);

+    flp_header = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(FlpBatchOptions));

+    if(flp_header== NULL) {

+        LOGE("flp update malloc failed");

+        return MTK_FLP_ERROR;

+    }

+    flp_header->type = MTK_FLP_MSG_HAL_SET_OPTION_CMD;

+    flp_header->length = sizeof(FlpBatchOptions);

+    memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&gFusedOptions, sizeof(FlpBatchOptions));

+    put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+    ret = flp_send2mnl(buff, offset);

+    free(flp_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2FLP send error return error");

+        return MTK_FLP_ERROR;

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+int flphal2mnl_stop_batching(int id) {

+    int ret, offset = 0;

+    unsigned int msg_size=0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *flp_header = NULL;

+

+    if( id >= FLP_OPTION_MAX || id <0 || (!isflp_thread_exist())) {

+        LOGD("Error batching id:%d, %d", id,isflp_thread_exist());

+        return MTK_FLP_SUCCESS;

+    }

+    memset(&gFlpOptions[id], 0, sizeof(FlpBatchOptions));

+    mtk_flp_update_options();

+

+    if(gFusedOptions.sources_to_use == 0) {

+        LOGD("stop all instance, last id = %d", id);

+        flp_header = malloc(sizeof(MTK_FLP_MSG_T));

+        if(flp_header== NULL) {

+            LOGE("flp stop malloc failed");

+            return MTK_FLP_ERROR;

+        }

+        flp_header->type = MTK_FLP_MSG_HAL_STOP_CMD;

+        flp_header->length = 0;

+        put_binary(buff, &offset, (const char*)flp_header, sizeof(MTK_FLP_MSG_T));

+        ret = flp_send2mnl(buff, offset);

+        free(flp_header);

+        if(ret < 0) {

+            LOGE("MTK_HAL2FLP send error return error");

+            return MTK_FLP_ERROR;

+        }

+        gFlpFirstBatch = 1;

+    } else {

+        LOGD("update instance, stop id = %d", id);

+        flp_header = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(FlpBatchOptions));

+        if(flp_header== NULL) {

+            LOGE("flp stop malloc failed");

+            return MTK_FLP_ERROR;

+        }

+        flp_header->type = MTK_FLP_MSG_HAL_SET_OPTION_CMD;

+        flp_header->length = sizeof(FlpBatchOptions);

+        memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&gFusedOptions, sizeof(FlpBatchOptions));

+        put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+        ret = flp_send2mnl(buff, offset);

+        free(flp_header);

+        if(ret < 0) {

+            LOGE("MTK_HAL2FLP send error return error");

+            return MTK_FLP_ERROR;

+        }

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+void flphal2mnl_get_batched_location(int last_n_locations) {

+    int ret, offset = 0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *flp_header = NULL;

+

+    flp_header = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(int));

+    if(flp_header== NULL) {

+        LOGE("flp get batch malloc failed");

+        return;

+    }

+

+    flp_header->type = MTK_FLP_MSG_HAL_REQUEST_LOC_NTF;

+    flp_header->length = sizeof(int);

+    memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&last_n_locations, sizeof(int));

+    put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+    ret = flp_send2mnl(buff, offset);

+    free(flp_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2FLP send error return error");

+    }

+}

+

+int flphal2mnl_inject_location(FlpLocation* location) {

+    int ret, offset = 0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *flp_header = NULL;

+

+    if(location == NULL) {

+        return MTK_FLP_ERROR;

+    }

+

+    flp_header = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(FlpLocation));

+    if(flp_header== NULL) {

+        LOGE("flp inject loc malloc failed");

+        return MTK_FLP_ERROR;

+    }

+

+    flp_header->type = MTK_FLP_MSG_HAL_INJECT_LOC_CMD;

+    flp_header->length = sizeof(FlpLocation);

+    memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),location, sizeof(FlpLocation));

+    put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));

+    ret = flp_send2mnl(buff, offset);

+    free(flp_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2FLP send error return error");

+        return MTK_FLP_ERROR;

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+/*******************************************

+  unicode to ASCII conversion

+********************************************/

+int Unicode2Ascii(char* unicode, char * ascii, int len) {

+    int i;

+    for(i = 0; i < len; i++) {

+        ascii[i] = unicode[i*2];

+    }

+    return len;

+}

+

+

+/*********************************************************/

+/* FLP Location Diagnostic Interface implementation      */

+/*********************************************************/

+int flphal2mnl_diag_inject_data(char* data, int length) {

+    unsigned int msg_size=0;

+    int i, ret, offset = 0;

+    char asciibuf[1024];

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+

+    //geofence info injection

+    float injectGeoInfo[4] = {0};

+    char* injectGeoField;

+    int injectGeoIndex = 0;

+    MTK_FLP_MSG_T *flp_msg = NULL;

+

+    if(data == NULL || length <= 0) {

+        return MTK_FLP_ERROR;

+    }

+    Unicode2Ascii(data, asciibuf, length);

+    asciibuf[length] = '\0';

+    //LOGD("DIAG_IN:%s\n", asciibuf);

+

+    if (strncmp(asciibuf, "RESET_FLP_DATA", 14) == 0) {

+        // stop FLP

+        if (!gFlpFirstBatch) {

+            //LOGD("Reset FLP\n");

+            for (i = 0; i < FLP_OPTION_MAX; i++) {

+                memset(&gFlpOptions[i], 0, sizeof(FlpBatchOptions));

+            }

+            memset(&gFusedOptions, 0, sizeof(FlpBatchOptions));

+

+            flp_msg = malloc(sizeof(MTK_FLP_MSG_T));

+            if(flp_msg == NULL) {

+                LOGE("diag inject alloc failed");

+                return MTK_FLP_ERROR;

+            }

+            flp_msg->type = MTK_FLP_MSG_HAL_STOP_CMD;

+            flp_msg->length = 0;

+            put_binary(buff, &offset, (const char*)flp_msg, sizeof(MTK_FLP_MSG_T));

+            ret = flp_send2mnl(buff, offset);

+            free(flp_msg);

+            if(ret < 0) {

+                LOGE("MTK_HAL2FLP send error return error");

+                return MTK_FLP_ERROR;

+            }

+            gFlpFirstBatch = 1;

+        }

+    } else if (strncmp(asciibuf, "GEO_COR", 7) == 0) {

+        injectGeoField = strtok(asciibuf, ",");

+        if (injectGeoField) {

+            injectGeoField = strtok(NULL, ",");

+        }

+        while (injectGeoField && injectGeoIndex < 4) {

+            injectGeoInfo[injectGeoIndex] = atof(injectGeoField);

+            injectGeoIndex++;

+            injectGeoField = strtok(NULL, ",");

+        }

+        flp_msg = malloc(sizeof(MTK_FLP_MSG_T)+3*sizeof(float));

+        if(flp_msg == NULL) {

+            LOGE("GEO_COR alloc failed");

+            return MTK_FLP_ERROR;

+        }

+        flp_msg->type = GEOFENCE_INJECT_LOC_ENUM;

+        flp_msg->length = 3*sizeof(float);

+        memcpy((char *)flp_msg+sizeof(MTK_FLP_MSG_T),&injectGeoInfo[0],3*sizeof(float));

+        put_binary(buff, &offset, (const char*)flp_msg, (flp_msg->length+sizeof(MTK_FLP_MSG_T)));

+        ret = flp_send2mnl(buff, offset);

+        free(flp_msg);

+        if(ret < 0) {

+            LOGE("GEOFENCE_INJECT_LOC_ENUM MTK_GFC2HAL send error return error");

+            return MTK_FLP_ERROR;

+        }

+    }

+    return MTK_FLP_SUCCESS;

+}

+

+void flphal2mnl_flush_batched_locations() {

+    int ret, offset = 0;

+    char buff[HAL_FLP_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T flp_header;

+

+    flp_header.type = MTK_FLP_MSG_HAL_FLUSH_LOC_NTF;

+    flp_header.length = 0;

+    put_binary(buff, &offset, (const char*)&flp_header, sizeof(MTK_FLP_MSG_T));

+    ret = flp_send2mnl(buff, offset);

+    if(ret < 0) {

+        LOGE("MTK_HAL2FLP send error return error");

+    }

+}

+

+static void mtk_flp_dump_options(FlpBatchOptions* options) {

+    LOGD("BatchOptions:flg %d,max_pow: %lf, period %" PRId64 ", source %d\n",

+        options->flags, options->max_power_allocation_mW, options->period_ns,

+        options->sources_to_use);

+}

+

+static void mtk_flp_set_options(int id, FlpBatchOptions* options) {

+    if( options == NULL) {

+        LOGE("WRONG USAGE of mtk_flp_set_options");

+        return;

+    }

+    //LOGD("mtk_flp_set_options id = %d",id);

+    memcpy( &gFlpOptions[id], options, sizeof(FlpBatchOptions));

+    mtk_flp_dump_options((FlpBatchOptions*)&gFlpOptions[id]);

+}

+

+static void mtk_flp_update_options() {

+    int i;

+

+    memset(&gFusedOptions, 0, sizeof(FlpBatchOptions));

+    gFusedOptions.period_ns = 1000000000000;

+

+    // update gFusedOptions

+    for(i = 0; i < FLP_OPTION_MAX; i++) {

+        if(gFlpOptions[i].sources_to_use == 0) {

+            continue;

+        }

+        gFusedOptions.sources_to_use |= gFlpOptions[i].sources_to_use;

+        if(gFusedOptions.period_ns > gFlpOptions[i].period_ns) {

+            gFusedOptions.period_ns = gFlpOptions[i].period_ns;

+        }

+        if(gFusedOptions.flags < gFlpOptions[i].flags) {

+            gFusedOptions.flags = gFlpOptions[i].flags;

+        }

+        gFusedOptions.max_power_allocation_mW = gFlpOptions[i].max_power_allocation_mW;

+    }

+    if(gFusedOptions.period_ns == 1000000000000) {

+        gFusedOptions.period_ns = 0;

+    }

+    //LOGD("mtk_flp_update_options");

+    mtk_flp_dump_options(&gFusedOptions);

+}

+

+

+

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;
+}
diff --git a/src/connectivity/gps/gps.rc b/src/connectivity/gps/gps.rc
new file mode 100644
index 0000000..500ed88
--- /dev/null
+++ b/src/connectivity/gps/gps.rc
@@ -0,0 +1,24 @@
+# GPS

+    mkdir /data/vendor/gps_mnl 0771 gps system

+    mkdir /data/vendor/misc/gps 0770 gps system

+    chown gps system /data/vendor/mpe_mnl

+    chown gps gps /sys/class/gpsdrv/gps/pwrctl

+    chown gps gps /sys/class/gpsdrv/gps/suspend

+    chown gps gps /sys/class/gpsdrv/gps/state

+    chown gps gps /sys/class/gpsdrv/gps/pwrsave

+    chown gps gps /sys/class/gpsdrv/gps/status

+

+#/dev/ttyS1 for GPS 3337 usage

+    chmod 0660 /dev/ttyS1

+    chown system system /dev/ttyS1

+

+# GPS EMI

+    chmod 666 /dev/gps_emi

+

+# GPS

+service mnld /vendor/bin/mnld

+    class main

+    user gps

+    group gps inet misc sdcard_rw sdcard_r media_rw system radio

+    socket mnld stream 660 gps system

+

diff --git a/src/connectivity/gps/gps_hal/Android.mk b/src/connectivity/gps/gps_hal/Android.mk
new file mode 100644
index 0000000..9956a5a
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/Android.mk
@@ -0,0 +1,84 @@
+# 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) 2016. 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.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+ifeq ($(BOARD_GPS_LIBRARIES), true)
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SHARED_LIBRARIES := \
+					liblog \
+					libcutils \
+					libhardware
+
+LOCAL_HEADER_LIBRARIES := libcutils_headers
+
+LOCAL_C_INCLUDES += \
+      $(LOCAL_PATH)/inc \
+      $(TOP)/hardware/libhardware/include \
+      $(TOP)/system/core/include \
+      $(TOP)/system/core/libcutils/include
+
+LOCAL_SRC_FILES += \
+	    src/hal2mnl_interface.c \
+		src/hal_mnl_interface_common.c \
+		src/data_coder.c \
+		src/mtk_lbs_utility.c \
+		src/agpsinf.c \
+		src/gpshal.c \
+		src/gpshal_worker.c \
+		src/gfchal_mnl_interface.c \
+		src/geofenceinf.c \
+  		src/mtk_auto_log.c \
+
+ifeq ($(MTK_GPS_CHIP),MTK_GPS_MT3337)
+LOCAL_SRC_FILES += \
+            src/gpsinf3337.c
+else
+LOCAL_SRC_FILES += \
+            src/gpsinf.c
+endif
+
+LOCAL_CFLAGS += -D__ANDROID_OS__
+
+LOCAL_MODULE := gps.$(TARGET_BOARD_PLATFORM)
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/src/connectivity/gps/gps_hal/LICENSE b/src/connectivity/gps/gps_hal/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/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/gps_hal/Makefile.am b/src/connectivity/gps/gps_hal/Makefile.am
new file mode 100644
index 0000000..a7dc7af
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/Makefile.am
@@ -0,0 +1,29 @@
+AUTOMAKE_OPTIONS=foreign subdir-objects
+lib_LTLIBRARIES = libgpshal.la
+
+libgpshal_la_SOURCES =  src/hal2mnl_interface.c \
+		src/hal_mnl_interface_common.c \
+		src/data_coder.c \
+		src/mtk_lbs_utility.c \
+		src/agpsinf.c \
+		src/gpshal.c \
+		src/gpshal_worker.c \
+		src/gfchal_mnl_interface.c \
+		src/geofenceinf.c \
+  		src/mtk_auto_log.c \
+  		src/gpsinf.c
+
+AM_CFLAGS = -Iinc \
+		-Iinc/hardware \
+		-Ihardware
+
+include_HEADERS = hardware/gps.h \
+		inc/hardware/gps_mtk.h \
+		hardware/gps_internal.h \
+		inc/hal_mnl_interface_common.h \
+		inc/mtk_lbs_utility.h \
+		inc/hal2mnl_interface.h
+
+libgpshal_la_LIBADD = -lrt
+
+DEFS+=-D__LINUX_OS__ -DMTK_GPS_DATA_PATH="\"/usr/share/gps/\""
diff --git a/src/connectivity/gps/gps_hal/NOTICE b/src/connectivity/gps/gps_hal/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/gps_hal/README b/src/connectivity/gps/gps_hal/README
new file mode 100644
index 0000000..92f6303
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/README
@@ -0,0 +1,44 @@
+This directory contains GPS HAL layer code.
+
+WHAT IT DOES?
+=============
+It provide GPS interfaces for gps provider on frameworks,which allow init/open/close/cleanup gps 
+when mnld daemon is launched.
+
+HOW IT WAS BUILT?
+==================
+
+It needs the following libs from AOSP:
+1.  libc.so
+2.  libcutils
+3.  libnetutils
+4.  libhardware
+5.  libandroid_runtime
+6.  libnativehelper
+7.  libcrypto
+8.  libssl
+9.  libz
+
+and the following libs from MediaTek:
+1. liblog.so
+2. libepos.a
+3. libcurl
+
+All source/dependency modules of this module are already put in
+'vendor/mediatek/libs' folder.
+
+
+HOW TO USE IT?
+==============
+
+Files in this directory is used to
+generate a library which's name is 'gps.mtxxxx.so'
+
+
+gps.mtxxxx
+mtxxxx means chip platform name,
+The lib 'gps.mtxxxx' is loaded by system_server,
+GPS Location provider will call gps_module_methods API, if system_server is launched.
+
+All the source code of this library were written by MediaTek co..
+
diff --git a/src/connectivity/gps/gps_hal/configure.ac b/src/connectivity/gps/gps_hal/configure.ac
new file mode 100644
index 0000000..9334153
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/configure.ac
@@ -0,0 +1,8 @@
+AC_INIT([gpshal], [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/gps_hal/hardware/gps.h b/src/connectivity/gps/gps_hal/hardware/gps.h
new file mode 100644
index 0000000..11804f3
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/hardware/gps.h
@@ -0,0 +1,2234 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_H
+
+#ifdef __LINUX_OS__
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+/*
+ * Enums defined in HIDL in hardware/interfaces are auto-generated and present
+ * in gnss-base.h.
+ */
+
+/* for compatibility */
+
+/*#define GPS_REQUEST_AGPS_DATA_CONN GNSS_REQUEST_AGNSS_DATA_CONN
+#define GPS_RELEASE_AGPS_DATA_CONN GNSS_RELEASE_AGNSS_DATA_CONN
+#define GPS_AGPS_DATA_CONNECTED GNSS_AGNSS_DATA_CONNECTED
+#define GPS_AGPS_DATA_CONN_DONE GNSS_AGNSS_DATA_CONN_DONE
+#define GPS_AGPS_DATA_CONN_FAILED GNSS_AGNSS_DATA_CONN_FAILED
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS AGPS_RIL_NETWORK_TYPE_MMS
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL AGPS_RIL_NETWORK_TYPE_SUPL
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN AGPS_RIL_NETWORK_TYPE_DUN
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI AGPS_RIL_NETWORK_TYPE_HIPRI
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX AGPS_RIL_NETWORK_TYPE_WIMAX
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT GNSS_MULTIPATH_INDICATIOR_NOT_PRESENT
+#define AGPS_SETID_TYPE_MSISDN AGPS_SETID_TYPE_MSISDM
+#define GPS_MEASUREMENT_OPERATION_SUCCESS GPS_MEASUREMENT_SUCCESS
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS GPS_NAVIGATION_MESSAGE_SUCCESS
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L2CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L5CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_CNAV2
+#define GPS_LOCATION_HAS_ACCURACY GPS_LOCATION_HAS_HORIZONTAL_ACCURACY
+*/
+/**
+ * The id of this module
+ */
+#define GPS_HARDWARE_MODULE_ID "gps"
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS             0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT         -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC              -101
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GpsUtcTime;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in gps_measurement_callback(). */
+#define GPS_MAX_MEASUREMENT   32
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT   64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t GpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define GPS_POSITION_MODE_STANDALONE    0
+/** AGPS MS-Based mode. */
+#define GPS_POSITION_MODE_MS_BASED      1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define GPS_POSITION_MODE_MS_ASSISTED   2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t GpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define GPS_POSITION_RECURRENCE_PERIODIC    0
+/** Request a single shot GPS fix. */
+#define GPS_POSITION_RECURRENCE_SINGLE      1
+
+/** GPS status event values. */
+typedef uint16_t GpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define GPS_STATUS_NONE             0
+/** GPS has begun navigating. */
+#define GPS_STATUS_SESSION_BEGIN    1
+/** GPS has stopped navigating. */
+#define GPS_STATUS_SESSION_END      2
+/** GPS has powered on but is not navigating. */
+#define GPS_STATUS_ENGINE_ON        3
+/** GPS is powered off. */
+#define GPS_STATUS_ENGINE_OFF       4
+
+/** Flags to indicate which values are valid in a GpsLocation. */
+typedef uint16_t GpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GpsLocation has valid latitude and longitude. */
+#define GPS_LOCATION_HAS_LAT_LONG   0x0001
+/** GpsLocation has valid altitude. */
+#define GPS_LOCATION_HAS_ALTITUDE   0x0002
+/** GpsLocation has valid speed. */
+#define GPS_LOCATION_HAS_SPEED      0x0004
+/** GpsLocation has valid bearing. */
+#define GPS_LOCATION_HAS_BEARING    0x0008
+/** GpsLocation has valid accuracy. */
+#define GPS_LOCATION_HAS_ACCURACY   0x0010
+
+/**
+ * GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define GPS_CAPABILITY_SCHEDULING       (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define GPS_CAPABILITY_MSB              (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define GPS_CAPABILITY_MSA              (1 << 2)
+/** GPS supports single-shot fixes */
+#define GPS_CAPABILITY_SINGLE_SHOT      (1 << 3)
+/** GPS supports on demand time injection */
+#define GPS_CAPABILITY_ON_DEMAND_TIME   (1 << 4)
+/** GPS supports Geofencing  */
+#define GPS_CAPABILITY_GEOFENCING       (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS     (1 << 6)
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES     (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t GpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#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
+
+/** AGPS type */
+typedef uint16_t AGpsType;
+#define AGPS_TYPE_SUPL          1
+#define AGPS_TYPE_C2K           2
+
+typedef uint16_t AGpsSetIDType;
+#define AGPS_SETID_TYPE_NONE    0
+#define AGPS_SETID_TYPE_IMSI    1
+#define AGPS_SETID_TYPE_MSISDN  2
+
+typedef uint16_t ApnIpType;
+#define APN_IP_INVALID          0
+#define APN_IP_IPV4             1
+#define APN_IP_IPV6             2
+#define APN_IP_IPV4V6           3
+
+/**
+ * String length constants
+ */
+#define GPS_NI_SHORT_STRING_MAXLEN      256
+#define GPS_NI_LONG_STRING_MAXLEN       2048
+
+/**
+ * GpsNiType constants
+ */
+typedef uint32_t GpsNiType;
+#define GPS_NI_TYPE_VOICE              1
+#define GPS_NI_TYPE_UMTS_SUPL          2
+#define GPS_NI_TYPE_UMTS_CTRL_PLANE    3
+
+/**
+ * GpsNiNotifyFlags constants
+ */
+typedef uint32_t GpsNiNotifyFlags;
+/** NI requires notification */
+#define GPS_NI_NEED_NOTIFY          0x0001
+/** NI requires verification */
+#define GPS_NI_NEED_VERIFY          0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define GPS_NI_PRIVACY_OVERRIDE     0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int GpsUserResponseType;
+#define GPS_NI_RESPONSE_ACCEPT         1
+#define GPS_NI_RESPONSE_DENY           2
+#define GPS_NI_RESPONSE_NORESP         3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int GpsNiEncodingType;
+#define GPS_ENC_NONE                   0
+#define GPS_ENC_SUPL_GSM_DEFAULT       1
+#define GPS_ENC_SUPL_UTF8              2
+#define GPS_ENC_SUPL_UCS2              3
+#define GPS_ENC_UNKNOWN                -1
+
+/** AGPS status event values. */
+typedef uint16_t AGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define GPS_REQUEST_AGPS_DATA_CONN  1
+/** GPS releases the AGPS data connection. */
+#define GPS_RELEASE_AGPS_DATA_CONN  2
+/** AGPS data connection initiated */
+#define GPS_AGPS_DATA_CONNECTED     3
+/** AGPS data connection completed */
+#define GPS_AGPS_DATA_CONN_DONE     4
+/** AGPS data connection failed */
+#define GPS_AGPS_DATA_CONN_FAILED   5
+
+typedef uint16_t AGpsRefLocationType;
+#define AGPS_REF_LOCATION_TYPE_GSM_CELLID   1
+#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID  2
+#define AGPS_REF_LOCATION_TYPE_MAC          3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID   4
+
+/* Deprecated, to be removed in the next Android release. */
+#define AGPS_REG_LOCATION_TYPE_MAC          3
+
+/** Network types for update_network_state "type" parameter */
+#define AGPS_RIL_NETWORK_TYPE_MOBILE        0
+#define AGPS_RIL_NETWORK_TYPE_WIFI          1
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS    2
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL   3
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN   4
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX        6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsClockFlags;
+#define GPS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+#define GPS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+#define GPS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+#define GPS_CLOCK_HAS_BIAS                      (1<<3)
+#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+#define GPS_CLOCK_HAS_DRIFT                     (1<<5)
+#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/**
+ * Flags to indicate what fields in GnssClock are valid.
+ */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsClockType;
+#define GPS_CLOCK_TYPE_UNKNOWN                  0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME            1
+#define GPS_CLOCK_TYPE_GPS_TIME                 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t GpsMeasurementFlags;
+#define GPS_MEASUREMENT_HAS_SNR                               (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION                         (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY             (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH                           (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY               (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE                       (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY           (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE                        (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY            (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER                        (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT                (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                     (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY         (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX                       (1<<17)
+#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE      (1<<18)
+
+/**
+ * Flags to indicate what fields in GnssMeasurement are valid.
+ */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsLossOfLock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN                            0
+#define GPS_LOSS_OF_LOCK_OK                                 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP                         2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
+ */
+typedef uint8_t GpsMultipathIndicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN                 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED                1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED                2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsMeasurementState;
+#define GPS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ *         GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsAccumulatedDeltaRangeState;
+#define GPS_ADR_STATE_UNKNOWN                       0
+#define GPS_ADR_STATE_VALID                     (1<<0)
+#define GPS_ADR_STATE_RESET                     (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN                       0
+#define GNSS_ADR_STATE_VALID                     (1<<0)
+#define GNSS_ADR_STATE_RESET                     (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN         0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA            1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV          2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV          3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2           4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN              0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW              0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t                                 GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE                      0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA        (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA          (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX               (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t                         GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN      0
+#define GNSS_CONSTELLATION_GPS          1
+#define GNSS_CONSTELLATION_SBAS         2
+#define GNSS_CONSTELLATION_GLONASS      3
+#define GNSS_CONSTELLATION_QZSS         4
+#define GNSS_CONSTELLATION_BEIDOU       5
+#define GNSS_CONSTELLATION_GALILEO      6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define GPS_XTRA_INTERFACE      "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define GPS_DEBUG_INTERFACE      "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+#define AGPS_INTERFACE      "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define SUPL_CERTIFICATE_INTERFACE  "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define AGPS_RIL_INTERFACE      "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define GPS_GEOFENCING_INTERFACE   "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define GPS_MEASUREMENT_INTERFACE   "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define GPS_NAVIGATION_MESSAGE_INTERFACE     "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define GNSS_CONFIGURATION_INTERFACE     "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(GpsLocation) */
+    size_t          size;
+    /** Contains GpsLocationFlags bits. */
+    uint16_t        flags;
+    /** Represents latitude in degrees. */
+    double          latitude;
+    /** Represents longitude in degrees. */
+    double          longitude;
+    /**
+     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     */
+    double          altitude;
+    /** Represents speed in meters per second. */
+    float           speed;
+    /** Represents heading in degrees. */
+    float           bearing;
+    /** Represents expected accuracy in meters. */
+    float           accuracy;
+    /** Timestamp for the location fix. */
+    GpsUtcTime      timestamp;
+} GpsLocation;
+
+/** Represents the status. */
+typedef struct {
+    /** set to sizeof(GpsStatus) */
+    size_t          size;
+    GpsStatusValue status;
+} GpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvInfo) */
+    size_t          size;
+    /** Pseudo-random number for the SV. */
+    int     prn;
+    /** Signal to noise ratio. */
+    float   snr;
+    /** Elevation of SV in degrees. */
+    float   elevation;
+    /** Azimuth of SV in degrees. */
+    float   azimuth;
+} GpsSvInfo;
+
+typedef struct {
+    /** set to sizeof(GnssSvInfo) */
+    size_t size;
+
+    /**
+     * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+     * distinction is made by looking at constellation field. Values should be
+     * in the range of:
+     *
+     * - GPS:     1-32
+     * - SBAS:    120-151, 183-192
+     * - GLONASS: 1-24, the orbital slot number (OSN), if known.  Or, if not:
+     *            93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+     *            i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+     * - QZSS:    193-200
+     * - Galileo: 1-36
+     * - Beidou:  1-37
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    float c_n0_dbhz;
+
+    /** Elevation of SV in degrees. */
+    float elevation;
+
+    /** Azimuth of SV in degrees. */
+    float azimuth;
+
+    /**
+     * Contains additional data about the given SV. Value should be one of those
+     * GNSS_SV_FLAGS_* constants
+     */
+    GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvStatus) */
+    size_t size;
+    int num_svs;
+    GpsSvInfo sv_list[GPS_MAX_SVS];
+    uint32_t ephemeris_mask;
+    uint32_t almanac_mask;
+    uint32_t used_in_fix_mask;
+} GpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+    AGpsRefLocationType type;
+    /** Mobile Country Code. */
+    uint16_t mcc;
+    /** Mobile Network Code .*/
+    uint16_t mnc;
+    /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+     * lac is populated with tac, to ensure that we don't break old clients that
+     * might rely in the old (wrong) behavior.
+     */
+    uint16_t lac;
+    /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+    uint32_t cid;
+    /** Tracking Area Code in LTE. */
+    uint16_t tac;
+    /** Physical Cell id in LTE (not used in 2G and 3G) */
+    uint16_t pcid;
+} AGpsRefLocationCellID;
+
+typedef struct {
+    uint8_t mac[6];
+} AGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+    AGpsRefLocationType type;
+    union {
+        AGpsRefLocationCellID   cellID;
+        AGpsRefLocationMac      mac;
+    } u;
+} AGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_callback)(GpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* gps_status_callback)(GpsStatus* status);
+
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
+ */
+typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of GPS_CAPABILITY_* flags.
+ */
+typedef void (* gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+    /** Set to sizeof(GnssSystemInfo) */
+    size_t   size;
+    /* year in which the last update was made to the underlying hardware/firmware
+     * used to capture GNSS signals, e.g. 2016 */
+    uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int   (*init)( GpsCallbacks* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+} GpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+    gps_xtra_download_request download_request_cb;
+    gps_create_thread create_thread_cb;
+} GpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+    /** set to sizeof(GpsXtraInterface) */
+    size_t          size;
+    /**
+     * Opens the XTRA interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int  (*init)( GpsXtraCallbacks* callbacks );
+    /** Injects XTRA data into the GPS. */
+    int  (*inject_xtra_data)( char* data, int length );
+} GpsXtraInterface;
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} GpsDebugInterface;
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus) */
+    size_t                  size;
+
+    AGpsType                type;
+    AGpsStatusValue         status;
+
+    /**
+     * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+     * address, or set to INADDR_NONE otherwise.
+     */
+    uint32_t                ipaddr;
+
+    /**
+     * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+     * Any other value of addr.ss_family will be rejected.
+     */
+    struct sockaddr_storage addr;
+} AGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* agps_status_callback)(AGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+    agps_status_callback status_cb;
+    gps_create_thread create_thread_cb;
+} AGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface) */
+    size_t size;
+
+    /**
+     * Opens the AGPS interface and provides the callback routines to the
+     * implementation of this interface.
+     */
+    void (*init)(AGpsCallbacks* callbacks);
+    /**
+     * Deprecated.
+     * If the HAL supports AGpsInterface_v2 this API will not be used, see
+     * data_conn_open_with_apn_ip_type for more information.
+     */
+    int (*data_conn_open)(const char* apn);
+    /**
+     * Notifies that the AGPS data connection has been closed.
+     */
+    int (*data_conn_closed)();
+    /**
+     * Notifies that a data connection is not available for AGPS.
+     */
+    int (*data_conn_failed)();
+    /**
+     * Sets the hostname and port for the AGPS server.
+     */
+    int (*set_server)(AGpsType type, const char* hostname, int port);
+
+    /**
+     * Notifies that a data connection is available and sets the name of the
+     * APN, and its IP type, to be used for SUPL connections.
+     */
+    int (*data_conn_open_with_apn_ip_type)(
+            const char* apn,
+            ApnIpType apnIpType);
+} AGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define AGPS_CERTIFICATE_OPERATION_SUCCESS               0
+#define AGPS_CERTIFICATE_ERROR_GENERIC                -100
+#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES  -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+    size_t  length;
+    u_char* data;
+} DerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+    u_char data[20];
+} Sha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+    /** set to sizeof(SuplCertificateInterface) */
+    size_t size;
+
+    /**
+     * Installs a set of Certificates used for SUPL connections to the AGPS server.
+     * If needed the HAL should find out internally any certificates that need to be removed to
+     * accommodate the certificates to install.
+     * The certificates installed represent a full set of valid certificates needed to connect to
+     * AGPS SUPL servers.
+     * The list of certificates is required, and all must be available at the same time, when trying
+     * to establish a connection with the AGPS Server.
+     *
+     * Parameters:
+     *      certificates - A pointer to an array of DER encoded certificates that are need to be
+     *                     installed in the HAL.
+     *      length - The number of certificates to install.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+     *      AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+     *          certificates attempted to be installed, the state of the certificates stored should
+     *          remain the same as before on this error case.
+     *
+     * IMPORTANT:
+     *      If needed the HAL should find out internally the set of certificates that need to be
+     *      removed to accommodate the certificates to install.
+     */
+    int  (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length );
+
+    /**
+     * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+     * expected that the given set of certificates is removed from the internal store of the HAL.
+     *
+     * Parameters:
+     *      fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+     *                     certificates to revoke.
+     *      length - The number of fingerprints provided.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+     *
+     * IMPORTANT:
+     *      If any of the certificates provided (through its fingerprint) is not known by the HAL,
+     *      it should be ignored and continue revoking/deleting the rest of them.
+     */
+    int  (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length );
+} SuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+    /** set to sizeof(GpsNiNotification) */
+    size_t          size;
+
+    /**
+     * An ID generated by HAL to associate NI notifications and UI
+     * responses
+     */
+    int             notification_id;
+
+    /**
+     * An NI type used to distinguish different categories of NI
+     * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ...
+     */
+    GpsNiType       ni_type;
+
+    /**
+     * Notification/verification options, combinations of GpsNiNotifyFlags constants
+     */
+    GpsNiNotifyFlags notify_flags;
+
+    /**
+     * Timeout period to wait for user response.
+     * Set to 0 for no time out limit.
+     */
+    int             timeout;
+
+    /**
+     * Default response when time out.
+     */
+    GpsUserResponseType default_response;
+
+    /**
+     * Requestor ID
+     */
+    char            requestor_id[GPS_NI_SHORT_STRING_MAXLEN];
+
+    /**
+     * Notification message. It can also be used to store client_id in some cases
+     */
+    char            text[GPS_NI_LONG_STRING_MAXLEN];
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType requestor_id_encoding;
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType text_encoding;
+
+    /**
+     * A pointer to extra data. Format:
+     * key_1 = value_1
+     * key_2 = value_2
+     */
+    char           extras[GPS_NI_LONG_STRING_MAXLEN];
+
+} GpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+    /**
+     * Sends the notification request from HAL to GPSLocationProvider.
+     */
+    gps_ni_notify_callback notify_cb;
+    gps_create_thread create_thread_cb;
+} GpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+    /** set to sizeof(GpsNiInterface) */
+    size_t          size;
+
+   /** Registers the callbacks for HAL to use. */
+   void (*init) (GpsNiCallbacks *callbacks);
+
+   /** Sends a response to HAL. */
+   void (*respond) (int notif_id, GpsUserResponseType user_response);
+} GpsNiInterface;
+
+#if defined(__ANDROID_OS__)
+struct gps_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct gps_device_t {
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#endif
+
+#define AGPS_RIL_REQUEST_REFLOC_CELLID  (1<<0L)
+#define AGPS_RIL_REQUEST_REFLOC_MAC     (1<<1L)
+
+typedef void (*agps_ril_request_set_id)(uint32_t flags);
+typedef void (*agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+    agps_ril_request_set_id request_setid;
+    agps_ril_request_ref_loc request_refloc;
+    gps_create_thread create_thread_cb;
+} AGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+    /** set to sizeof(AGpsRilInterface) */
+    size_t          size;
+    /**
+     * Opens the AGPS interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    void  (*init)( AGpsRilCallbacks* callbacks );
+
+    /**
+     * Sets the reference location.
+     */
+    void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+    /**
+     * Sets the set ID.
+     */
+    void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+    /**
+     * Send network initiated message.
+     */
+    void (*ni_message) (uint8_t *msg, size_t len);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ *      There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ *     In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define GPS_GEOFENCE_ENTERED     (1<<0L)
+#define GPS_GEOFENCE_EXITED      (1<<1L)
+#define GPS_GEOFENCE_UNCERTAIN   (1<<2L)
+
+#define GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define GPS_GEOFENCE_AVAILABLE   (1<<1L)
+
+#define GPS_GEOFENCE_OPERATION_SUCCESS           0
+#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define GPS_GEOFENCE_ERROR_ID_EXISTS          -101
+#define GPS_GEOFENCE_ERROR_ID_UNKNOWN         -102
+#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define GPS_GEOFENCE_ERROR_GENERIC            -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_callback) (int32_t geofence_id,  GpsLocation* location,
+        int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          GPS_GEOFENCE_ERROR_ID_EXISTS  - geofence with id already exists
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+    gps_geofence_transition_callback geofence_transition_callback;
+    gps_geofence_status_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsClock) */
+    size_t size;
+    GpsClockFlags flags;
+    int16_t leap_second;
+    GpsClockType type;
+    int64_t time_ns;
+    double time_uncertainty_ns;
+    int64_t full_bias_ns;
+    double bias_ns;
+    double bias_uncertainty_ns;
+    double drift_nsps;
+    double drift_uncertainty_nsps;
+} GpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+    /** set to sizeof(GnssClock) */
+    size_t size;
+
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    GnssClockFlags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+     *      1,000,000,000
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+     */
+    int16_t leap_second;
+
+    /**
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
+     *
+     * For local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * available) from this value.
+     *
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+     * The value contains the 'time uncertainty' in it.
+     *
+     * This field is mandatory.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * The sign of the value is defined by the following equation:
+     *      local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+     *
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * bias) in nanoseconds. The uncertainty is represented as an absolute
+     * (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+     *
+     * This value is mandatory if the receiver has estimated GNSS time
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
+     */
+    double drift_uncertainty_nsps;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+    GpsMeasurementFlags flags;
+    int8_t prn;
+    double time_offset_ns;
+    GpsMeasurementState state;
+    int64_t received_gps_tow_ns;
+    int64_t received_gps_tow_uncertainty_ns;
+    double c_n0_dbhz;
+    double pseudorange_rate_mps;
+    double pseudorange_rate_uncertainty_mps;
+    GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+    double accumulated_delta_range_m;
+    double accumulated_delta_range_uncertainty_m;
+    double pseudorange_m;
+    double pseudorange_uncertainty_m;
+    double code_phase_chips;
+    double code_phase_uncertainty_chips;
+    float carrier_frequency_hz;
+    int64_t carrier_cycles;
+    double carrier_phase;
+    double carrier_phase_uncertainty;
+    GpsLossOfLock loss_of_lock;
+    int32_t bit_number;
+    int16_t time_from_last_bit_ms;
+    double doppler_shift_hz;
+    double doppler_shift_uncertainty_hz;
+    GpsMultipathIndicator multipath_indicator;
+    double snr_db;
+    double elevation_deg;
+    double elevation_uncertainty_deg;
+    double azimuth_deg;
+    double azimuth_uncertainty_deg;
+    bool used_in_fix;
+} GpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    GnssMeasurementFlags flags;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     *
+     * This is a mandatory value.
+     */
+    GnssMeasurementState state;
+
+    /**
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
+     *
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     *
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_sv_time_uncertainty_in_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s. The correction of a given
+     * Pseudorange Rate value includes corrections for receiver and satellite
+     * clock frequency errors. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
+     *
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+     * shift' is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     *
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This is a mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     *
+     * This is a mandatory value.
+     */
+    GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     *
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
+     *
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
+     */
+    GnssMultipathIndicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
+     */
+    double snr_db;
+} GnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsData) */
+    size_t size;
+    size_t measurement_count;
+    GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GpsClock clock;
+} GpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gps_measurement_callback) (GpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks;
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsMeasurementCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface;
+
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsNavigationMessage) */
+    size_t size;
+    int8_t prn;
+    GpsNavigationMessageType type;
+    NavigationMessageStatus status;
+    int16_t message_id;
+    int16_t submessage_id;
+    size_t data_length;
+    uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+    /** set to sizeof(GnssNavigationMessage) */
+    size_t size;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a mandatory value.
+     */
+    GnssNavigationMessageType type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    NavigationMessageStatus status;
+
+    /**
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
+     */
+    int16_t message_id;
+
+    /**
+     * Sub-message identifier. If required by the message 'type', this value
+     * contains a sub-index within the current message (or frame) that is being
+     * transmitted.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+     */
+    int16_t submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     *
+     * This is a mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+     *
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
+     */
+    uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+    /** set to sizeof(GpsNavigationMessageCallbacks) */
+    size_t size;
+    gps_navigation_message_callback navigation_message_callback;
+    gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsNavigationMessageInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates as they become
+     * available.
+     *
+     * Status:
+     *      GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+     *      GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+     *              without a corresponding call to 'close'.
+     *      GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+     *              the HAL will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsNavigationMessageInterface;
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+} GnssConfigurationInterface;
+
+__END_DECLS
+
+#endif
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/gps_hal/hardware/gps_internal.h b/src/connectivity/gps/gps_hal/hardware/gps_internal.h
new file mode 100644
index 0000000..67a16e8
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/hardware/gps_internal.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+
+#ifdef __LINUX_OS__
+//#include <hardware/gps.h>
+#include "gps.h"
+
+/****************************************************************************
+ * This file contains legacy structs that are deprecated/retired from gps.h *
+ ****************************************************************************/
+
+__BEGIN_DECLS
+
+/**
+ * Legacy GPS callback structure.
+ * Deprecated, to be removed in the next Android release.
+ * Use GpsCallbacks instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsCallbacks_v1) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+} GpsCallbacks_v1;
+
+#pragma pack(push,4)
+// We need to keep the alignment of this data structure to 4-bytes, to ensure that in 64-bit
+// environments the size of this legacy definition does not collide with _v2. Implementations should
+// be using _v2 and _v3, so it's OK to pay the 'unaligned' penalty in 64-bit if an old
+// implementation is still in use.
+
+/**
+ * Legacy struct to represent the status of AGPS.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v1) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+} AGpsStatus_v1;
+
+#pragma pack(pop)
+
+/**
+ * Legacy struct to represent the status of AGPS augmented with a IPv4 address
+ * field.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v2) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+
+    /*-------------------- New fields in _v2 --------------------*/
+
+    uint32_t        ipaddr;
+} AGpsStatus_v2;
+
+/**
+ * Legacy extended interface for AGPS support.
+ * See AGpsInterface_v2 for more information.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface_v1) */
+    size_t          size;
+    void  (*init)( AGpsCallbacks* callbacks );
+    int  (*data_conn_open)( const char* apn );
+    int  (*data_conn_closed)();
+    int  (*data_conn_failed)();
+    int  (*set_server)( AGpsType type, const char* hostname, int port );
+} AGpsInterface_v1;
+
+__END_DECLS
+
+#endif
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H */
diff --git a/src/connectivity/gps/gps_hal/inc/data_coder.h b/src/connectivity/gps/gps_hal/inc/data_coder.h
new file mode 100644
index 0000000..fc66d2f
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/data_coder.h
@@ -0,0 +1,32 @@
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char        get_byte(char* buff, int* offset, int src_len);
+short       get_short(char* buff, int* offset, int src_len);
+int         get_int(char* buff, int* offset, int src_len);
+long long   get_long(char* buff, int* offset, int src_len);
+float       get_float(char* buff, int* offset, int src_len);
+double      get_double(char* buff, int* offset, int src_len);
+char*       get_string(char* buff, int* offset, int src_len);
+char*       get_string2(char* buff, int* offset, int src_len);
+int         get_binary(char* buff, int* offset, char* output, int src_len, int des_len);
+
+void put_byte(char* buff, int* offset, const char input);
+void put_short(char* buff, int* offset, const short input);
+void put_int(char* buff, int* offset, const int input);
+void put_long(char* buff, int* offset, const long long input);
+void put_float(char* buff, int* offset, const float input);
+void put_double(char* buff, int* offset, const double input);
+void put_string(char* buff, int* offset, const char* input);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/gps_hal/inc/geofencehal_worker.h b/src/connectivity/gps/gps_hal/inc/geofencehal_worker.h
new file mode 100644
index 0000000..e5542dc
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/geofencehal_worker.h
@@ -0,0 +1,142 @@
+#ifndef __GEOFENCE_HAL_WORKER_H__

+#define __GEOFENCE_HAL_WORKER_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#include <stdint.h>

+#include <pthread.h>

+#include "data_coder.h"

+

+#if defined(__ANDROID_OS__)

+#include <hardware/gps.h>

+#elif defined(__LINUX_OS__)

+#include "gps.h"

+#endif

+

+//======================================================

+// GFC(GPS HAL) -> MNL

+//======================================================

+#define GEOFENCE_TO_MNL "gfc_to_mnl"

+#define MNL_TO_GEOFENCE "mnl_to_gfc"

+

+#define HAL_GFC_BUFF_SIZE   (1 * 1024)

+#define MAX_GOEFENCE 30

+#define GEO_CONFIG_MASK_DISABLE_SMD     (1U<<0)

+#ifdef __aarch64__

+#define MTK_64_PLATFORM

+#endif

+

+#define MTK_GFC_SUCCESS     (0)

+#define MTK_GFC_ERROR       (-1)

+#define MTK_GFC_TIMEOUT     (-2)

+

+

+typedef enum {

+    MTK_FLP_MSG_SYS_FLPD_RESET_NTF = 100,

+

+    //HAL messages

+    MTK_FLP_MSG_HAL_INIT_CMD = 200,

+    MTK_FLP_MSG_HAL_START_CMD,

+    MTK_FLP_MSG_HAL_STOP_CMD,

+    MTK_FLP_MSG_HAL_STOP_RSP,

+    MTK_FLP_MSG_HAL_SET_OPTION_CMD,

+    MTK_FLP_MSG_HAL_INJECT_LOC_CMD,

+    MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF,

+    MTK_FLP_MSG_HAL_DIAG_REPORT_DATA_NTF,

+

+    MTK_FLP_MSG_HSB_REPORT_LOC_NTF = 300,

+    MTK_FLP_MSG_OFL_REPORT_LOC_NTF,

+

+    MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF = 400,

+    MTK_FLP_MSG_HAL_REQUEST_LOC_NTF,

+    MTK_FLP_MSG_HAL_FLUSH_LOC_NTF,

+    MTK_FLP_MSG_HAL_REPORT_STATUS_NTF,

+    MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF,  //for Offload geofence use

+    MTK_FLP_MSG_OFL_GEOFENCE_CMD,

+

+    MTK_FLP_MSG_DC_START_CMD = 500,

+    MTK_FLP_MSG_DC_STOP_CMD,

+    MTK_FLP_MSG_CONN_SCREEN_STATUS,     //for AP to connsys screen on/off status exchange

+    MTK_FLP_MSG_END,

+}MTK_FLP_MSG_TYPE;

+

+typedef enum {

+    inside,

+    outside,

+    uncertain

+} SET_STATE;

+

+typedef enum {

+    INIT_GEOFENCE,

+    ADD_GEOFENCE_AREA,

+    PAUSE_GEOFENCE,

+    RESUME_GEOFENCE,

+    REMOVE_GEOFENCE,

+    RECOVER_GEOFENCE,

+    CLEAR_GEOFENCE,

+} MTK_GFC_COMMAND_T;

+

+typedef enum {

+    GEOFENCE_ADD_CALLBACK,

+    GEOFENCE_REMOVE_CALLBACK,

+    GEOFENCE_PAUSE_CALLBACK,

+    GEOFENCE_RESUME_CALLBACK

+} GEOFENCE_CALLBACK_T;

+

+typedef struct mtk_geofence_area {

+    int32_t geofence_id;

+    double latitude;

+    double longitude;

+    double radius;

+    float coordinate_dn;

+    float coordinate_de;

+    int last_transition; /*current state, most cases is GPS_GEOFENCE_UNCERTAIN*/

+    int monitor_transition; /*bitwise or of  entered/exited/uncertain*/

+    int notification_period;/*timer  interval, period of report transition status*/

+    int unknown_timer;/*continue positioning time limitied while positioning*/

+    int alive;/*geofence status, 1 alive, 0 sleep*/

+    SET_STATE latest_state;/*latest status: outside, inside, uncertain*/

+    uint32_t config;

+} MTK_GEOFENCE_PROPERTY_T;

+

+typedef struct {

+    int type;

+    int length;

+} MTK_FLP_MSG_T;

+

+typedef struct mtk_geofence_callback {

+    int32_t cb_id;

+    int32_t geofence_id;

+    int32_t result;

+} MTK_GEOFENCE_CALLBACK_T;

+

+

+void hal2_geofence_init();

+int is_gfc_exist();

+void hal2_geofence_add_geofences(const MTK_GEOFENCE_PROPERTY_T dbg_fence);

+void hal2_geofence_pause_geofence(const int32_t geofence_id);

+void hal2_geofence_resume_geofence(const int32_t geofence_id, const int monitor_transitions);

+void hal2_geofence_remove_geofences(const int32_t geofence_id);

+void mtk_geo_inject_info_set(int fence_id, float dn, float de);

+void mtk_geo_inject_info_get(int fence_id, float* dn, float* de);

+int check_buff_fence_exist(const int32_t fence_id);

+int set_buff_transition_fence(const int32_t fence_id, const int transition);

+#ifdef MTK_64_PLATFORM

+void mtk_loc_rearrange(unsigned char *loc_in, GpsLocation *loc_out);

+#endif

+

+//Callbacks to GPS HAL

+void mtk_geofence_transition_callbacks_proc(MTK_FLP_MSG_T *prmsg);

+void mtk_geofence_callbacks_proc(MTK_FLP_MSG_T *prmsg);

+

+

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

+

+

diff --git a/src/connectivity/gps/gps_hal/inc/gps.h b/src/connectivity/gps/gps_hal/inc/gps.h
new file mode 100644
index 0000000..596499c
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/gps.h
@@ -0,0 +1,2233 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#ifdef __ANDROID_OS__
+#include <hardware/hardware.h>
+#endif
+__BEGIN_DECLS
+
+/*
+ * Enums defined in HIDL in hardware/interfaces are auto-generated and present
+ * in gnss-base.h.
+ */
+
+/* for compatibility */
+
+/*#define GPS_REQUEST_AGPS_DATA_CONN GNSS_REQUEST_AGNSS_DATA_CONN
+#define GPS_RELEASE_AGPS_DATA_CONN GNSS_RELEASE_AGNSS_DATA_CONN
+#define GPS_AGPS_DATA_CONNECTED GNSS_AGNSS_DATA_CONNECTED
+#define GPS_AGPS_DATA_CONN_DONE GNSS_AGNSS_DATA_CONN_DONE
+#define GPS_AGPS_DATA_CONN_FAILED GNSS_AGNSS_DATA_CONN_FAILED
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS AGPS_RIL_NETWORK_TYPE_MMS
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL AGPS_RIL_NETWORK_TYPE_SUPL
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN AGPS_RIL_NETWORK_TYPE_DUN
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI AGPS_RIL_NETWORK_TYPE_HIPRI
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX AGPS_RIL_NETWORK_TYPE_WIMAX
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT GNSS_MULTIPATH_INDICATIOR_NOT_PRESENT
+#define AGPS_SETID_TYPE_MSISDN AGPS_SETID_TYPE_MSISDM
+#define GPS_MEASUREMENT_OPERATION_SUCCESS GPS_MEASUREMENT_SUCCESS
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS GPS_NAVIGATION_MESSAGE_SUCCESS
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L2CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L5CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_CNAV2
+#define GPS_LOCATION_HAS_ACCURACY GPS_LOCATION_HAS_HORIZONTAL_ACCURACY
+*/
+/**
+ * The id of this module
+ */
+#define GPS_HARDWARE_MODULE_ID "gps"
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS             0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT         -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC              -101
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GpsUtcTime;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in gps_measurement_callback(). */
+#define GPS_MAX_MEASUREMENT   32
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT   64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t GpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define GPS_POSITION_MODE_STANDALONE    0
+/** AGPS MS-Based mode. */
+#define GPS_POSITION_MODE_MS_BASED      1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define GPS_POSITION_MODE_MS_ASSISTED   2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t GpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define GPS_POSITION_RECURRENCE_PERIODIC    0
+/** Request a single shot GPS fix. */
+#define GPS_POSITION_RECURRENCE_SINGLE      1
+
+/** GPS status event values. */
+typedef uint16_t GpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define GPS_STATUS_NONE             0
+/** GPS has begun navigating. */
+#define GPS_STATUS_SESSION_BEGIN    1
+/** GPS has stopped navigating. */
+#define GPS_STATUS_SESSION_END      2
+/** GPS has powered on but is not navigating. */
+#define GPS_STATUS_ENGINE_ON        3
+/** GPS is powered off. */
+#define GPS_STATUS_ENGINE_OFF       4
+
+/** Flags to indicate which values are valid in a GpsLocation. */
+typedef uint16_t GpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GpsLocation has valid latitude and longitude. */
+#define GPS_LOCATION_HAS_LAT_LONG   0x0001
+/** GpsLocation has valid altitude. */
+#define GPS_LOCATION_HAS_ALTITUDE   0x0002
+/** GpsLocation has valid speed. */
+#define GPS_LOCATION_HAS_SPEED      0x0004
+/** GpsLocation has valid bearing. */
+#define GPS_LOCATION_HAS_BEARING    0x0008
+/** GpsLocation has valid accuracy. */
+#define GPS_LOCATION_HAS_ACCURACY   0x0010
+
+/**
+ * GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define GPS_CAPABILITY_SCHEDULING       (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define GPS_CAPABILITY_MSB              (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define GPS_CAPABILITY_MSA              (1 << 2)
+/** GPS supports single-shot fixes */
+#define GPS_CAPABILITY_SINGLE_SHOT      (1 << 3)
+/** GPS supports on demand time injection */
+#define GPS_CAPABILITY_ON_DEMAND_TIME   (1 << 4)
+/** GPS supports Geofencing  */
+#define GPS_CAPABILITY_GEOFENCING       (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS     (1 << 6)
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES     (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t GpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#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
+
+/** AGPS type */
+typedef uint16_t AGpsType;
+#define AGPS_TYPE_SUPL          1
+#define AGPS_TYPE_C2K           2
+
+typedef uint16_t AGpsSetIDType;
+#define AGPS_SETID_TYPE_NONE    0
+#define AGPS_SETID_TYPE_IMSI    1
+#define AGPS_SETID_TYPE_MSISDN  2
+
+typedef uint16_t ApnIpType;
+#define APN_IP_INVALID          0
+#define APN_IP_IPV4             1
+#define APN_IP_IPV6             2
+#define APN_IP_IPV4V6           3
+
+/**
+ * String length constants
+ */
+#define GPS_NI_SHORT_STRING_MAXLEN      256
+#define GPS_NI_LONG_STRING_MAXLEN       2048
+
+/**
+ * GpsNiType constants
+ */
+typedef uint32_t GpsNiType;
+#define GPS_NI_TYPE_VOICE              1
+#define GPS_NI_TYPE_UMTS_SUPL          2
+#define GPS_NI_TYPE_UMTS_CTRL_PLANE    3
+
+/**
+ * GpsNiNotifyFlags constants
+ */
+typedef uint32_t GpsNiNotifyFlags;
+/** NI requires notification */
+#define GPS_NI_NEED_NOTIFY          0x0001
+/** NI requires verification */
+#define GPS_NI_NEED_VERIFY          0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define GPS_NI_PRIVACY_OVERRIDE     0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int GpsUserResponseType;
+#define GPS_NI_RESPONSE_ACCEPT         1
+#define GPS_NI_RESPONSE_DENY           2
+#define GPS_NI_RESPONSE_NORESP         3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int GpsNiEncodingType;
+#define GPS_ENC_NONE                   0
+#define GPS_ENC_SUPL_GSM_DEFAULT       1
+#define GPS_ENC_SUPL_UTF8              2
+#define GPS_ENC_SUPL_UCS2              3
+#define GPS_ENC_UNKNOWN                -1
+
+/** AGPS status event values. */
+typedef uint16_t AGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define GPS_REQUEST_AGPS_DATA_CONN  1
+/** GPS releases the AGPS data connection. */
+#define GPS_RELEASE_AGPS_DATA_CONN  2
+/** AGPS data connection initiated */
+#define GPS_AGPS_DATA_CONNECTED     3
+/** AGPS data connection completed */
+#define GPS_AGPS_DATA_CONN_DONE     4
+/** AGPS data connection failed */
+#define GPS_AGPS_DATA_CONN_FAILED   5
+
+typedef uint16_t AGpsRefLocationType;
+#define AGPS_REF_LOCATION_TYPE_GSM_CELLID   1
+#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID  2
+#define AGPS_REF_LOCATION_TYPE_MAC          3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID   4
+
+/* Deprecated, to be removed in the next Android release. */
+#define AGPS_REG_LOCATION_TYPE_MAC          3
+
+/** Network types for update_network_state "type" parameter */
+#define AGPS_RIL_NETWORK_TYPE_MOBILE        0
+#define AGPS_RIL_NETWORK_TYPE_WIFI          1
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS    2
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL   3
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN   4
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX        6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsClockFlags;
+#define GPS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+#define GPS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+#define GPS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+#define GPS_CLOCK_HAS_BIAS                      (1<<3)
+#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+#define GPS_CLOCK_HAS_DRIFT                     (1<<5)
+#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/**
+ * Flags to indicate what fields in GnssClock are valid.
+ */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsClockType;
+#define GPS_CLOCK_TYPE_UNKNOWN                  0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME            1
+#define GPS_CLOCK_TYPE_GPS_TIME                 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t GpsMeasurementFlags;
+#define GPS_MEASUREMENT_HAS_SNR                               (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION                         (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY             (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH                           (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY               (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE                       (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY           (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE                        (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY            (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER                        (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT                (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                     (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY         (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX                       (1<<17)
+#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE      (1<<18)
+
+/**
+ * Flags to indicate what fields in GnssMeasurement are valid.
+ */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsLossOfLock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN                            0
+#define GPS_LOSS_OF_LOCK_OK                                 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP                         2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
+ */
+typedef uint8_t GpsMultipathIndicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN                 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED                1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED                2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsMeasurementState;
+#define GPS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ *         GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsAccumulatedDeltaRangeState;
+#define GPS_ADR_STATE_UNKNOWN                       0
+#define GPS_ADR_STATE_VALID                     (1<<0)
+#define GPS_ADR_STATE_RESET                     (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN                       0
+#define GNSS_ADR_STATE_VALID                     (1<<0)
+#define GNSS_ADR_STATE_RESET                     (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN         0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA            1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV          2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV          3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2           4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN              0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW              0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t                                 GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE                      0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA        (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA          (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX               (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t                         GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN      0
+#define GNSS_CONSTELLATION_GPS          1
+#define GNSS_CONSTELLATION_SBAS         2
+#define GNSS_CONSTELLATION_GLONASS      3
+#define GNSS_CONSTELLATION_QZSS         4
+#define GNSS_CONSTELLATION_BEIDOU       5
+#define GNSS_CONSTELLATION_GALILEO      6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define GPS_XTRA_INTERFACE      "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define GPS_DEBUG_INTERFACE      "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+#define AGPS_INTERFACE      "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define SUPL_CERTIFICATE_INTERFACE  "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define AGPS_RIL_INTERFACE      "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define GPS_GEOFENCING_INTERFACE   "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define GPS_MEASUREMENT_INTERFACE   "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define GPS_NAVIGATION_MESSAGE_INTERFACE     "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define GNSS_CONFIGURATION_INTERFACE     "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(GpsLocation) */
+    size_t          size;
+    /** Contains GpsLocationFlags bits. */
+    uint16_t        flags;
+    /** Represents latitude in degrees. */
+    double          latitude;
+    /** Represents longitude in degrees. */
+    double          longitude;
+    /**
+     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     */
+    double          altitude;
+    /** Represents speed in meters per second. */
+    float           speed;
+    /** Represents heading in degrees. */
+    float           bearing;
+    /** Represents expected accuracy in meters. */
+    float           accuracy;
+    /** Timestamp for the location fix. */
+    GpsUtcTime      timestamp;
+} GpsLocation;
+
+/** Represents the status. */
+typedef struct {
+    /** set to sizeof(GpsStatus) */
+    size_t          size;
+    GpsStatusValue status;
+} GpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvInfo) */
+    size_t          size;
+    /** Pseudo-random number for the SV. */
+    int     prn;
+    /** Signal to noise ratio. */
+    float   snr;
+    /** Elevation of SV in degrees. */
+    float   elevation;
+    /** Azimuth of SV in degrees. */
+    float   azimuth;
+} GpsSvInfo;
+
+typedef struct {
+    /** set to sizeof(GnssSvInfo) */
+    size_t size;
+
+    /**
+     * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+     * distinction is made by looking at constellation field. Values should be
+     * in the range of:
+     *
+     * - GPS:     1-32
+     * - SBAS:    120-151, 183-192
+     * - GLONASS: 1-24, the orbital slot number (OSN), if known.  Or, if not:
+     *            93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+     *            i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+     * - QZSS:    193-200
+     * - Galileo: 1-36
+     * - Beidou:  1-37
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    float c_n0_dbhz;
+
+    /** Elevation of SV in degrees. */
+    float elevation;
+
+    /** Azimuth of SV in degrees. */
+    float azimuth;
+
+    /**
+     * Contains additional data about the given SV. Value should be one of those
+     * GNSS_SV_FLAGS_* constants
+     */
+    GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvStatus) */
+    size_t size;
+    int num_svs;
+    GpsSvInfo sv_list[GPS_MAX_SVS];
+    uint32_t ephemeris_mask;
+    uint32_t almanac_mask;
+    uint32_t used_in_fix_mask;
+} GpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+    AGpsRefLocationType type;
+    /** Mobile Country Code. */
+    uint16_t mcc;
+    /** Mobile Network Code .*/
+    uint16_t mnc;
+    /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+     * lac is populated with tac, to ensure that we don't break old clients that
+     * might rely in the old (wrong) behavior.
+     */
+    uint16_t lac;
+    /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+    uint32_t cid;
+    /** Tracking Area Code in LTE. */
+    uint16_t tac;
+    /** Physical Cell id in LTE (not used in 2G and 3G) */
+    uint16_t pcid;
+} AGpsRefLocationCellID;
+
+typedef struct {
+    uint8_t mac[6];
+} AGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+    AGpsRefLocationType type;
+    union {
+        AGpsRefLocationCellID   cellID;
+        AGpsRefLocationMac      mac;
+    } u;
+} AGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_callback)(GpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* gps_status_callback)(GpsStatus* status);
+
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
+ */
+typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of GPS_CAPABILITY_* flags.
+ */
+typedef void (* gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+    /** Set to sizeof(GnssSystemInfo) */
+    size_t   size;
+    /* year in which the last update was made to the underlying hardware/firmware
+     * used to capture GNSS signals, e.g. 2016 */
+    uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int   (*init)( GpsCallbacks* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+} GpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+    gps_xtra_download_request download_request_cb;
+    gps_create_thread create_thread_cb;
+} GpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+    /** set to sizeof(GpsXtraInterface) */
+    size_t          size;
+    /**
+     * Opens the XTRA interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int  (*init)( GpsXtraCallbacks* callbacks );
+    /** Injects XTRA data into the GPS. */
+    int  (*inject_xtra_data)( char* data, int length );
+} GpsXtraInterface;
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} GpsDebugInterface;
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus) */
+    size_t                  size;
+
+    AGpsType                type;
+    AGpsStatusValue         status;
+
+    /**
+     * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+     * address, or set to INADDR_NONE otherwise.
+     */
+    uint32_t                ipaddr;
+
+    /**
+     * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+     * Any other value of addr.ss_family will be rejected.
+     */
+    struct sockaddr_storage addr;
+} AGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* agps_status_callback)(AGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+    agps_status_callback status_cb;
+    gps_create_thread create_thread_cb;
+} AGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface) */
+    size_t size;
+
+    /**
+     * Opens the AGPS interface and provides the callback routines to the
+     * implementation of this interface.
+     */
+    void (*init)(AGpsCallbacks* callbacks);
+    /**
+     * Deprecated.
+     * If the HAL supports AGpsInterface_v2 this API will not be used, see
+     * data_conn_open_with_apn_ip_type for more information.
+     */
+    int (*data_conn_open)(const char* apn);
+    /**
+     * Notifies that the AGPS data connection has been closed.
+     */
+    int (*data_conn_closed)();
+    /**
+     * Notifies that a data connection is not available for AGPS.
+     */
+    int (*data_conn_failed)();
+    /**
+     * Sets the hostname and port for the AGPS server.
+     */
+    int (*set_server)(AGpsType type, const char* hostname, int port);
+
+    /**
+     * Notifies that a data connection is available and sets the name of the
+     * APN, and its IP type, to be used for SUPL connections.
+     */
+    int (*data_conn_open_with_apn_ip_type)(
+            const char* apn,
+            ApnIpType apnIpType);
+} AGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define AGPS_CERTIFICATE_OPERATION_SUCCESS               0
+#define AGPS_CERTIFICATE_ERROR_GENERIC                -100
+#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES  -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+    size_t  length;
+    u_char* data;
+} DerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+    u_char data[20];
+} Sha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+    /** set to sizeof(SuplCertificateInterface) */
+    size_t size;
+
+    /**
+     * Installs a set of Certificates used for SUPL connections to the AGPS server.
+     * If needed the HAL should find out internally any certificates that need to be removed to
+     * accommodate the certificates to install.
+     * The certificates installed represent a full set of valid certificates needed to connect to
+     * AGPS SUPL servers.
+     * The list of certificates is required, and all must be available at the same time, when trying
+     * to establish a connection with the AGPS Server.
+     *
+     * Parameters:
+     *      certificates - A pointer to an array of DER encoded certificates that are need to be
+     *                     installed in the HAL.
+     *      length - The number of certificates to install.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+     *      AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+     *          certificates attempted to be installed, the state of the certificates stored should
+     *          remain the same as before on this error case.
+     *
+     * IMPORTANT:
+     *      If needed the HAL should find out internally the set of certificates that need to be
+     *      removed to accommodate the certificates to install.
+     */
+    int  (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length );
+
+    /**
+     * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+     * expected that the given set of certificates is removed from the internal store of the HAL.
+     *
+     * Parameters:
+     *      fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+     *                     certificates to revoke.
+     *      length - The number of fingerprints provided.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+     *
+     * IMPORTANT:
+     *      If any of the certificates provided (through its fingerprint) is not known by the HAL,
+     *      it should be ignored and continue revoking/deleting the rest of them.
+     */
+    int  (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length );
+} SuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+    /** set to sizeof(GpsNiNotification) */
+    size_t          size;
+
+    /**
+     * An ID generated by HAL to associate NI notifications and UI
+     * responses
+     */
+    int             notification_id;
+
+    /**
+     * An NI type used to distinguish different categories of NI
+     * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ...
+     */
+    GpsNiType       ni_type;
+
+    /**
+     * Notification/verification options, combinations of GpsNiNotifyFlags constants
+     */
+    GpsNiNotifyFlags notify_flags;
+
+    /**
+     * Timeout period to wait for user response.
+     * Set to 0 for no time out limit.
+     */
+    int             timeout;
+
+    /**
+     * Default response when time out.
+     */
+    GpsUserResponseType default_response;
+
+    /**
+     * Requestor ID
+     */
+    char            requestor_id[GPS_NI_SHORT_STRING_MAXLEN];
+
+    /**
+     * Notification message. It can also be used to store client_id in some cases
+     */
+    char            text[GPS_NI_LONG_STRING_MAXLEN];
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType requestor_id_encoding;
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType text_encoding;
+
+    /**
+     * A pointer to extra data. Format:
+     * key_1 = value_1
+     * key_2 = value_2
+     */
+    char           extras[GPS_NI_LONG_STRING_MAXLEN];
+
+} GpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+    /**
+     * Sends the notification request from HAL to GPSLocationProvider.
+     */
+    gps_ni_notify_callback notify_cb;
+    gps_create_thread create_thread_cb;
+} GpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+    /** set to sizeof(GpsNiInterface) */
+    size_t          size;
+
+   /** Registers the callbacks for HAL to use. */
+   void (*init) (GpsNiCallbacks *callbacks);
+
+   /** Sends a response to HAL. */
+   void (*respond) (int notif_id, GpsUserResponseType user_response);
+} GpsNiInterface;
+
+#if defined(__ANDROID_OS__)
+struct gps_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct gps_device_t {
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#endif
+
+#define AGPS_RIL_REQUEST_REFLOC_CELLID  (1<<0L)
+#define AGPS_RIL_REQUEST_REFLOC_MAC     (1<<1L)
+
+typedef void (*agps_ril_request_set_id)(uint32_t flags);
+typedef void (*agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+    agps_ril_request_set_id request_setid;
+    agps_ril_request_ref_loc request_refloc;
+    gps_create_thread create_thread_cb;
+} AGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+    /** set to sizeof(AGpsRilInterface) */
+    size_t          size;
+    /**
+     * Opens the AGPS interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    void  (*init)( AGpsRilCallbacks* callbacks );
+
+    /**
+     * Sets the reference location.
+     */
+    void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+    /**
+     * Sets the set ID.
+     */
+    void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+    /**
+     * Send network initiated message.
+     */
+    void (*ni_message) (uint8_t *msg, size_t len);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ *      There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ *     In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define GPS_GEOFENCE_ENTERED     (1<<0L)
+#define GPS_GEOFENCE_EXITED      (1<<1L)
+#define GPS_GEOFENCE_UNCERTAIN   (1<<2L)
+
+#define GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define GPS_GEOFENCE_AVAILABLE   (1<<1L)
+
+#define GPS_GEOFENCE_OPERATION_SUCCESS           0
+#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define GPS_GEOFENCE_ERROR_ID_EXISTS          -101
+#define GPS_GEOFENCE_ERROR_ID_UNKNOWN         -102
+#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define GPS_GEOFENCE_ERROR_GENERIC            -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_callback) (int32_t geofence_id,  GpsLocation* location,
+        int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          GPS_GEOFENCE_ERROR_ID_EXISTS  - geofence with id already exists
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+    gps_geofence_transition_callback geofence_transition_callback;
+    gps_geofence_status_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsClock) */
+    size_t size;
+    GpsClockFlags flags;
+    int16_t leap_second;
+    GpsClockType type;
+    int64_t time_ns;
+    double time_uncertainty_ns;
+    int64_t full_bias_ns;
+    double bias_ns;
+    double bias_uncertainty_ns;
+    double drift_nsps;
+    double drift_uncertainty_nsps;
+} GpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+    /** set to sizeof(GnssClock) */
+    size_t size;
+
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    GnssClockFlags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+     *      1,000,000,000
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+     */
+    int16_t leap_second;
+
+    /**
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
+     *
+     * For local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * available) from this value.
+     *
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+     * The value contains the 'time uncertainty' in it.
+     *
+     * This field is mandatory.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * The sign of the value is defined by the following equation:
+     *      local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+     *
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * bias) in nanoseconds. The uncertainty is represented as an absolute
+     * (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+     *
+     * This value is mandatory if the receiver has estimated GNSS time
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
+     */
+    double drift_uncertainty_nsps;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+    GpsMeasurementFlags flags;
+    int8_t prn;
+    double time_offset_ns;
+    GpsMeasurementState state;
+    int64_t received_gps_tow_ns;
+    int64_t received_gps_tow_uncertainty_ns;
+    double c_n0_dbhz;
+    double pseudorange_rate_mps;
+    double pseudorange_rate_uncertainty_mps;
+    GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+    double accumulated_delta_range_m;
+    double accumulated_delta_range_uncertainty_m;
+    double pseudorange_m;
+    double pseudorange_uncertainty_m;
+    double code_phase_chips;
+    double code_phase_uncertainty_chips;
+    float carrier_frequency_hz;
+    int64_t carrier_cycles;
+    double carrier_phase;
+    double carrier_phase_uncertainty;
+    GpsLossOfLock loss_of_lock;
+    int32_t bit_number;
+    int16_t time_from_last_bit_ms;
+    double doppler_shift_hz;
+    double doppler_shift_uncertainty_hz;
+    GpsMultipathIndicator multipath_indicator;
+    double snr_db;
+    double elevation_deg;
+    double elevation_uncertainty_deg;
+    double azimuth_deg;
+    double azimuth_uncertainty_deg;
+    bool used_in_fix;
+} GpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    GnssMeasurementFlags flags;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     *
+     * This is a mandatory value.
+     */
+    GnssMeasurementState state;
+
+    /**
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
+     *
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     *
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_sv_time_uncertainty_in_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s. The correction of a given
+     * Pseudorange Rate value includes corrections for receiver and satellite
+     * clock frequency errors. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
+     *
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+     * shift' is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     *
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This is a mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     *
+     * This is a mandatory value.
+     */
+    GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     *
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
+     *
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
+     */
+    GnssMultipathIndicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
+     */
+    double snr_db;
+} GnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsData) */
+    size_t size;
+    size_t measurement_count;
+    GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GpsClock clock;
+} GpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gps_measurement_callback) (GpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks;
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsMeasurementCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface;
+
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsNavigationMessage) */
+    size_t size;
+    int8_t prn;
+    GpsNavigationMessageType type;
+    NavigationMessageStatus status;
+    int16_t message_id;
+    int16_t submessage_id;
+    size_t data_length;
+    uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+    /** set to sizeof(GnssNavigationMessage) */
+    size_t size;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a mandatory value.
+     */
+    GnssNavigationMessageType type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    NavigationMessageStatus status;
+
+    /**
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
+     */
+    int16_t message_id;
+
+    /**
+     * Sub-message identifier. If required by the message 'type', this value
+     * contains a sub-index within the current message (or frame) that is being
+     * transmitted.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+     */
+    int16_t submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     *
+     * This is a mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+     *
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
+     */
+    uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+    /** set to sizeof(GpsNavigationMessageCallbacks) */
+    size_t size;
+    gps_navigation_message_callback navigation_message_callback;
+    gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsNavigationMessageInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates as they become
+     * available.
+     *
+     * Status:
+     *      GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+     *      GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+     *              without a corresponding call to 'close'.
+     *      GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+     *              the HAL will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsNavigationMessageInterface;
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+} GnssConfigurationInterface;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/gps_hal/inc/gps_internal.h b/src/connectivity/gps/gps_hal/inc/gps_internal.h
new file mode 100644
index 0000000..0aa335d
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/gps_internal.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+
+#ifdef __ANDROID_OS__
+#include "hardware/gps.h"
+#else
+#include "gps.h"
+#endif
+
+/****************************************************************************
+ * This file contains legacy structs that are deprecated/retired from gps.h *
+ ****************************************************************************/
+
+__BEGIN_DECLS
+
+/**
+ * Legacy GPS callback structure.
+ * Deprecated, to be removed in the next Android release.
+ * Use GpsCallbacks instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsCallbacks_v1) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+} GpsCallbacks_v1;
+
+#pragma pack(push,4)
+// We need to keep the alignment of this data structure to 4-bytes, to ensure that in 64-bit
+// environments the size of this legacy definition does not collide with _v2. Implementations should
+// be using _v2 and _v3, so it's OK to pay the 'unaligned' penalty in 64-bit if an old
+// implementation is still in use.
+
+/**
+ * Legacy struct to represent the status of AGPS.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v1) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+} AGpsStatus_v1;
+
+#pragma pack(pop)
+
+/**
+ * Legacy struct to represent the status of AGPS augmented with a IPv4 address
+ * field.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v2) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+
+    /*-------------------- New fields in _v2 --------------------*/
+
+    uint32_t        ipaddr;
+} AGpsStatus_v2;
+
+/**
+ * Legacy extended interface for AGPS support.
+ * See AGpsInterface_v2 for more information.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface_v1) */
+    size_t          size;
+    void  (*init)( AGpsCallbacks* callbacks );
+    int  (*data_conn_open)( const char* apn );
+    int  (*data_conn_closed)();
+    int  (*data_conn_failed)();
+    int  (*set_server)( AGpsType type, const char* hostname, int port );
+} AGpsInterface_v1;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H */
diff --git a/src/connectivity/gps/gps_hal/inc/gpshal.h b/src/connectivity/gps/gps_hal/inc/gpshal.h
new file mode 100644
index 0000000..0b0f9e2
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/gpshal.h
@@ -0,0 +1,99 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __GPS_HAL_H__
+#define __GPS_HAL_H__
+
+#include "hardware/gps_mtk.h"
+#include <pthread.h>
+
+//=========================================================
+
+#define MAX_EPOLL_EVENT 50
+
+//=========================================================
+
+typedef enum {  // state order is important
+    GPSHAL_STATE_UNKNOWN,
+    GPSHAL_STATE_RESOURCE,
+    GPSHAL_STATE_CLEANUP,
+    GPSHAL_STATE_INIT,    // == STOP
+    GPSHAL_STATE_STOP,    // == INIT
+    GPSHAL_STATE_START
+} gpshal_state;
+
+typedef struct {
+    int       fd_mnl2hal;
+    int       fd_worker_epoll;
+    pthread_t thd_worker;
+
+    pthread_mutex_t mutex_gps_state_intent;
+    gpshal_state    gps_state_intent;  // what we want
+    gpshal_state    gps_state;  // what we are, but we may fail to change it
+
+    GpsCallbacks_ext* gps_cbs;
+    AGpsCallbacks*    agps_cbs;
+    GpsNiCallbacks*   gpsni_cbs;
+    AGpsRilCallbacks* agpsril_cbs;
+    GpsMeasurementCallbacks_ext*       meas_cbs;
+    GpsNavigationMessageCallbacks* navimsg_cbs;
+    GpsGeofenceCallbacks* geofence_cbs;
+    VzwDebugCallbacks* vzw_debug_cbs;
+} gpshal_context_t;
+
+//=========================================================
+
+extern gpshal_context_t g_gpshal_ctx;
+extern const AGpsInterface mtk_agps_inf;
+extern const GpsNiInterface  mtk_gps_ni_inf;
+extern const AGpsRilInterface mtk_agps_ril_inf;
+extern const GpsGeofencingInterface mtkGeofence_inf;
+
+
+//=========================================================
+
+extern const char* gpshal_state_to_string(gpshal_state state);
+
+extern int gpshal_gpscbs_save(GpsCallbacks_ext* src);
+
+extern void gpshal_set_gps_state_intent(gpshal_state newState);
+
+extern void gpshal2mnl_gps_init();
+extern void gpshal2mnl_gps_start();
+extern void gpshal2mnl_gps_stop();
+extern void gpshal2mnl_gps_cleanup();
+
+extern void gpshal_worker_thread(void *arg);
+
+#endif  //  __GPS_HAL_DEBUG_H__
diff --git a/src/connectivity/gps/gps_hal/inc/gpshal_param_check.h b/src/connectivity/gps/gps_hal/inc/gpshal_param_check.h
new file mode 100644
index 0000000..c87ec98
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/gpshal_param_check.h
@@ -0,0 +1,91 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __GPS_HAL_PARAM_CHECK_H__
+#define __GPS_HAL_PARAM_CHECK_H__
+
+#include <string.h>
+
+#if 0 != PARAM_CHECK  // PARAM_CHECK is enabled
+    #define GPS_HW_MODULE_OPEN__CHECK_PARAM \
+        do { \
+            if (&HAL_MODULE_INFO_SYM != module) { \
+                ALOGT("-: Bad module object"); \
+                return -1;  /* Fail: any non-zero value */ \
+            } else if (NULL == id || strcmp(id, HAL_MODULE_INFO_SYM.id)) { \
+                ALOGT("-: Bad id"); \
+                return -2; \
+            } else if (NULL == device) { \
+                ALOGT("-: Bad device"); \
+                return -3; \
+            } \
+        } while (0)
+    #define GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM \
+        do { \
+            if (NULL == device || \
+                    &HAL_MODULE_INFO_SYM != device->common.module || \
+                gps_device__get_gps_interface != device->get_gps_interface) { \
+                ALOGT("-: Bad device object"); \
+                return NULL; \
+            } \
+        } while (0)
+#elif !defined(NDEBUG)  // assert() is effective
+    #define GPS_HW_MODULE_OPEN__CHECK_PARAM \
+        do { \
+            assert(&HAL_MODULE_INFO_SYM == module); \
+            assert(NULL != id); \
+            assert(NULL != device); \
+            assert(0 == strcmp(id, HAL_MODULE_INFO_SYM.id)); \
+        } while (0)
+    #define GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM \
+        do { \
+            assert(NULL != device); \
+            assert(&HAL_MODULE_INFO_SYM == device->common.module); \
+            assert(gps_device__get_gps_interface == device->get_gps_interface); \
+        } while (0)
+#else
+    // PARAM_CHECK is disabled
+    // And assert() is not effective
+    #define GPS_HW_MODULE_OPEN__CHECK_PARAM \
+        do { \
+            UNUSED(module); \
+            UNUSED(id); \
+        } while (0)
+    #define GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM \
+        UNUSED(device)
+#endif
+
+
+#endif  // __GPS_HAL_PARAM_CHECK_H__
\ No newline at end of file
diff --git a/src/connectivity/gps/gps_hal/inc/hal2mnl_interface.h b/src/connectivity/gps/gps_hal/inc/hal2mnl_interface.h
new file mode 100644
index 0000000..77cd331
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/hal2mnl_interface.h
@@ -0,0 +1,87 @@
+#ifndef __HAL2MNL_INTERFACE_H__
+#define __HAL2MNL_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    void (*mnld_reboot)();
+
+    void (*location)(gps_location location);
+    void (*gps_status)(gps_status status);
+    void (*gps_sv)(gnss_sv_info sv);
+    void (*nmea)(int64_t timestamp, const char* nmea, int length);
+    void (*gps_capabilities)(gps_capabilites capabilities);
+    void (*gps_measurements)(gps_data data);
+    void (*gps_navigation)(gps_nav_msg msg);
+    void (*gnss_measurements)(gnss_data data);
+    void (*gnss_navigation)(gnss_nav_msg msg);
+
+    void (*request_wakelock)();
+    void (*release_wakelock)();
+
+    void (*request_utc_time)();
+
+    void (*request_data_conn)(struct sockaddr_storage* addr);
+    void (*release_data_conn)();
+    void (*request_ni_notify)(int session_id, agps_notify_type type, const char* requestor_id,
+        const char* client_name, ni_encoding_type requestor_id_encoding,
+        ni_encoding_type client_name_encoding);
+    void (*request_set_id)(request_setid flags);
+    void (*request_ref_loc)(request_refloc flags);
+    void (*output_vzw_debug)(const char* str);
+    void (*update_gnss_name)(const char* name, int length);
+    void (*request_nlp)(bool independentFromGnss);
+} mnl2hal_interface;
+
+int hal2mnl_hal_reboot();
+
+int hal2mnl_gps_init();
+int hal2mnl_gps_start();
+int hal2mnl_gps_stop();
+int hal2mnl_gps_cleanup();
+
+int hal2mnl_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty);
+int hal2mnl_gps_inject_location(double lat, double lng, float acc);
+int hal2mnl_gps_delete_aiding_data(int flags);
+int hal2mnl_gps_set_position_mode(gps_pos_mode mode, gps_pos_recurrence recurrence,
+    int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode);
+
+int hal2mnl_data_conn_open(const char* apn);
+int hal2mnl_data_conn_open_with_apn_ip_type(const char* apn, apn_ip_type ip_type);
+int hal2mnl_data_conn_closed();
+int hal2mnl_data_conn_failed();
+
+int hal2mnl_set_server(agps_type type, const char* hostname, int port);
+int hal2mnl_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid);
+int hal2mnl_set_id(agps_id_type type, const char* setid);
+
+int hal2mnl_ni_message(char* msg, int len);
+int hal2mnl_ni_respond(int notif_id, ni_user_response_type user_response);
+
+int hal2mnl_update_network_state(int connected, network_type type, int roaming,
+    const char* extra_info);
+int hal2mnl_update_network_availability(int available, const char* apn);
+
+int hal2mnl_set_gps_measurement(bool enabled, bool enableFullTracking);
+int hal2mnl_set_gps_navigation(bool enabled);
+
+int hal2mnl_set_vzw_debug(bool enabled);
+int hal2mnl_update_gnss_config(const char* config_data, int length);
+int hal2mnl_setBlacklist(long long* blacklist, int32_t size);
+
+// -1 means failure
+int mnl2hal_hdlr(int fd, mnl2hal_interface* hdlr);
+
+// -1 means failure
+int create_mnl2hal_fd();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/gps_hal/inc/hal_mnl_interface_common.h b/src/connectivity/gps/gps_hal/inc/hal_mnl_interface_common.h
new file mode 100644
index 0000000..ab01a3a
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/hal_mnl_interface_common.h
@@ -0,0 +1,1353 @@
+#ifndef __HAL_MNL_INTERFACE_COMMON_H__
+#define __HAL_MNL_INTERFACE_COMMON_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HAL_MNL_BUFF_SIZE           (16 * 1024)
+#define HAL_MNL_INTERFACE_VERSION   1
+
+//======================================================
+// GPS HAL -> MNLD
+//======================================================
+#define MTK_HAL2MNL "mtk_hal2mnl"
+
+typedef enum {
+    HAL2MNL_HAL_REBOOT                      = 0,
+    HAL2MNL_GPS_INIT                        = 101,
+    HAL2MNL_GPS_START                       = 102,
+    HAL2MNL_GPS_STOP                        = 103,
+    HAL2MNL_GPS_CLEANUP                     = 104,
+    HAL2MNL_GPS_INJECT_TIME                 = 105,
+    HAL2MNL_GPS_INJECT_LOCATION             = 106,
+    HAL2MNL_GPS_DELETE_AIDING_DATA          = 107,
+    HAL2MNL_GPS_SET_POSITION_MODE           = 108,
+    HAL2MNL_DATA_CONN_OPEN                  = 201,
+    HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE = 202,
+    HAL2MNL_DATA_CONN_CLOSED                = 203,
+    HAL2MNL_DATA_CONN_FAILED                = 204,
+    HAL2MNL_SET_SERVER                      = 301,
+    HAL2MNL_SET_REF_LOCATION                = 302,
+    HAL2MNL_SET_ID                          = 303,
+    HAL2MNL_NI_MESSAGE                      = 401,
+    HAL2MNL_NI_RESPOND                      = 402,
+    HAL2MNL_UPDATE_NETWORK_STATE            = 501,
+    HAL2MNL_UPDATE_NETWORK_AVAILABILITY     = 502,
+    HAL2MNL_GPS_MEASUREMENT                 = 601,
+    HAL2MNL_GPS_NAVIGATION                  = 602,
+    HAL2MNL_VZW_DEBUG                       = 603,
+    HAL2MNL_GNSS_CONFIG                     = 604,
+    //HAL2MNL_SV_BLACKLIST                    = 605,
+    HAL2MNL_SEND_PMTK                       = 701,
+} hal2mnl_cmd;
+
+typedef int gps_pos_mode;
+#define GPS_POS_MODE_STANDALONE     0
+#define GPS_POS_MODE_MSB            1
+
+typedef int gps_pos_recurrence;
+#define GPS_POS_RECURRENCE_PERIODIC     0
+#define GPS_POS_RECURRENCE_SINGLE       1
+
+typedef int ni_user_response_type;
+#define NI_USER_RESPONSE_ACCEPT     1
+#define NI_USER_RESPONSE_DENY       2
+#define NI_USER_RESPONSE_NORESP     3
+
+typedef int cell_type;
+#define CELL_TYPE_GSM       1
+#define CELL_TYPE_UMTS      2
+
+typedef int agps_id_type;
+#define AGPS_ID_TYPE_NONE       0
+#define AGPS_ID_TYPE_IMSI       1
+#define AGPS_ID_TYPE_MSISDN     2
+
+typedef int network_type;
+#define NETWORK_TYPE_MOBILE         0
+#define NETWORK_TYPE_WIFI           1
+#define NETWORK_TYPE_MOBILE_MMS     2
+#define NETWORK_TYPE_MOBILE_SUPL    3
+#define NETWORK_TYPE_MOBILE_DUN     4
+#define NETWORK_TYPE_MOBILE_HIPRI   5
+#define NETWORK_TYPE_WIMAX          6
+
+typedef int apn_ip_type;
+#define MTK_APN_IP_INVALID          0
+#define MTK_APN_IP_IPV4             1
+#define MTK_APN_IP_IPV6             2
+#define MTK_APN_IP_IPV4V6           3
+
+typedef int agps_type;
+#define MTK_AGPS_TYPE_SUPL          1
+#define MTK_AGPS_TYPE_C2K           2
+
+//======================================================
+// MNLD -> GPS HAL
+//======================================================
+#define MTK_MNL2HAL "mtk_mnl2hal"
+
+typedef enum {
+    MNL2HAL_MNLD_REBOOT             = 1,
+    MNL2HAL_LOCATION                = 101,
+    MNL2HAL_GPS_STATUS              = 102,
+    MNL2HAL_GPS_SV                  = 103,
+    MNL2HAL_NMEA                    = 104,
+    MNL2HAL_GPS_CAPABILITIES        = 105,
+    MNL2HAL_GPS_MEASUREMENTS        = 106,
+    MNL2HAL_GPS_NAVIGATION          = 107,
+    MNL2HAL_GNSS_MEASUREMENTS       = 108,
+    MNL2HAL_GNSS_NAVIGATION         = 109,
+    MNL2HAL_REQUEST_WAKELOCK        = 201,
+    MNL2HAL_RELEASE_WAKELOCK        = 202,
+    MNL2HAL_REQUEST_UTC_TIME        = 301,
+    MNL2HAL_REQUEST_DATA_CONN       = 302,
+    MNL2HAL_RELEASE_DATA_CONN       = 303,
+    MNL2HAL_REQUEST_NI_NOTIFY       = 304,
+    MNL2HAL_REQUEST_SET_ID          = 305,
+    MNL2HAL_REQUEST_REF_LOC         = 306,
+    MNL2HAL_VZW_DEBUG_OUTPUT        = 307,
+    MNL2HAL_UPDATE_GNSS_NAME        = 308,
+    MNL2HAL_REQUEST_NLP             = 309,
+} mnl2hal_cmd;
+
+#define MTK_HAL_GNSS_MAX_SVS            64
+#define GPS_MAX_MEASUREMENT     32
+#define MTK_HAL_GNSS_MAX_MEASUREMENT    64
+
+typedef int gps_location_flags;
+#define MTK_GPS_LOCATION_HAS_LAT_LONG   0x0001
+#define MTK_GPS_LOCATION_HAS_ALT        0x0002
+#define MTK_GPS_LOCATION_HAS_SPEED      0x0004
+#define MTK_GPS_LOCATION_HAS_BEARING    0x0008
+#define MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY    0x0010
+#define MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY      0x0020
+#define MTK_GPS_LOCATION_HAS_SPEED_ACCURACY         0x0040
+#define MTK_GPS_LOCATION_HAS_BEARING_ACCURACY       0x0080
+
+typedef int gps_capabilites;
+#define GPS_CAP_NONE             0x0010000
+#define GPS_CAP_SCHEDULING       0x0000001
+#define GPS_CAP_MSB              0x0000002
+#define GPS_CAP_MSA              0x0000004
+#define GPS_CAP_SINGLE_SHOT      0x0000008
+#define GPS_CAP_ON_DEMAND_TIME   0x0000010
+#define GPS_CAP_GEOFENCING       0x0000020
+#define GPS_CAP_MEASUREMENTS     0x0000040
+#define GPS_CAP_NAV_MESSAGES     0x0000080
+
+typedef int request_setid;
+#define REQUEST_SETID_IMSI     (1<<0L)
+#define REQUEST_SETID_MSISDN   (1<<1L)
+
+typedef int request_refloc;
+#define REQUEST_REFLOC_CELLID  (1<<0L)
+#define REQUEST_REFLOC_MAC     (1<<1L)   // not ready
+
+typedef short gps_clock_flags;
+#define GPS_CLK_HAS_LEAP_SECOND               (1<<0)
+#define GPS_CLK_HAS_TIME_UNCERTAINTY          (1<<1)
+#define GPS_CLK_HAS_FULL_BIAS                 (1<<2)
+#define GPS_CLK_HAS_BIAS                      (1<<3)
+#define GPS_CLK_HAS_BIAS_UNCERTAINTY          (1<<4)
+#define GPS_CLK_HAS_DRIFT                     (1<<5)
+#define GPS_CLK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+typedef char gps_clock_type;
+#define GPS_CLOCK_TYPE_UNKNOWN                  0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME            1
+#define GPS_CLOCK_TYPE_GPS_TIME                 2
+
+typedef int gps_measurement_flags;
+#define GPS_MEASUREMENT_HAS_SNR                               (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION                         (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY             (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH                           (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY               (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE                       (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY           (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE                        (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY            (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER                        (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT                (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                     (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY         (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX                       (1<<17)
+
+typedef short gps_measurement_state;
+#define GPS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+
+typedef short gps_accumulated_delta_range_state;
+#define GPS_ADR_STATE_UNKNOWN                       0
+#define GPS_ADR_STATE_VALID                     (1<<0)
+#define GPS_ADR_STATE_RESET                     (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+typedef char gps_loss_of_lock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN                            0
+#define GPS_LOSS_OF_LOCK_OK                                 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP                         2
+
+typedef char gps_multipath_indicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN                 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED                1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED                2
+
+typedef char gps_nav_msg_type;
+#define GPS_NAV_MSG_TYPE_UNKNOWN         0
+#define GPS_NAV_MSG_TYPE_L1CA            1
+#define GPS_NAV_MSG_TYPE_L2CNAV          2
+#define GPS_NAV_MSG_TYPE_L5CNAV          3
+#define GPS_NAV_MSG_TYPE_CNAV2           4
+
+typedef short nav_msg_status;
+#define NAV_MSG_STATUS_UNKONW              0
+#define NAV_MSG_STATUS_PARITY_PASSED   (1<<0)
+#define NAV_MSG_STATUS_PARITY_REBUILT  (1<<1)
+
+typedef int gps_status;
+#define MTK_GPS_STATUS_SESSION_BEGIN        1
+#define MTK_GPS_STATUS_SESSION_END          2
+#define MTK_GPS_STATUS_SESSION_ENGINE_ON    3
+#define MTK_GPS_STATUS_SESSION_ENGINE_OFF   4
+
+typedef int agps_ni_type;
+#define AGPS_NI_TYPE_VOICE              1
+#define AGPS_NI_TYPE_UMTS_SUPL          2
+#define AGPS_NI_TYPE_UMTS_CTRL_PLANE    3
+#define AGPS_NI_TYPE_EMERGENCY_SUPL     4
+
+typedef int agps_notify_type;
+#define AGPS_NOTIFY_TYPE_NONE                       0
+#define AGPS_NOTIFY_TYPE_NOTIFY_ONLY                1
+#define AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER     2
+#define AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER      3
+#define AGPS_NOTIFY_TYPE_PRIVACY                    4
+
+typedef int ni_encoding_type;
+#define NI_ENCODING_TYPE_NONE   0
+#define NI_ENCODING_TYPE_GSM7   1
+#define NI_ENCODING_TYPE_UTF8   2
+#define NI_ENCODING_TYPE_UCS2   3
+
+typedef struct {
+    gps_location_flags flags;
+    double lat;
+    double lng;
+    double alt;
+    float speed;
+    float bearing;
+    float h_accuracy;  //horizontal
+    float v_accuracy;  //vertical
+    float s_accuracy;  //spedd
+    float b_accuracy;  //bearing
+    int64_t timestamp;
+} gps_location;
+
+typedef struct {
+    int16_t   svid;
+    uint8_t   constellation;
+    float     c_n0_dbhz;
+    float     elevation;
+    float     azimuth;
+    uint8_t   flags;
+    float     carrier_frequency;
+} gnss_sv;
+
+typedef struct {
+    int  num_svs;
+    gnss_sv  sv_list[MTK_HAL_GNSS_MAX_SVS];
+} gnss_sv_info;
+
+typedef struct {
+    int prn;
+    bool has_ephemeris_data;
+    bool has_almanac_data;
+    bool used_in_fix;
+} NmeaCash;
+
+typedef uint16_t MTK_HAL_NavigationMessageStatus;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN              0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+typedef int16_t MTK_HAL_GnssNavigationMessageType;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+typedef uint8_t MTK_HAL_GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+typedef uint16_t MTK_HAL_GnssAccumulatedDeltaRangeState;
+#define MTK_GNSS_ADR_STATE_UNKNOWN                       0
+#define MTK_GNSS_ADR_STATE_VALID                     (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET                     (1<<1)
+#define MTK_GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+typedef uint32_t MTK_HAL_GnssMeasurementState;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define MTK_GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+typedef uint8_t  MTK_HAL_GnssConstellationType;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN      0
+#define MTK_GNSS_CONSTELLATION_GPS          1
+#define MTK_GNSS_CONSTELLATION_SBAS         2
+#define MTK_GNSS_CONSTELLATION_GLONASS      3
+#define MTK_GNSS_CONSTELLATION_QZSS         4
+#define MTK_GNSS_CONSTELLATION_BEIDOU       5
+#define MTK_GNSS_CONSTELLATION_GALILEO      6
+
+typedef uint32_t MTK_HAL_GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+typedef uint16_t MTK_HAL_GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+typedef struct {
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    gps_clock_flags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_LEAP_SECOND.
+     */
+    short leap_second;
+
+    /**
+     * Indicates the type of time reported by the 'time_ns' field.
+     */
+    gps_clock_type type;
+
+    /**
+     * The GPS receiver internal clock value. This can be either the local hardware clock value
+     * (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+     * (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+     *
+     * For local hardware clock, this value is expected to be monotonically increasing during
+     * the reporting session. The real GPS time can be derived by compensating the 'full bias'
+     * (when it is available) from this value.
+     *
+     * For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+     * receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+     * The value contains the 'time uncertainty' in it.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_TIME_UNCERTAINTY.
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver and the true GPS
+     * time since 0000Z, January 6, 1980, in nanoseconds.
+     * This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+     * has solved the clock for GPS time.
+     * The caller is responsible for using the 'bias uncertainty' field for quality check.
+     *
+     * The sign of the value is defined by the following equation:
+     *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+     *
+     * This value contains the 'bias uncertainty' in it.
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_FULL_BIAS.
+
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The value contains the 'bias uncertainty' in it.
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS_UNCERTAINTY.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     * A positive value means that the frequency is higher than the nominal frequency.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT.
+     *
+     * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+     * it is encouraged that this field is also provided.
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT_UNCERTAINTY.
+     */
+    double drift_uncertainty_nsps;
+} gps_clock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    MTK_HAL_GnssClockFlags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+     *      1,000,000,000
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+     */
+    int16_t leap_second;
+
+    /**
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
+     *
+     * For local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * available) from this value.
+     *
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+     * The value contains the 'time uncertainty' in it.
+     *
+     * This field is mandatory.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * The sign of the value is defined by the following equation:
+     *      local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+     *
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * bias) in nanoseconds. The uncertainty is represented as an absolute
+     * (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+     *
+     * This value is mandatory if the receiver has estimated GNSS time
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
+     */
+    double drift_uncertainty_nsps;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+} gnss_clock;
+
+typedef struct {
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    gps_measurement_flags flags;
+
+    /**
+     * Pseudo-random number in the range of [1, 32]
+     * This is a Mandatory value.
+     */
+    int8_t prn;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a Mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     * This is a Mandatory value.
+     */
+    gps_measurement_state state;
+
+    /**
+     * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     * The value is relative to the beginning of the current GPS week.
+     *
+     * Given the highest sync state that can be achieved, per each satellite, valid range for
+     * this field can be:
+     *     Searching       : [ 0       ]   : GPS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * However, if there is any ambiguity in integer millisecond,
+     * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_gps_tow_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_gps_tow_uncertainty_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna input.
+     * This is a Mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s.
+     * The value also includes the effects of the receiver clock frequency and satellite clock
+     * frequency errors.
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive value indicates that the pseudorange is getting larger.
+     * This is a Mandatory value.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudurange rate in m/s.
+     * The uncertainty is represented as an absolute (single sided) value.
+     * This is a Mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     * This is a Mandatory value.
+     */
+    gps_accumulated_delta_range_state accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * The data is available if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Best derived Pseudorange by the chip-set, in meters.
+     * The value contains the 'pseudorange uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE.
+     */
+    double pseudorange_m;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange in meters.
+     * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY.
+     */
+    double pseudorange_uncertainty_m;
+
+    /**
+     * A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+     * This value contains the time (in Chip units) since the last C/A code cycle (GPS Msec epoch).
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'code-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE.
+     */
+    double code_phase_chips;
+
+    /**
+     * 1-Sigma uncertainty of the code-phase, in a fraction of chips.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY.
+     */
+    double code_phase_uncertainty_chips;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'loss of lock' state of the event.
+     */
+    gps_loss_of_lock loss_of_lock;
+
+    /**
+     * The number of GPS bits transmitted since Sat-Sun midnight (GPS week).
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_BIT_NUMBER.
+     */
+    int32_t bit_number;
+
+    /**
+     * The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT.
+     */
+    int16_t time_from_last_bit_ms;
+
+    /**
+     * Doppler shift in Hz.
+     * A positive value indicates that the SV is moving toward the receiver.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'doppler shift uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT.
+     */
+    double doppler_shift_hz;
+
+    /**
+     * 1-Sigma uncertainty of the doppler shift in Hz.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY.
+     */
+    double doppler_shift_uncertainty_hz;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     */
+    gps_multipath_indicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio in dB.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR.
+     */
+    double snr_db;
+
+    /**
+     * Elevation in degrees, the valid range is [-90, 90].
+     * The value contains the 'elevation uncertainty' in it.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION.
+     */
+    double elevation_deg;
+
+    /**
+     * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+     * The uncertainty is represented as the absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY.
+     */
+    double elevation_uncertainty_deg;
+
+    /**
+     * Azimuth in degrees, in the range [0, 360).
+     * The value contains the 'azimuth uncertainty' in it.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH.
+     *  */
+    double azimuth_deg;
+
+    /**
+     * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY.
+     */
+    double azimuth_uncertainty_deg;
+
+    /**
+     * Whether the GPS represented by the measurement was used for computing the most recent fix.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_USED_IN_FIX.
+     */
+    bool used_in_fix;
+} gps_measurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    MTK_HAL_GnssMeasurementFlags flags;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    MTK_HAL_GnssConstellationType constellation;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     *
+     * This is a mandatory value.
+     */
+    MTK_HAL_GnssMeasurementState state;
+
+    /**
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
+     *
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     *
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_sv_time_uncertainty_in_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s. The correction of a given
+     * Pseudorange Rate value includes corrections for receiver and satellite
+     * clock frequency errors. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
+     *
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+     * shift' is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     *
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This is a mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     *
+     * This is a mandatory value.
+     */
+    MTK_HAL_GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     *
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
+     *
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
+     */
+    MTK_HAL_GnssMultipathIndicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
+     */
+    double snr_db;
+
+    /**
+       * Automatic gain control (AGC) level. AGC acts as a variable gain
+       * amplifier adjusting the power of the incoming signal. The AGC level
+       * may be used to indicate potential interference. When AGC is at a
+       * nominal level, this value must be set as 0. Higher gain (and/or lower
+       * input power) must be output as a positive number. Hence in cases of
+       * strong jamming, in the band of this signal, this value must go more
+       * negative.
+       */
+    double agc_level_db;
+} gnss_measurement;
+
+typedef struct {
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    gps_measurement measurements[GPS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    gps_clock clock;
+} gps_data;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    gnss_measurement measurements[MTK_HAL_GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    gnss_clock clock;
+} gnss_data;
+
+typedef struct {
+    /**
+     * Pseudo-random number in the range of [1, 32]
+     * This is a Mandatory value.
+     */
+    int8_t prn;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a Mandatory value.
+     */
+    gps_nav_msg_type type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    nav_msg_status status;
+
+    /**
+     * Message identifier.
+     * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+     * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+     * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+     */
+    short message_id;
+
+    /**
+     * Sub-message identifier.
+     * If required by the message 'type', this value contains a sub-index within the current
+     * message (or frame) that is being transmitted.
+     * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+     */
+    short submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     * This is a Mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message.
+     * The bytes (or words) specified using big endian format (MSB first).
+     *
+     * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+     * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
+     */
+    char data[40];
+} gps_nav_msg;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+    /** set to sizeof(GnssNavigationMessage) */
+    size_t size;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a mandatory value.
+     */
+    MTK_HAL_GnssNavigationMessageType type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    MTK_HAL_NavigationMessageStatus status;
+
+    /**
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
+     */
+    int16_t message_id;
+
+    /**
+     * Sub-message identifier. If required by the message 'type', this value
+     * contains a sub-index within the current message (or frame) that is being
+     * transmitted.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+     */
+    int16_t submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     *
+     * This is a mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+     *
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
+     */
+    uint8_t* data;
+} gnss_nav_msg;
+
+#if 0
+void dump_gps_location(gps_location in);
+void dump_gnss_sv(gnss_sv in);
+void dump_gnss_sv_info(gnss_sv_info in);
+void dump_gps_data(gps_data in);
+void dump_gps_measurement(gps_measurement in);
+void dump_gps_clock(gps_clock in);
+void dump_gps_nav_msg(gps_nav_msg in);
+void dump_gnss_data(gnss_data in);
+void dump_gnss_measurement(gnss_measurement in);
+void dump_gnss_clock(gnss_clock in);
+void dump_gnss_nav_msg(gnss_nav_msg in);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/gps_hal/inc/hardware/gps_mtk.h b/src/connectivity/gps/gps_hal/inc/hardware/gps_mtk.h
new file mode 100644
index 0000000..df13674
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/hardware/gps_mtk.h
@@ -0,0 +1,698 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+
+#if defined (__ANDROID_OS__)
+#include <hardware/gps_internal.h>
+#elif defined (__LINUX_OS__)
+#include "gps_internal.h"
+#endif
+
+__BEGIN_DECLS
+
+// MTK extended GpsAidingData values.
+#define GPS_DELETE_HOT_STILL 0x2000
+#define GPS_DELETE_EPO      0x4000
+
+// ====================vzw debug screen API =================
+/**
+ * Name for the VZW debug interface.
+ */
+#define VZW_DEBUG_INTERFACE      "vzw-debug"
+
+#define VZW_DEBUG_STRING_MAXLEN      200
+
+/** Represents data of VzwDebugData. */
+typedef struct {
+    /** set to sizeof(VzwDebugData) */
+    size_t size;
+
+    char  vzw_msg_data[VZW_DEBUG_STRING_MAXLEN];
+} VzwDebugData;
+
+
+typedef void (* vzw_debug_callback)(VzwDebugData* vzw_message);
+
+/** Callback structure for the Vzw debug interface. */
+typedef struct {
+    vzw_debug_callback vzw_debug_cb;
+} VzwDebugCallbacks;
+
+
+/** Extended interface for VZW DEBUG support. */
+typedef struct {
+    /** set to sizeof(VzwDebugInterface) */
+    size_t          size;
+
+    /** Registers the callbacks for Vzw debug message. */
+    int  (*init)( VzwDebugCallbacks* callbacks );
+
+    /** Set Vzw debug screen enable/disable **/
+    void (*set_vzw_debug_screen)(bool enabled);
+} VzwDebugInterface;
+
+////////////////////// GNSS HIDL v1.0 ////////////////////////////
+
+/** Represents a location. */
+typedef struct {
+    GpsLocation legacyLocation;
+    /**
+    * Represents expected horizontal position accuracy, radial, in meters
+    * (68% confidence).
+    */
+    float           horizontalAccuracyMeters;
+
+    /**
+    * Represents expected vertical position accuracy in meters
+    * (68% confidence).
+    */
+    float           verticalAccuracyMeters;
+
+    /**
+    * Represents expected speed accuracy in meter per seconds
+    * (68% confidence).
+    */
+    float           speedAccuracyMetersPerSecond;
+
+    /**
+    * Represents expected bearing accuracy in degrees
+    * (68% confidence).
+    */
+    float           bearingAccuracyDegrees;
+
+} GpsLocation_ext;
+
+
+typedef struct {
+    GnssSvInfo legacySvInfo;
+
+    /// v1.0 ///
+    float carrier_frequency;
+
+} GnssSvInfo_ext;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo_ext gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus_ext;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_ext_callback)(GpsLocation_ext* location);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_ext_callback)(GnssSvStatus_ext* sv_info);
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_ext_callback) (int32_t geofence_id,
+        GpsLocation_ext* location, int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_ext_callback) (int32_t status,
+        GpsLocation_ext* last_location);
+
+typedef struct {
+    gps_geofence_transition_ext_callback geofence_transition_callback;
+    gps_geofence_status_ext_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks_ext;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks_ext* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface_ext;
+
+typedef struct {
+    GnssMeasurement legacyMeasurement;
+
+    /**
+     * Automatic gain control (AGC) level. AGC acts as a variable gain
+     * amplifier adjusting the power of the incoming signal. The AGC level
+     * may be used to indicate potential interference. When AGC is at a
+     * nominal level, this value must be set as 0. Higher gain (and/or lower
+     * input power) must be output as a positive number. Hence in cases of
+     * strong jamming, in the band of this signal, this value must go more
+     * negative.
+     *
+     * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+     * other RF HW components) may also affect the typical output of of this
+     * value on any given hardware design in an open sky test - the
+     * important aspect of this output is that changes in this value are
+     * indicative of changes on input signal power in the frequency band for
+     * this measurement.
+     */
+    double agc_level_db;
+} GnssMeasurement_ext;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement_ext measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData_ext;
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_ext_callback) (GnssData_ext* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_ext_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks_ext;
+
+
+/////// Gnss debug ////
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+typedef enum {
+    /** Ephemeris is known for this satellite. */
+    EPHEMERIS,
+    /**
+     * Ephemeris is not known, but Almanac (approximate location) is known.
+     */
+    ALMANAC_ONLY,
+    /**
+     * Both ephemeris & almanac are not known (e.g. during a cold start
+     * blind search.)
+     */
+    NOT_AVAILABLE
+} SatelliteEphemerisType;
+
+typedef enum {
+    /**
+     * The ephemeris (or almanac only) information was demodulated from the
+     * signal received on the device
+     */
+    DEMODULATED,
+    /**
+     * The ephemeris (or almanac only) information was received from a SUPL
+     * server.
+     */
+    SUPL_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * server.
+     */
+    OTHER_SERVER_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * method, e.g. injected via a local debug tool, from build defaults
+     * (e.g. almanac), or is from a satellite
+     * with SatelliteEphemerisType::NOT_AVAILABLE.
+     */
+    OTHER
+} SatelliteEphemerisSource;
+
+typedef enum {
+    /** The ephemeris is known good. */
+    GOOD,
+    /** The ephemeris is known bad. */
+    BAD,
+    /** The ephemeris is unknown to be good or bad. */
+    UNKNOWN
+} SatelliteEphemerisHealth;
+
+/**
+ * Provides the current best known position from any
+ * source (GNSS or injected assistance).
+ */
+typedef struct {
+    /**
+     * Validity of the data in this struct. False only if no
+     * latitude/longitude information is known.
+     */
+    bool valid;
+    /** Latitude expressed in degrees */
+    double latitudeDegrees;
+    /** Longitude expressed in degrees */
+    double longitudeDegrees;
+    /** Altitude above ellipsoid expressed in meters */
+    float altitudeMeters;
+    /** Represents horizontal speed in meters per second. */
+    float speedMetersPerSec;
+    /** Represents heading in degrees. */
+    float bearingDegrees;
+    /**
+     * Estimated horizontal accuracy of position expressed in meters,
+     * radial, 68% confidence.
+     */
+    double horizontalAccuracyMeters;
+    /**
+     * Estimated vertical accuracy of position expressed in meters, with
+     * 68% confidence.
+     */
+    double verticalAccuracyMeters;
+    /**
+     * Estimated speed accuracy in meters per second with 68% confidence.
+     */
+    double speedAccuracyMetersPerSecond;
+    /**
+     * estimated bearing accuracy degrees with 68% confidence.
+     */
+    double bearingAccuracyDegrees;
+    /**
+     * Time duration before this report that this position information was
+     * valid.  This can, for example, be a previous injected location with
+     * an age potentially thousands of seconds old, or
+     * extrapolated to the current time (with appropriately increased
+     * accuracy estimates), with a (near) zero age.
+     */
+    float ageSeconds;
+} PositionDebug;
+
+/**
+ * Provides the current best known UTC time estimate.
+ * If no fresh information is available, e.g. after a delete all,
+ * then whatever the effective defaults are on the device must be
+ * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+ * in the specified units.
+ */
+typedef struct {
+    /** UTC time estimate. */
+    GnssUtcTime timeEstimate;
+    /** 68% error estimate in time. */
+    float timeUncertaintyNs;
+    /**
+     * 68% error estimate in local clock drift,
+     * in nanoseconds per second (also known as parts per billion - ppb.)
+     */
+    float frequencyUncertaintyNsPerSec;
+} TimeDebug;
+
+/**
+ * Provides a single satellite info that has decoded navigation data.
+ */
+typedef struct {
+    /** Satellite vehicle ID number */
+    int16_t svid;
+    /** Defines the constellation type of the given SV. */
+    GnssConstellationType constellation;
+
+    /**
+     * Defines the standard broadcast ephemeris or almanac availability for
+     * the satellite.  To report status of predicted orbit and clock
+     * information, see the serverPrediction fields below.
+     */
+    SatelliteEphemerisType ephemerisType;
+    /** Defines the ephemeris source of the satellite. */
+    SatelliteEphemerisSource ephemerisSource;
+    /**
+     * Defines whether the satellite is known healthy
+     * (safe for use in location calculation.)
+     */
+    SatelliteEphemerisHealth ephemerisHealth;
+    /**
+     * Time duration from this report (current time), minus the
+     * effective time of the ephemeris source (e.g. TOE, TOA.)
+     * Set to 0 when ephemerisType is NOT_AVAILABLE.
+     */
+    float ephemerisAgeSeconds;
+
+    /**
+     * True if a server has provided a predicted orbit and clock model for
+     * this satellite.
+     */
+    bool serverPredictionIsAvailable;
+    /**
+     * Time duration from this report (current time) minus the time of the
+     * start of the server predicted information.  For example, a 1 day
+     * old prediction would be reported as 86400 seconds here.
+     */
+    float serverPredictionAgeSeconds;
+} SatelliteData;
+
+/**
+ * Provides a set of debug information that is filled by the GNSS chipset
+ * when the method getDebugData() is invoked.
+ */
+typedef struct {
+    /** Current best known position. */
+    PositionDebug position;
+    /** Current best know time estimate */
+    TimeDebug time;
+    /**
+     * Provides a list of the available satellite data, for all
+     * satellites and constellations the device can track,
+     * including GnssConstellationType UNKNOWN.
+     */
+    SatelliteData satelliteDataArray[GNSS_MAX_SVS];
+} DebugData;
+
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    // size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+    /// v1.0 ///
+    bool (*get_internal_state)(DebugData* debugData);
+} GpsDebugInterface_ext;
+
+
+////////////////////// GNSS HIDL v1.1 ////////////////////////////
+
+/**
+ * Callback for reporting driver name information.
+ */
+typedef void (* gnss_set_name_callback)(const char* name, int length);
+
+/**
+ * Callback for requesting framework NLP or Fused location injection.
+ */
+typedef void (* gnss_request_location_callback)(bool independentFromGnss);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_ext_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_ext_callback gnss_sv_status_cb;
+
+    /////v1.1////
+    gnss_set_name_callback set_name_cb;
+    gnss_request_location_callback request_location_cb;
+} GpsCallbacks_ext;
+
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    /// v1.0 ///
+//    int   (*init)( GpsCallbacks* callbacks );
+    /// v1.1 ///
+    int   (*init)( GpsCallbacks_ext* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+     /// v1.0 ///
+//    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+//            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+    /// v1.1 ///
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time,
+            bool lowPowerMode);
+
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+
+    /// v1.1 ///
+    int  (*inject_fused_location)(double latitude, double longitude, float accuracy);
+
+} GpsInterface_ext;
+
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface_ext) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    /// v1.0 ///
+//    int (*init) (GpsMeasurementCallbacks* callbacks);
+    /// v1.1 ///
+    int (*init) (GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface_ext;
+
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+
+   //// v1.1 ////
+   void (*setBlacklist) (long long* blacklist, int32_t size);
+} GnssConfigurationInterface_ext;
+
+
+#if defined (__ANDROID_OS__)
+struct gps_device_t_ext {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#elif defined (__LINUX_OS__)
+struct gps_device_t_ext {
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#endif
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_MTK_H */
+
diff --git a/src/connectivity/gps/gps_hal/inc/mtk_auto_log.h b/src/connectivity/gps/gps_hal/inc/mtk_auto_log.h
new file mode 100644
index 0000000..edf1775
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/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_hal"
+#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/gps_hal/inc/mtk_lbs_utility.h b/src/connectivity/gps/gps_hal/inc/mtk_lbs_utility.h
new file mode 100644
index 0000000..3d8fafd
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/inc/mtk_lbs_utility.h
@@ -0,0 +1,87 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+//#include "mtk_auto_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#define  MTK_GPS_NVRAM  0
+
+#if defined(__ANDROID_OS__)
+#define  ANDROID_MNLD_PROP_SUPPORT 1
+#elif defined(__LINUX_OS__)
+#define  ANDROID_MNLD_PROP_SUPPORT 0
+#endif
+
+void msleep(int interval);
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+/*************************************************
+* Timer
+**************************************************/
+typedef void (* timer_callback)();
+
+
+// in millisecond
+time_t get_tick();
+
+// in millisecond
+time_t get_time_in_millisecond();
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd);
+
+// -1 failed
+int epoll_add_fd2(int epfd, int fd, uint32_t events);
+
+// -1 failed
+int epoll_del_fd(int epfd, int fd);
+
+int epoll_mod_fd(int epfd, int fd, uint32_t events);
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_bind_udp(const char* path);
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking);
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len);
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len);
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds);
+
+// -1 means failure
+int stop_timer(timer_t timerid);
+
+// -1 means failure
+timer_t init_timer(timer_callback cb);
+
+// -1 means failure
+int deinit_timer(timer_t timerid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/gps_hal/src/agpsinf.c b/src/connectivity/gps/gps_hal/src/agpsinf.c
new file mode 100644
index 0000000..c1ba646
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/agpsinf.c
@@ -0,0 +1,181 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <string.h>
+
+#include "gpshal.h"
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "agpsinf"
+#endif
+
+//=========================================================
+// Agps Interface
+#ifndef __unused
+#define __unused
+#endif
+
+static void agpsinf_init(AGpsCallbacks* callbacks) {
+    g_gpshal_ctx.agps_cbs = callbacks;
+}
+
+static int agpsinf_set_server(AGpsType type, const char* hostname, int port) {
+    hal2mnl_set_server(type, hostname, port);
+    return 0;  // 0:ok,   non-zero: error; but GPS JNI will ignore it
+}
+
+static int agpsinf_data_conn_open_with_apn_ip_type(
+        const char* apn,
+        ApnIpType apnIpType) {
+    hal2mnl_data_conn_open_with_apn_ip_type(apn, apnIpType);
+    return 0;  // 0:ok,   non-zero: error; but GPS JNI will ignore it
+}
+
+const AGpsInterface mtk_agps_inf = {
+    sizeof(AGpsInterface),
+    agpsinf_init,
+    hal2mnl_data_conn_open,    // GPS JNI will ignore its ret value
+    hal2mnl_data_conn_closed,  // GPS JNI will ignore its ret value
+    hal2mnl_data_conn_failed,  // GPS JNI will ignore its ret value
+    agpsinf_set_server,
+    agpsinf_data_conn_open_with_apn_ip_type
+};
+
+
+//=========================================================
+// Gps Ni Interface
+
+static void gpsni_init(GpsNiCallbacks *callbacks) {
+    g_gpshal_ctx.gpsni_cbs = callbacks;
+}
+
+static void gpsni_respond(int notif_id, GpsUserResponseType user_response) {
+    hal2mnl_ni_respond(notif_id, user_response);
+}
+
+const GpsNiInterface  mtk_gps_ni_inf = {
+    sizeof(GpsNiInterface),
+    gpsni_init,
+    gpsni_respond
+};
+
+
+//=========================================================
+// Agps Ril Interface
+
+static void agps_ril_init(AGpsRilCallbacks* callbacks) {
+    g_gpshal_ctx.agpsril_cbs = callbacks;
+}
+
+static void agps_ril_set_ref_location(
+        const AGpsRefLocation *agps_reflocation,
+        __unused size_t sz_struct) {
+    // UNUSED(sz_struct);
+    uint16_t type = agps_reflocation->type;
+    switch (type) {
+        case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
+        case AGPS_REF_LOCATION_TYPE_UMTS_CELLID: {
+            const AGpsRefLocationCellID cell = agps_reflocation->u.cellID;
+            hal2mnl_set_ref_location(
+                     type, cell.mcc, cell.mnc, cell.lac, cell.cid);
+            break;
+        }
+        // case AGPS_REG_LOCATION_TYPE_MAC:
+            // TODO: to support MAC when GPS JNI can support it
+            // break;
+        default:
+            LOGW("%s: unsupported ref loc type: %d", __func__, type);
+    }
+}
+
+static void agps_ril_set_set_id(AGpsSetIDType type, const char* setid) {
+    hal2mnl_set_id(type, setid);
+}
+
+static void agps_ril_ni_message(uint8_t *msg, size_t len) {
+    hal2mnl_ni_message((char*)msg, len);
+}
+
+static void agps_ril_update_network_state(int connected, int type, int roaming, const char* extra_info) {
+    hal2mnl_update_network_state(connected, type, roaming, extra_info);
+}
+
+static void agps_ril_update_network_availability(int available, const char* apn) {
+    hal2mnl_update_network_availability(available, apn);
+}
+
+const AGpsRilInterface mtk_agps_ril_inf = {
+    sizeof(AGpsRilInterface),
+    agps_ril_init,
+    agps_ril_set_ref_location,
+    agps_ril_set_set_id,
+    agps_ril_ni_message,
+    agps_ril_update_network_state,
+    agps_ril_update_network_availability
+};
+
+//=========================================================
+// Supl Certificate Interface
+
+#if 0  // not ready, even in GPS JNI
+static int suplcert_install_certificates(
+        __unused const DerEncodedCertificate* certificates,
+        __unused size_t length) {
+    UNUSED_VAR(certificates);
+    UNUSED_VAR(length);
+    // TODO: to use the new hal2mnl lib
+    return -1;
+}
+
+static int suplcert_revoke_certificates(
+        __unused const Sha1CertificateFingerprint* fingerprints,
+        __unused size_t length) {
+    UNUSED_VAR(fingerprints);
+    UNUSED_VAR(length);
+    // TODO: to use the new hal2mnl lib
+    return -1;
+}
+
+const SuplCertificateInterface mtk_supl_cert_inf = {
+    sizeof(SuplCertificateInterface),
+    suplcert_install_certificates,
+    suplcert_revoke_certificates,
+};
+#endif
+
diff --git a/src/connectivity/gps/gps_hal/src/data_coder.c b/src/connectivity/gps/gps_hal/src/data_coder.c
new file mode 100644
index 0000000..ab67b38
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char get_byte(char* buff, int* offset, int src_len) {
+    char ret = 0;
+    if (*offset >= 0 && *offset < src_len) {
+        ret = buff[*offset];
+        *offset += 1;
+    }
+    return ret;
+}
+
+short get_short(char* buff, int* offset, int src_len) {
+    short ret = 0;
+    ret |= get_byte(buff, offset, src_len) & 0xff;
+    ret |= (get_byte(buff, offset, src_len) << 8);
+    return ret;
+}
+
+int get_int(char* buff, int* offset, int src_len) {
+    int ret = 0;
+    ret |= get_short(buff, offset, src_len) & 0xffff;
+    ret |= (get_short(buff, offset, src_len) << 16);
+    return ret;
+}
+
+long long get_long(char* buff, int* offset, int src_len) {
+    long long ret = 0;
+    ret |= get_int(buff, offset, src_len) & 0xffffffffL;
+    ret |= ((long long)get_int(buff, offset, src_len) << 32);
+    return ret;
+}
+
+float get_float(char* buff, int* offset, int src_len) {
+    float ret;
+    int tmp = get_int(buff, offset, src_len);
+    ret = *((float*)&tmp);
+    return ret;
+}
+
+double get_double(char* buff, int* offset, int src_len) {
+    double ret;
+    long long tmp = get_long(buff, offset, src_len);
+    ret = *((double*)&tmp);
+    return ret;
+}
+
+char* get_string(char* buff, int* offset, int src_len) {
+    char ret = get_byte(buff, offset, src_len);
+    if (ret == 0) {
+        return NULL;
+    } else {
+        char* p = NULL;
+        int len = get_int(buff, offset, src_len);
+        if (*offset < 0 || *offset >= src_len) {
+            *offset = 0;
+        }
+        if ((len > src_len - *offset) || len < 0) {
+            len = src_len - *offset;
+        }
+        if (len <= 0) {
+            return NULL;
+        }
+        p = &buff[*offset];
+        p[len-1] = 0;
+        *offset += len;
+        return p;
+    }
+}
+
+char* get_string2(char* buff, int* offset, int src_len) {
+    char* output = get_string(buff, offset, src_len);
+    if (output == NULL) {
+        return "";
+    } else {
+        return output;
+    }
+}
+
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+    int len = 0;
+    if (*offset >= 0 && *offset <= src_len) {
+        len = get_int(buff, offset, src_len);
+        if (len > MIN((src_len-(*offset)), des_len)) {
+            len = MIN((src_len-(*offset)), des_len);
+        }
+        if (len > 0) {
+            memcpy(output, &buff[*offset], len);
+            *offset += len;
+        }
+    }
+    return len;
+}
+
+//===============================================================
+// put
+void put_byte(char* buff, int* offset, const char input) {
+    *((char*)&buff[*offset]) = input;
+    *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+    put_byte(buff, offset, input & 0xff);
+    put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+    put_short(buff, offset, input & 0xffff);
+    put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+    put_int(buff, offset, input & 0xffffffffL);
+    put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+    int* data = (int*)&input;
+    put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+    long long* data = (long long*)&input;
+    put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+    if (input == NULL) {
+        put_byte(buff, offset, 0);
+    } else {
+        int len = strlen(input) + 1;
+        put_byte(buff, offset, 1);
+        put_int(buff, offset, len);
+        memcpy(&buff[*offset], input, len);
+        *offset += len;
+    }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+    put_int(buff, offset, len);
+    if (len > 0) {
+        memcpy(&buff[*offset], input, len);
+        *offset += len;
+    }
+}
+
diff --git a/src/connectivity/gps/gps_hal/src/geofenceinf.c b/src/connectivity/gps/gps_hal/src/geofenceinf.c
new file mode 100644
index 0000000..78c229f
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/geofenceinf.c
@@ -0,0 +1,153 @@
+#include "gpshal.h"

+#include "geofencehal_worker.h"

+#include "mtk_auto_log.h"

+#include <stdio.h>

+#include <inttypes.h>

+

+#ifndef UNUSED

+#define UNUSED(x) (x)=(x)

+#endif

+

+/**********************************************************

+ *  Global Variables                                      *

+ **********************************************************/

+extern unsigned int gConfigHalGeofence;

+

+/*********************************************************/

+/* FLP Geofence Interface implementation                 */

+/*********************************************************/

+void mtk_hal_geofence_init(GpsGeofenceCallbacks* callbacks) {

+    hal2_geofence_init();

+    LOGD("init geofence, cb function : %p",callbacks);

+    g_gpshal_ctx.geofence_cbs= callbacks;

+    return;

+}

+

+void mtk_hal_geofence_add_geofences(int32_t geofence_id, double latitude, double longitude,

+    double radius_meters, int last_transition, int monitor_transitions,

+    int notification_responsiveness_ms, int unknown_timer_ms) {

+    MTK_GEOFENCE_PROPERTY_T dbg_fence;

+

+    if(!is_gfc_exist()) {

+        LOGE("gfc not exist");

+        return;

+    }

+    dbg_fence.geofence_id = geofence_id;

+    dbg_fence.latitude = latitude;

+    dbg_fence.longitude = longitude;

+    dbg_fence.radius = radius_meters;

+    dbg_fence.last_transition = last_transition;

+    dbg_fence.monitor_transition = monitor_transitions;

+    dbg_fence.notification_period = notification_responsiveness_ms;

+    dbg_fence.unknown_timer = unknown_timer_ms;

+    dbg_fence.alive = 1;

+    dbg_fence.latest_state = last_transition >> 1;

+    dbg_fence.config = gConfigHalGeofence;

+    mtk_geo_inject_info_get(dbg_fence.geofence_id, &dbg_fence.coordinate_dn, &dbg_fence.coordinate_de);

+    hal2_geofence_add_geofences(dbg_fence);

+    return;

+}

+

+void mtk_hal_geofence_pause_geofence(int32_t geofence_id) {

+    if(!is_gfc_exist()) {

+        LOGE("gfc not exist");

+        return;

+    }

+    hal2_geofence_pause_geofence(geofence_id);

+    return;

+}

+

+void mtk_hal_geofence_resume_geofence(int32_t geofence_id, int monitor_transitions) {

+    if(!is_gfc_exist()) {

+        LOGE("gfc not exist");

+        return;

+    }

+    hal2_geofence_resume_geofence(geofence_id,monitor_transitions);

+    return;

+}

+

+void mtk_hal_geofence_remove_geofences(int32_t geofence_id) {

+    if(!is_gfc_exist()) {

+        LOGE("gfc not exist");

+        return;

+    }

+    hal2_geofence_remove_geofences(geofence_id);

+    return;

+}

+

+/*************************************************************/

+/*  Handle message from mnl to GPS/Geofence HAL              */

+/*************************************************************/

+void mtk_geofence_transition_callbacks_proc(MTK_FLP_MSG_T *prmsg) {

+    int32_t geofence_id, transition;

+    GpsLocation location;

+    int64_t timestamp;

+    #ifdef MTK_64_PLATFORM

+    unsigned char ratio = 2; //32 to 64-bits

+    unsigned char padding_diff = 4;

+    unsigned char loc_in[128] = {0};

+    unsigned int sizeof_loc_in = sizeof(GpsLocation) - sizeof(size_t)/ratio - padding_diff;

+    #else

+    uint32_t sizeof_loc_in = sizeof(GpsLocation);

+    #endif

+    memcpy(&geofence_id, (((char*)prmsg)+sizeof(MTK_FLP_MSG_T)), sizeof(int32_t));

+    #ifdef MTK_64_PLATFORM

+    memcpy(loc_in, (((char*)prmsg)+sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)), sizeof_loc_in);

+    mtk_loc_rearrange(loc_in, &location);

+    #else

+    memcpy(&location, (((char*)prmsg)+sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)), sizeof_loc_in);

+    #endif

+    memcpy(&transition, (((char*)prmsg)+sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)+sizeof_loc_in), sizeof(int32_t));

+    memcpy(&timestamp, (((char*)prmsg)+sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)+sizeof_loc_in+sizeof(int32_t)), sizeof(int64_t));

+    LOGD("geo transition: id=%"PRId32", transition=%"PRId32", latlon=%lf,%lf",geofence_id,transition,location.latitude,location.longitude);

+

+    if(g_gpshal_ctx.geofence_cbs == NULL) {

+        LOGE("mtk_geofence_transition_callbacks_proc: NO geofence callbacks assigned");

+        return;

+    }

+

+    //geofence CB for transition ntf

+    if (set_buff_transition_fence(geofence_id, transition) == 0) {

+       g_gpshal_ctx.geofence_cbs->geofence_transition_callback(geofence_id, &location, transition, timestamp);

+    }

+}

+

+void mtk_geofence_callbacks_proc(MTK_FLP_MSG_T *prmsg) {

+    MTK_GEOFENCE_CALLBACK_T cbs;

+

+    memcpy(&cbs,(char*)prmsg+sizeof(MTK_FLP_MSG_T),sizeof(MTK_GEOFENCE_CALLBACK_T));

+    //LOGD("geo_cb_proc: id=%d, result=%d",cbs.cb_id,cbs.result);

+

+    if(g_gpshal_ctx.geofence_cbs == NULL) {

+        LOGE("mtk_geofence_callbacks_proc: NO geofence callbacks assigned");

+        return;

+    }

+    switch(cbs.cb_id) {

+    case GEOFENCE_ADD_CALLBACK:

+        g_gpshal_ctx.geofence_cbs->geofence_add_callback(cbs.geofence_id, cbs.result);

+        break;

+    case GEOFENCE_REMOVE_CALLBACK:

+        g_gpshal_ctx.geofence_cbs->geofence_remove_callback(cbs.geofence_id, cbs.result);

+        break;

+    case GEOFENCE_PAUSE_CALLBACK:

+        g_gpshal_ctx.geofence_cbs->geofence_pause_callback(cbs.geofence_id, cbs.result);

+        break;

+    case GEOFENCE_RESUME_CALLBACK:

+        g_gpshal_ctx.geofence_cbs->geofence_resume_callback(cbs.geofence_id, cbs.result);

+        break;

+    default:

+        LOGE("mtk_geofence_callbacks_proc: Unknown callback id:%d", cbs.cb_id);

+        break;

+    }

+}

+

+const GpsGeofencingInterface mtkGeofence_inf = {

+    sizeof(GpsGeofencingInterface),

+    mtk_hal_geofence_init,

+    mtk_hal_geofence_add_geofences,

+    mtk_hal_geofence_pause_geofence,

+    mtk_hal_geofence_resume_geofence,

+    mtk_hal_geofence_remove_geofences,

+};

+

+

diff --git a/src/connectivity/gps/gps_hal/src/gfchal_mnl_interface.c b/src/connectivity/gps/gps_hal/src/gfchal_mnl_interface.c
new file mode 100644
index 0000000..5215818
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/gfchal_mnl_interface.c
@@ -0,0 +1,717 @@
+#include <string.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <unistd.h>

+#include <fcntl.h>

+#include <sys/socket.h>

+#include <sys/types.h>

+#include <sys/stat.h>

+#include <sys/un.h>

+#include <errno.h>

+#include <inttypes.h>

+

+#include "geofencehal_worker.h"

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "GFC_INF"

+#endif

+

+/**********************************************************

+ *  Define                                                *

+ **********************************************************/

+typedef void*(*threadptr)(void*);

+#define GEOFENCE_INJECT_LOC_ENUM 600

+

+#define MNLD_STRNCPY(dst,src,size) do{\

+                                       strncpy((char *)(dst), (src), (size - 1));\

+                                      (dst)[size - 1] = '\0';\

+                                     }while(0)

+

+

+/**********************************************************

+ *  Global Variables                                      *

+ **********************************************************/

+static MTK_GEOFENCE_PROPERTY_T geofence_property[MAX_GOEFENCE];

+static float injectFenceInfo[MAX_GOEFENCE][3];

+static int gTotalFence = 0; /*current fence number, must < MAX_GEOFENCE*/

+static int  g_ThreadExitGfcJniSocket = 0, isgfc_exist = 0;

+static pthread_t geofence_hal_jni_thread_id;

+static char g_gfc2mnl_path[128] = GEOFENCE_TO_MNL;

+int  g_gfc_server_socket_fd;

+unsigned int gConfigHalGeofence = 0;

+

+/**********************************************************

+ *  Function Declaration                                  *

+ **********************************************************/

+void mnl2gfchal_jni_thread(void);

+

+

+/**********************************************************

+ *  Socket Function                                       *

+ **********************************************************/

+static int safe_recvfrom(int sockfd, char* buf, int len) {

+    int ret = 0;

+    int retry = 10;

+

+    while ((ret = recvfrom(sockfd, buf, len, 0, NULL, NULL)) == -1) {

+        //LOGW("ret=%d len=%d\n", ret, len);

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("sendto reason=[%s]\n", strerror(errno));

+        break;

+    }

+    return ret;

+}

+

+// -1 means failure

+static int safe_sendto(int sockfd, const char* dest, const char* buf, int size) {

+    int len = 0;

+    struct sockaddr_un soc_addr;

+    int retry = 10;

+

+    memset(&soc_addr, 0, sizeof(soc_addr));

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, dest,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+

+    while ((len = sendto(sockfd, buf, size, 0, (const struct sockaddr *)&soc_addr, sizeof(soc_addr))) == -1) {

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("sendto dest=[%s] len=%d reason=[%s]\n",dest, size, strerror(errno));

+        break;

+    }

+    return len;

+}

+

+static int gfc_send2mnl(const char* buff, int len) {

+    int ret = 0;

+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+

+    if (sockfd < 0) {

+        LOGE("gfc_send2mnl() socket() failed reason=[%s]%d",

+            strerror(errno), errno);

+        return -1;

+    }

+

+    if (safe_sendto(sockfd, g_gfc2mnl_path, buff, len) < 0) {

+        LOGE("gfc_send2mnl safe_sendto failed\n");

+        ret = -1;

+    }

+    close(sockfd);

+    return ret;

+}

+

+static int bind_udp_socket(char* path) {

+    int sockfd;

+    struct sockaddr_un soc_addr;

+

+    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+    if (sockfd < 0) {

+        LOGE("socket failed reason=[%s]\n", strerror(errno));

+        return -1;

+    }

+    memset(&soc_addr, 0, sizeof(soc_addr));

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, path,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+    unlink(soc_addr.sun_path);

+

+    if (bind(sockfd, (struct sockaddr *)&soc_addr, sizeof(soc_addr)) < 0) {

+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));

+        close(sockfd);

+        return -1;

+    }

+

+    return sockfd;

+}

+

+

+/**********************************************************

+ *  Geofence sub-Functions                                *

+ **********************************************************/

+static void set_buff_init_fence() {

+    int i;

+    memset(&geofence_property, 0, MAX_GOEFENCE*sizeof(MTK_GEOFENCE_PROPERTY_T));

+    for(i = 0; i < MAX_GOEFENCE; i++) {

+        geofence_property[i].geofence_id = -1;

+    }

+    gTotalFence = 0;

+    return;

+}

+

+static int set_buff_pause_fence(const int item) {

+    geofence_property[item].alive = 0;

+    geofence_property[item].last_transition = GPS_GEOFENCE_UNCERTAIN;

+    geofence_property[item].latest_state = uncertain;

+    return MTK_GFC_SUCCESS;

+}

+

+static int set_buff_resume_fence(const int item, const int transition) {

+    geofence_property[item].monitor_transition = transition;

+    geofence_property[item].alive = 1;

+    return MTK_GFC_SUCCESS;

+}

+

+static int set_buff_remove_fence(const int item) {

+    geofence_property[item].alive = 0;

+    memset(&geofence_property[item],0,sizeof(MTK_GEOFENCE_PROPERTY_T));

+    geofence_property[item].geofence_id = -1;

+    if(gTotalFence > 0) {

+        gTotalFence--;

+    }

+    return MTK_GFC_SUCCESS;

+}

+

+int set_buff_transition_fence(const int32_t fence_id, const int transition) {

+    int item;

+

+    if (transition != GPS_GEOFENCE_ENTERED &&

+        transition != GPS_GEOFENCE_EXITED &&

+        transition != GPS_GEOFENCE_UNCERTAIN) {

+        LOGE("transition type is invalid %d", transition);

+        return MTK_GFC_ERROR;

+    }

+

+    item = check_buff_fence_exist(fence_id);

+    if (item < 0) {

+        LOGE("transition fence id not exist");

+        return MTK_GFC_ERROR;

+    }

+    geofence_property[item].last_transition = transition;

+    geofence_property[item].latest_state = transition >> 1;

+    return MTK_GFC_SUCCESS;

+}

+

+void mtk_geo_inject_info_init() {

+    memset(injectFenceInfo, 0, sizeof(injectFenceInfo[0][0]) * MAX_GOEFENCE * 3);

+    //LOGD("GEO_JNI: init fence info\n");

+}

+

+static void mtk_geo_set_project_config() {

+    const char flp_prop_path[] = "/vendor/etc/geo.prop";

+    char propbuf[512];

+    FILE *fp = fopen(flp_prop_path, "rb");

+

+    gConfigHalGeofence = 0;

+    if(!fp) {

+        LOGE("mtk_flp_set_project_config - open fd fail! %d (%s)", errno, strerror(errno));

+        return;

+    }

+    while(fgets(propbuf, sizeof(propbuf), fp)) {

+        if(strstr(propbuf, "lowpower.geofence=no")) {

+            gConfigHalGeofence |= GEO_CONFIG_MASK_DISABLE_SMD;

+        }

+    }

+    LOGD("mtk_flp_set_project_config %u", gConfigHalGeofence);

+    fclose(fp);

+    return;

+}

+

+void mtk_geo_inject_info_set(int fence_id, float dn, float de) {

+    if (fence_id < MAX_GOEFENCE) {

+        injectFenceInfo[fence_id][0] = 1; //valid

+        injectFenceInfo[fence_id][1] = dn;

+        injectFenceInfo[fence_id][2] = de;

+        LOGD("GEO_JNI :set fence info, %d %f %f", fence_id, dn, de);

+    }

+}

+

+void mtk_geo_inject_info_reset(int fence_id) {

+    if (fence_id < MAX_GOEFENCE) {

+        injectFenceInfo[fence_id][0] = 0; //valid

+        injectFenceInfo[fence_id][1] = 0;

+        injectFenceInfo[fence_id][2] = 0;

+        LOGD("GEO_JNI: reset fence id %d\n", fence_id);

+    }

+}

+

+void mtk_geo_inject_info_get(int fence_id, float* dn, float* de) {

+    *dn = 0;

+    *de = 0;

+    if (fence_id < MAX_GOEFENCE) {

+        if (injectFenceInfo[fence_id][0]) {

+            *dn = injectFenceInfo[fence_id][1];

+            *de = injectFenceInfo[fence_id][2];

+            LOGD("GEO_JNI: get fence info %d %f %f\n", fence_id, *dn, *de);

+        }

+    }

+}

+

+static int check_buff_full_of_fence() {

+    if(gTotalFence >= MAX_GOEFENCE) {

+        return MTK_GFC_ERROR;

+    } else {

+        return MTK_GFC_SUCCESS;

+    }

+}

+

+int check_buff_fence_exist(const int32_t fence_id) {

+    int i;

+

+    for(i = 0; i < MAX_GOEFENCE; i++) {

+        if(geofence_property[i].geofence_id == fence_id ) {

+            return i;

+        }

+    }

+    return MTK_GFC_ERROR;

+}

+

+static int check_valid_transition(const int transition) {

+    switch(transition) {

+        case GPS_GEOFENCE_ENTERED:

+        case GPS_GEOFENCE_EXITED:

+        case GPS_GEOFENCE_ENTERED|GPS_GEOFENCE_EXITED:

+        case GPS_GEOFENCE_ENTERED|GPS_GEOFENCE_EXITED|GPS_GEOFENCE_UNCERTAIN:

+            return MTK_GFC_SUCCESS;

+        default:

+            return MTK_GFC_ERROR;

+    }

+}

+

+static int get_buff_avalibale_item() {

+    int i = 0;

+

+    while(i < MAX_GOEFENCE && geofence_property[i].alive == 1) {

+        i++;

+    }

+

+    if(i == MAX_GOEFENCE) {

+        return MTK_GFC_ERROR;

+    }

+    return i;

+}

+

+static int check_fence_vadility(const MTK_GEOFENCE_PROPERTY_T fence) {

+    int ret;

+    int ret2;

+

+    ret = check_buff_full_of_fence();

+    if(ret < 0) {

+        LOGE("too many fences\n");

+        ret2 =  -1;

+        return ret2;

+    }

+    ret = check_buff_fence_exist(fence.geofence_id);

+    if(ret >= 0) {

+        LOGE("fence has been added before\n");

+        ret2 =  -2;

+        return ret2;

+    }

+    ret = check_valid_transition(fence.monitor_transition);

+    if(ret < 0) {

+        LOGE("fence is invalid\n");

+        ret2 =  -3;

+        return ret2;

+    }

+    ret2 = 0;

+    return ret2;

+}

+

+static int set_buff_add_fence(const MTK_GEOFENCE_PROPERTY_T fence) {

+    int item;

+

+    item = get_buff_avalibale_item();

+    if(item < 0) {

+        LOGE("out of range\n");

+        return MTK_GFC_ERROR;

+    }

+    //LOGD("new fenece will be added into item %d\n", item);

+

+    memcpy(&geofence_property[item], &fence, sizeof(MTK_GEOFENCE_PROPERTY_T));

+    geofence_property[item].alive = 1;

+    gTotalFence++;

+    return MTK_GFC_SUCCESS;

+}

+

+#ifdef MTK_64_PLATFORM

+void mtk_loc_rearrange(unsigned char *loc_in, GpsLocation *loc_out) {

+    unsigned char ratio = 2; //32 to 64-bits

+    unsigned char padding_diff = 4;

+    unsigned int sizeof_loc_in = sizeof(GpsLocation) - sizeof(size_t)/ratio - padding_diff;

+

+    memset(loc_out, 0, sizeof(GpsLocation));

+    loc_out->size = sizeof(GpsLocation);

+    memcpy(&loc_out->flags, loc_in + sizeof(size_t)/ratio, sizeof(uint16_t));

+    memcpy(&loc_out->latitude, loc_in + sizeof(size_t), sizeof_loc_in - sizeof(size_t));

+}

+#endif

+

+/*************************************************************/

+/*  mnl to FLP HAL socket, -1 means failure                  */

+/*************************************************************/

+int create_mnl2gfchal_fd() {

+    int fd = bind_udp_socket(MNL_TO_GEOFENCE);

+    return fd;

+}

+

+int is_gfc_exist() {

+    return isgfc_exist;

+}

+

+

+/*********************************************************/

+/* GPS Geofence Interface implementation                 */

+/*********************************************************/

+void hal2_geofence_init() {

+    int  ret;

+    #if 0

+    int offset = 0;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *geo_header =NULL;

+    MTK_FLP_MSG_T geo_msg;

+    #endif

+

+    //Init client socket thread

+    if(isgfc_exist) {

+        LOGE("geofence init before");

+        return;

+    }

+    ret = pthread_create(&geofence_hal_jni_thread_id, NULL, (threadptr)mnl2gfchal_jni_thread, NULL);

+    if(ret < 0) {

+        LOGE("Create mnl2gfchal_jni_thread error\n");

+    }

+    isgfc_exist = 1;

+    #if 0

+    geo_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(MTK_FLP_MSG_T));

+    if(geo_header == NULL) {

+        LOGE("init fence malloc error");

+        return;

+    }

+

+    geo_header->type = MTK_FLP_MSG_OFL_GEOFENCE_CMD;

+    geo_header->length = sizeof(MTK_FLP_MSG_T) + sizeof(MTK_FLP_MSG_T);

+    geo_msg.type = INIT_GEOFENCE;

+    geo_msg.length = sizeof(MTK_FLP_MSG_T);

+    memcpy( ((char*)geo_header)+sizeof(MTK_FLP_MSG_T),&geo_msg, sizeof(MTK_FLP_MSG_T));

+    put_binary(buff, &offset, (const char*)&geo_header, geo_header->length);

+    ret = gfc_send2mnl(buff, offset);

+    free(geo_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2GFC send error return error");

+        return;

+    }

+    #endif

+    set_buff_init_fence();

+    mtk_geo_inject_info_init();

+    mtk_geo_set_project_config();

+    return;

+}

+

+void hal2_geofence_add_geofences(const MTK_GEOFENCE_PROPERTY_T dbg_fence) {

+    int ret, offset = 0;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    int32_t partial_size = 1;

+    MTK_FLP_MSG_T *geo_header=NULL;

+    MTK_FLP_MSG_T geo_msg;

+

+    /* For geofence recover mechanism */

+    ret = check_fence_vadility(dbg_fence);

+    if (ret == 0) {

+        set_buff_add_fence(dbg_fence);

+    } else {

+        return;

+    }

+

+    //construct add fence cmd

+    geo_header = malloc(2*sizeof(MTK_FLP_MSG_T)+sizeof(int32_t) + sizeof(MTK_GEOFENCE_PROPERTY_T));

+    if(geo_header == NULL) {

+        LOGE("add fence malloc error");

+        return;

+    }

+

+    geo_header->type = MTK_FLP_MSG_OFL_GEOFENCE_CMD;

+    geo_header->length = sizeof(MTK_FLP_MSG_T) + sizeof(MTK_FLP_MSG_T) + sizeof(int32_t) + sizeof(MTK_GEOFENCE_PROPERTY_T);

+    geo_msg.type = ADD_GEOFENCE_AREA;

+    geo_msg.length =  sizeof(MTK_FLP_MSG_T) + sizeof(int32_t) + sizeof(MTK_GEOFENCE_PROPERTY_T);

+    memcpy( ((char*)geo_header)+sizeof(MTK_FLP_MSG_T),&geo_msg, sizeof(MTK_FLP_MSG_T));

+    memcpy( ((char*)geo_header)+2*sizeof(MTK_FLP_MSG_T),&partial_size, sizeof(int32_t));

+    memcpy( ((char*)geo_header)+2*sizeof(MTK_FLP_MSG_T)+sizeof(int32_t),&dbg_fence, sizeof(MTK_GEOFENCE_PROPERTY_T));

+    #if 1

+    LOGD("HAL Add fence, id=%d, ll=%lf,%lf, last=%d, monitor=%d, notsec=%d, unksec=%d, ned=%f,%f, con=%u",

+        dbg_fence.geofence_id, dbg_fence.latitude, dbg_fence.longitude,

+        dbg_fence.last_transition, dbg_fence.monitor_transition,

+        dbg_fence.notification_period, dbg_fence.unknown_timer,

+        dbg_fence.coordinate_dn, dbg_fence.coordinate_de, dbg_fence.config);

+    #endif

+    put_binary(buff, &offset, (const char*)geo_header, geo_header->length);

+    ret = gfc_send2mnl(buff, offset);

+    free(geo_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2GFC send error return error");

+        return;

+    }

+    return;

+}

+

+void hal2_geofence_pause_geofence(const int32_t geofence_id) {

+    int ret, offset = 0;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *geo_header=NULL;

+    MTK_FLP_MSG_T geo_msg;

+

+    /* For geofence recover mechanism */

+    ret = check_buff_fence_exist(geofence_id);

+    if (ret != MTK_GFC_ERROR) {

+        set_buff_pause_fence(ret);

+    } else {

+        return;

+    }

+

+    //LOGD("hal2_geofence_pause_geofence, id: %d fence",geofence_id);

+    //construct pause fence cmd

+    geo_header = malloc(2*sizeof(MTK_FLP_MSG_T) + sizeof(int32_t));

+    if(geo_header == NULL) {

+        LOGE("pause fence malloc error");

+        return;

+    }

+

+    geo_header->type = MTK_FLP_MSG_OFL_GEOFENCE_CMD;

+    geo_header->length = sizeof(MTK_FLP_MSG_T) + sizeof(MTK_FLP_MSG_T) + sizeof(int32_t);

+    geo_msg.type = PAUSE_GEOFENCE;

+    geo_msg.length = sizeof(MTK_FLP_MSG_T) + sizeof(int32_t);

+    memcpy( ((char*)geo_header)+sizeof(MTK_FLP_MSG_T),&geo_msg, sizeof(MTK_FLP_MSG_T));

+    memcpy( ((char*)geo_header)+2*sizeof(MTK_FLP_MSG_T),&geofence_id, sizeof(int32_t));

+    put_binary(buff, &offset, (const char*)geo_header, geo_header->length);

+    ret = gfc_send2mnl(buff, offset);

+    free(geo_header);

+    if(ret < 0) {

+        LOGD("MTK_HAL2GFC send error return error");

+        return;

+    }

+    return;

+}

+

+

+void hal2_geofence_resume_geofence(const int32_t geofence_id, const int monitor_transitions) {

+    int ret, offset = 0;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *geo_header=NULL;

+    MTK_FLP_MSG_T geo_msg;

+

+    /* For geofence recover mechanism */

+    ret = check_buff_fence_exist(geofence_id);

+    if(ret != MTK_GFC_ERROR) {

+        set_buff_resume_fence(ret, monitor_transitions);

+    } else {

+        return;

+    }

+

+    //LOGD("hal2_geofence_resume_geofence, id: %d fence",geofence_id);

+    //construct resume fence cmd

+    geo_header = malloc(2*sizeof(MTK_FLP_MSG_T) + sizeof(int32_t) + sizeof(int));

+    if(geo_header == NULL) {

+        LOGE("resume fence malloc error");

+        return;

+    }

+    geo_header->type = MTK_FLP_MSG_OFL_GEOFENCE_CMD;

+    geo_header->length = 2*sizeof(MTK_FLP_MSG_T) + sizeof(int32_t) + sizeof(int);

+    geo_msg.type = RESUME_GEOFENCE;

+    geo_msg.length =  sizeof(MTK_FLP_MSG_T) + sizeof(int32_t) + sizeof(int);

+    memcpy( ((char*)geo_header)+sizeof(MTK_FLP_MSG_T),&geo_msg, sizeof(MTK_FLP_MSG_T));

+    memcpy( ((char*)geo_header)+2*sizeof(MTK_FLP_MSG_T),&geofence_id, sizeof(int32_t));

+    memcpy( ((char*)geo_header)+2*sizeof(MTK_FLP_MSG_T)+sizeof(int32_t),&monitor_transitions, sizeof(int));

+    put_binary(buff, &offset, (const char*)geo_header, geo_header->length);

+    ret = gfc_send2mnl(buff, offset);

+    free(geo_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2GFC send error return error");

+        return;

+    }

+    return;

+}

+

+void hal2_geofence_remove_geofences(const int32_t geofence_id) {

+    int ret, offset = 0;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T *geo_header=NULL;

+    MTK_FLP_MSG_T geo_msg;

+

+    /* For geofence recover mechanism */

+    ret = check_buff_fence_exist(geofence_id);

+    if(ret != MTK_GFC_ERROR) {

+        mtk_geo_inject_info_reset(geofence_id);

+        set_buff_remove_fence(ret);

+    } else {

+        return;

+    }

+

+    //LOGD("hal2_geofence_remove_geofences, fence id =%d",geofence_id);

+    //construct remove fence cmd

+    geo_header = malloc(2*sizeof(MTK_FLP_MSG_T) + sizeof(int32_t));

+    if(geo_header == NULL) {

+        LOGE("resume fence malloc error");

+        return;

+    }

+

+    geo_header->type = MTK_FLP_MSG_OFL_GEOFENCE_CMD;

+    geo_header->length = sizeof(MTK_FLP_MSG_T) + sizeof(MTK_FLP_MSG_T) + sizeof(int32_t);

+    geo_msg.type = REMOVE_GEOFENCE;

+    geo_msg.length = sizeof(MTK_FLP_MSG_T) + sizeof(int32_t);

+    memcpy( ((char*)geo_header)+sizeof(MTK_FLP_MSG_T),&geo_msg, sizeof(MTK_FLP_MSG_T));

+    memcpy( ((char*)geo_header)+2*sizeof(MTK_FLP_MSG_T),&geofence_id, sizeof(int32_t));

+    put_binary(buff, &offset, (const char*)geo_header, geo_header->length);

+    ret = gfc_send2mnl(buff, offset);

+    free(geo_header);

+    if(ret < 0) {

+        LOGE("MTK_HAL2GFC send error return error");

+        return;

+    }

+    return;

+}

+

+void hal2_geofence_recover_geofences() {

+    int ret, offset = 0;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    int i;

+    int partial_size = 1;

+    MTK_FLP_MSG_T* geo_header = NULL;

+    MTK_FLP_MSG_T geo_msg;

+

+    LOGE("FLP HAL RECOVER: recover total fence = %d", gTotalFence);

+    for(i = 0; i < MAX_GOEFENCE; i++) {

+        if(geofence_property[i].alive == 1) {

+            geo_header = malloc( sizeof(MTK_FLP_MSG_T)+ sizeof(MTK_FLP_MSG_T) + sizeof(int32_t) + sizeof(MTK_GEOFENCE_PROPERTY_T));

+            geo_header->type = MTK_FLP_MSG_OFL_GEOFENCE_CMD;

+            geo_header->length =  sizeof(MTK_FLP_MSG_T)+ sizeof(MTK_FLP_MSG_T)+ sizeof(int32_t) + sizeof(MTK_GEOFENCE_PROPERTY_T);

+            geo_msg.type = RECOVER_GEOFENCE;

+            geo_msg.length =  sizeof(MTK_FLP_MSG_T)+ sizeof(int32_t) + sizeof(MTK_GEOFENCE_PROPERTY_T);

+            memcpy(((char*)geo_header)+sizeof(MTK_FLP_MSG_T), &geo_msg, sizeof(MTK_FLP_MSG_T));

+            memcpy((((char*)geo_header)+sizeof(MTK_FLP_MSG_T)+sizeof(MTK_FLP_MSG_T)), &partial_size, sizeof(int32_t));

+            memcpy((((char*)geo_header)+sizeof(MTK_FLP_MSG_T)+sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)),&geofence_property[i],sizeof(MTK_GEOFENCE_PROPERTY_T));

+            LOGE("FLP HAL RECOVER: id=%"PRId32",type=%d,%d,%d,%lf,%d",geofence_property[i].geofence_id,geofence_property[i].last_transition,geofence_property[i].monitor_transition,

+            geofence_property[i].notification_period,geofence_property[i].latitude,geofence_property[i].unknown_timer);

+            offset = 0;

+            put_binary(buff, &offset, (const char*)geo_header, geo_header->length);

+            ret = gfc_send2mnl(buff, offset);

+            free(geo_header);

+            if(ret < 0) {

+                LOGE("MTK_HAL2GFC send error return error");

+                return;

+            }

+        }

+    }

+    return;

+}

+

+int mnl2gfchal_hdlr (char *buff) {

+    char data[1024] = {0};

+    int offset = 0;

+    int ret = MTK_GFC_ERROR, len;

+    unsigned int cmd, msg_len;

+    float geo_inject[3] = {0};

+    MTK_FLP_MSG_T *prmsg = NULL;

+

+    if(buff == NULL) {

+        LOGE("mnl2gfchal_hdlr, recv prmsg is null pointer\r\n");

+        return MTK_GFC_ERROR;

+    }

+    len = get_binary(buff, &offset, data, HAL_GFC_BUFF_SIZE, sizeof(data));

+    if((len > 0) && (len<=1024)) {

+        prmsg = (MTK_FLP_MSG_T *)&data[0];

+    } else {

+        LOGE("len err:%d",len);

+        return ret;

+    }

+    cmd = prmsg->type;

+    msg_len = prmsg->length;

+

+    LOGD("msg_len, recv prmsg, type %d, len %d\r\n", cmd, msg_len);

+    switch (cmd) {

+        case MTK_FLP_MSG_SYS_FLPD_RESET_NTF:

+            hal2_geofence_recover_geofences();

+            break;

+        case MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF:

+            mtk_geofence_transition_callbacks_proc(prmsg);

+            break;

+        case MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF:

+            mtk_geofence_callbacks_proc(prmsg);

+            break;

+        case GEOFENCE_INJECT_LOC_ENUM:

+            if(msg_len< 3*sizeof(float)) {

+                LOGE("GEOFENCE_INJECT_LOC_ENUM incrorrect size %d",msg_len);

+                return MTK_GFC_ERROR;

+            }

+            memcpy(geo_inject, (char *)prmsg + sizeof(MTK_FLP_MSG_T), 3*sizeof(float));

+            mtk_geo_inject_info_set((int)geo_inject[0],geo_inject[1],geo_inject[2]);

+            break;

+        default:

+            LOGE("invalid geofence cmd:0x%02x",cmd);

+            break;

+    }

+    return MTK_GFC_SUCCESS;

+}

+

+

+/*************************************************************/

+/*  mnl to GPS/Geofence HAL main thread                      */

+/*************************************************************/

+void mnl2gfchal_jni_thread(void) {

+

+    int ret = MTK_GFC_SUCCESS;

+    int offset = 0;

+    int read_len;

+    char buff[HAL_GFC_BUFF_SIZE] = {0};

+    MTK_FLP_MSG_T gfc_header;

+

+    LOGD("mtk_gfc_hal_jni_thread, Create\n");

+

+    g_gfc_server_socket_fd = create_mnl2gfchal_fd();

+

+    ///TODO: add system timer function here

+    //mtk_flp_sys_timer_create(FLP_TIMER_ID_CHECKCNN);

+    //Send SYS_INIT to HAL

+    gfc_header.type = MTK_FLP_MSG_HAL_INIT_CMD;

+    gfc_header.length = 0;

+    put_binary(buff, &offset, (const char*)&gfc_header, sizeof(MTK_FLP_MSG_T));

+    ret = gfc_send2mnl(buff, offset);

+    //LOGD("gfc:MTK_FLP_MSG_HAL_INIT_CMD");

+    if(ret < 0) {

+        LOGE("MTK_HAL2GFC send error return error");

+    }

+

+    if (g_gfc_server_socket_fd >= 0) {

+        while(!g_ThreadExitGfcJniSocket) {

+            // - recv msg from socket interface

+            read_len = safe_recvfrom(g_gfc_server_socket_fd, buff, sizeof(buff));

+            if ((read_len <= 0) || (read_len>HAL_GFC_BUFF_SIZE)) {

+                LOGE("mnl2gfc safe_recvfrom failed read_len=%d", read_len);

+            }

+

+            if (!g_ThreadExitGfcJniSocket) {

+                // Process received message

+                mnl2gfchal_hdlr(buff);

+            } else {

+                LOGE("mtk_flp_hal_jni_thread, read msg fail,exit socket thread\n");

+                //read msg fail...

+                g_ThreadExitGfcJniSocket = 1;

+            }

+        }

+    }

+

+    //close socket

+    LOGD("Closing server_fd,%d\r\n",g_gfc_server_socket_fd);

+    if(g_gfc_server_socket_fd >= 0) {

+        close(g_gfc_server_socket_fd);

+    }

+

+    LOGD("mnl2gfchal_jni_thread, exit\n");

+

+    g_ThreadExitGfcJniSocket = 1;

+    pthread_exit(NULL);

+

+    return;

+}

+

+

diff --git a/src/connectivity/gps/gps_hal/src/gpshal.c b/src/connectivity/gps/gps_hal/src/gpshal.c
new file mode 100644
index 0000000..41ac6a9
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/gpshal.c
@@ -0,0 +1,221 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include <sys/epoll.h>  // epoll_create, epoll_event
+#include <errno.h>     // errno
+#include <string.h>    // strerror
+
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "gpshal_param_check.h"
+#include "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gpshal"
+#endif
+
+#define GPSHAL_WORKER_THREAD_NAME "gpshal_worker_thread"
+
+//=========================================================
+
+gpshal_context_t g_gpshal_ctx = {
+    .fd_mnl2hal        = -1,
+    .fd_worker_epoll   = -1,
+    .thd_worker        = 0,
+    .mutex_gps_state_intent = PTHREAD_MUTEX_INITIALIZER,
+    .gps_state_intent  = GPSHAL_STATE_UNKNOWN,
+    .gps_state         = GPSHAL_STATE_UNKNOWN,
+    .gps_cbs           = NULL,
+    .agps_cbs          = NULL,
+    .gpsni_cbs         = NULL,
+    .agpsril_cbs       = NULL,
+    .meas_cbs          = NULL,
+    .navimsg_cbs       = NULL,
+    .geofence_cbs      = NULL,
+    .vzw_debug_cbs     = NULL,
+};
+
+//=========================================================
+
+const char* gpshal_state_to_string(gpshal_state state) {
+    switch (state) {
+        case GPSHAL_STATE_UNKNOWN:  return "UNKNOWN";
+        case GPSHAL_STATE_RESOURCE: return "RESOURCE_INIT";
+        case GPSHAL_STATE_CLEANUP:  return "CLEANUP";
+        case GPSHAL_STATE_INIT:     return "INIT";
+        case GPSHAL_STATE_STOP:     return "STOP";
+        case GPSHAL_STATE_START:    return "START";
+        default:                    return "INVALID";
+    }
+}
+
+static void gpshal_set_gps_state(gpshal_state newState) {
+    /*LOGD("gps_state: %s -> %s (intent: %s)",
+            gpshal_state_to_string(g_gpshal_ctx.gps_state),
+            gpshal_state_to_string(newState),
+            gpshal_state_to_string(g_gpshal_ctx.gps_state_intent));*/
+    g_gpshal_ctx.gps_state = newState;
+}
+
+void gpshal_set_gps_state_intent(gpshal_state newState) {
+    /*LOGD("gps_state: %s (intent: %s -> %s)",
+            gpshal_state_to_string(g_gpshal_ctx.gps_state),
+            gpshal_state_to_string(g_gpshal_ctx.gps_state_intent),
+            gpshal_state_to_string(newState));*/
+    g_gpshal_ctx.gps_state_intent = newState;
+}
+
+static void gpshal_check_capability(unsigned int *capabilities, unsigned int *year) {
+    #if ANDROID_MNLD_PROP_SUPPORT
+    char chip_id[PROPERTY_VALUE_MAX]={0};
+    property_get("persist.vendor.connsys.chipid", chip_id, NULL);
+    #else
+    char chip_id[100]={0};
+    strncpy(chip_id, "0x6630",sizeof(chip_id));
+    #endif
+    LOGI("chip id = %s", chip_id);
+    if (strcmp(chip_id, "0x6739") == 0 || strcmp(chip_id, "0x6765") == 0 ||
+        strcmp(chip_id, "0x6761") == 0) {
+        /*our HIDL version is 1.0, if the year is 2018, CTS GnssHardwareInfoTest#testHardwareModelName will fail*/
+        //*year = 2018;
+        *year = 2017;
+        *capabilities = (GPS_CAP_MEASUREMENTS | GPS_CAP_MSB | GPS_CAP_MSA);
+    } else {
+        /*our HIDL version is 1.0, if the year is 2018, CTS GnssHardwareInfoTest#testHardwareModelName will fail*/
+        *year = 2017;
+        *capabilities = (GPS_CAP_MEASUREMENTS | GPS_CAP_MSB | GPS_CAP_MSA);
+    }
+}
+//=========================================================
+
+// Design policy
+//     Init resources at most once (no retry)
+//         Because we can not save an unstable system,
+//         we think "less system call is better" for an unstable system
+//     Do not deinit resources
+//         We want to have a simple design for a built-in service
+//         "Deinit" is for an installable / removable service
+static void gpshal_resource_init(GpsCallbacks_ext* src) {
+    unsigned int capabilities = 0;
+    unsigned int year = 0;
+    g_gpshal_ctx.gps_cbs = (GpsCallbacks_ext*)src;
+    if (GPSHAL_STATE_UNKNOWN != g_gpshal_ctx.gps_state_intent) return;  // at most once
+
+    gpshal_check_capability(&capabilities, &year);
+    LOGI("year = %d, capabilities = %d", year, capabilities);
+    g_gpshal_ctx.gps_cbs->set_capabilities_cb(capabilities);
+
+    GnssSystemInfo system_info;
+    system_info.year_of_hw = year;
+    system_info.size = sizeof(GnssSystemInfo);
+    g_gpshal_ctx.gps_cbs->set_system_info_cb(&system_info);
+
+    g_gpshal_ctx.fd_mnl2hal = create_mnl2hal_fd();
+    if (-1 == g_gpshal_ctx.fd_mnl2hal) return;  // error
+
+    g_gpshal_ctx.fd_worker_epoll = epoll_create(MAX_EPOLL_EVENT);
+    if (-1 == g_gpshal_ctx.fd_worker_epoll) {
+        LOGE("Fail to create epoll reason=[%s]%d",
+                strerror(errno), errno);
+        return;  // error
+    }
+
+    if (epoll_add_fd(
+            g_gpshal_ctx.fd_worker_epoll,
+            g_gpshal_ctx.fd_mnl2hal) == -1) {
+        LOGE("Fail to add fd_mnl2hal");
+        return;  // error
+    }
+
+    g_gpshal_ctx.thd_worker = g_gpshal_ctx.gps_cbs->create_thread_cb(
+            GPSHAL_WORKER_THREAD_NAME, gpshal_worker_thread, NULL);
+    if (!g_gpshal_ctx.thd_worker) {
+        LOGE("Fail to create %s", GPSHAL_WORKER_THREAD_NAME);
+        return;  // error
+    }
+
+    gpshal_set_gps_state(GPSHAL_STATE_RESOURCE);
+}
+
+int gpshal_gpscbs_save(GpsCallbacks_ext* src) {
+// assert(NULL != src);
+    if (sizeof(GpsCallbacks_ext) == src->size) {
+        LOGD("Use GpsCallbacks");
+        gpshal_resource_init(src);
+        return 0;
+    }
+    LOGE("Bad callback, size: %zd, expected: %zd",
+            src->size, sizeof(GpsCallbacks_ext));
+    return -1;    //  error
+}
+
+//=========================================================
+
+void gpshal2mnl_gps_init() {
+    if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {  // Check this for unstable system
+        if (hal2mnl_gps_init() > 0) {
+            gpshal_set_gps_state(GPSHAL_STATE_INIT);
+        }
+    }
+}
+
+void gpshal2mnl_gps_start() {
+    if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {
+        if (hal2mnl_gps_start() > 0) {
+            gpshal_set_gps_state(GPSHAL_STATE_START);
+        }
+    }
+}
+
+void gpshal2mnl_gps_stop() {
+    if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {
+        if (hal2mnl_gps_stop() > 0) {
+            gpshal_set_gps_state(GPSHAL_STATE_STOP);
+        }
+    }
+}
+
+void gpshal2mnl_gps_cleanup() {
+    if (GPSHAL_STATE_RESOURCE <= g_gpshal_ctx.gps_state) {
+        if (hal2mnl_gps_cleanup() > 0) {
+            gpshal_set_gps_state(GPSHAL_STATE_CLEANUP);
+        }
+    }
+}
diff --git a/src/connectivity/gps/gps_hal/src/gpshal_worker.c b/src/connectivity/gps/gps_hal/src/gpshal_worker.c
new file mode 100644
index 0000000..e4012e5
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/gpshal_worker.c
@@ -0,0 +1,476 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include <sys/epoll.h>  // epoll_create, epoll_event
+#include <errno.h>     // errno
+#include <string.h>    // strerror
+// #include <linux/in.h>   // INADDR_NONE
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gpshal_worker"
+#endif
+
+//=========================================================
+
+#define GPSHAL_WORKER_THREAD_TIMEOUT (30*1000)
+
+#define fieldp_copy(dst, src, f)  (dst)->f  = (src)->f
+#define field_copy(dst, src, f)  (dst).f   = (src).f
+
+DebugData mnlDebugData; //for GNSS HIDL v1.1 GPS debug interface
+
+//=========================================================
+
+static void update_mnld_reboot() {
+// GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+    gpshal_state state = g_gpshal_ctx.gps_state_intent;
+    LOGD("state: (%d)", state);
+    switch (state) {
+        case GPSHAL_STATE_INIT:
+        case GPSHAL_STATE_STOP:
+            gpshal2mnl_gps_init();
+            break;
+        case GPSHAL_STATE_START:
+            gpshal2mnl_gps_init();
+            gpshal2mnl_gps_start();
+            break;
+        case GPSHAL_STATE_CLEANUP:
+        default:
+            LOGW("Current gps_state_intent: %s (%d)",
+                gpshal_state_to_string(state), state);
+    }
+}
+static void update_location(gps_location location) {
+    // Use mutex or not ?
+    //     If no, the issue may occur.
+    //     If yes, there will be a little performance impact.
+  //  GPSHAL_DEBUG_FUNC_SCOPE;
+    GpsLocation_ext loc;
+    //dump_gps_location(location);
+    gpshal_state state = g_gpshal_ctx.gps_state;
+    //LOGD("state: (%d)", state);
+    if (GPSHAL_STATE_START == state) {
+         loc.legacyLocation.size      = sizeof(loc);
+         loc.legacyLocation.flags     = location.flags;
+         loc.legacyLocation.latitude  = location.lat;
+         loc.legacyLocation.longitude = location.lng;
+         loc.legacyLocation.altitude  = location.alt;
+         loc.legacyLocation.speed     = location.speed;
+         loc.legacyLocation.bearing   = location.bearing;
+         loc.legacyLocation.accuracy  = loc.horizontalAccuracyMeters = location.h_accuracy;
+         loc.verticalAccuracyMeters       = location.v_accuracy;
+         loc.speedAccuracyMetersPerSecond = location.s_accuracy;
+         loc.bearingAccuracyDegrees       = location.b_accuracy;
+         loc.legacyLocation.timestamp = location.timestamp;
+         LOGD("hacc=%f,vacc=%f,sacc=%f,bacc=%f", loc.horizontalAccuracyMeters, loc.verticalAccuracyMeters,
+             loc.speedAccuracyMetersPerSecond, loc.bearingAccuracyDegrees);
+         g_gpshal_ctx.gps_cbs->location_cb(&loc);
+         //For GNSS HIDL v1.1 Gps debug interface
+         mnlDebugData.position.valid = true;
+         mnlDebugData.position.latitudeDegrees   = location.lat;
+         mnlDebugData.position.longitudeDegrees  = location.lng;
+         mnlDebugData.position.altitudeMeters    = location.alt;
+         mnlDebugData.position.speedMetersPerSec = location.speed;
+         mnlDebugData.position.bearingDegrees    = location.bearing;
+         mnlDebugData.position.horizontalAccuracyMeters     = location.h_accuracy;
+         mnlDebugData.position.verticalAccuracyMeters       = location.v_accuracy;
+         mnlDebugData.position.speedAccuracyMetersPerSecond = location.s_accuracy;
+         mnlDebugData.position.bearingAccuracyDegrees       = location.b_accuracy;
+    } else {
+        // Do not report this location to GLP to avoid strange TTFF time issue
+        LOGW("we have a location when gps_state_intent: %s (%d)",
+                gpshal_state_to_string(state), state);
+    }
+}
+static void update_gps_status(gps_status status) {
+    GpsStatus s;
+    LOGD("  status=%d", status);
+    s.size   = sizeof(s);
+    s.status = status;
+    g_gpshal_ctx.gps_cbs->status_cb(&s);
+}
+
+static void update_gps_sv(gnss_sv_info sv) {
+
+   // GPSHAL_DEBUG_FUNC_SCOPE;
+    int i;
+    GnssSvStatus_ext gss;
+    //dump_gnss_sv_info(sv);
+    gss.size = sizeof(gss);
+    gss.num_svs = sv.num_svs;
+    if (gss.num_svs > GNSS_MAX_SVS) {
+        gss.num_svs = GNSS_MAX_SVS;
+    }
+    for (i = 0; i < gss.num_svs; i++) {
+        GnssSvInfo* dst = &gss.gnss_sv_list[i].legacySvInfo;
+        gnss_sv*    src = &sv.sv_list[i];
+        dst->size = sizeof(*dst);
+        fieldp_copy(dst, src, svid);
+        fieldp_copy(dst, src, constellation);
+        fieldp_copy(dst, src, c_n0_dbhz);
+        fieldp_copy(dst, src, elevation);
+        fieldp_copy(dst, src, azimuth);
+        fieldp_copy(dst, src, flags);
+        fieldp_copy(&gss.gnss_sv_list[i], src, carrier_frequency);
+        mnlDebugData.satelliteDataArray[i].svid = gss.gnss_sv_list[i].legacySvInfo.svid;
+        mnlDebugData.satelliteDataArray[i].constellation = gss.gnss_sv_list[i].legacySvInfo.constellation;
+    }
+    g_gpshal_ctx.gps_cbs->gnss_sv_status_cb(&gss);
+}
+
+static void update_nmea(int64_t timestamp, const char* nmea, int length) {
+    /*LOGD("  timestamp=%lld nmea=[%s] length=%d",
+        timestamp, nmea, length);*/
+    g_gpshal_ctx.gps_cbs->nmea_cb(timestamp, nmea, length);
+}
+static void update_gps_capabilities(gps_capabilites capabilities) {
+    LOGD("  capabilities=0x%x", capabilities);
+    g_gpshal_ctx.gps_cbs->set_capabilities_cb(capabilities);
+}
+
+static void update_gps_measurements(gps_data data) {
+   // GPSHAL_DEBUG_FUNC_SCOPE;
+    size_t i;
+    GpsData gd;
+    //dump_gps_data(data);
+    gd.size = sizeof(gd);
+    field_copy(gd, data, measurement_count);
+    for (i = 0; i < GPS_MAX_MEASUREMENT; i++) {
+        GpsMeasurement*  dst = &gd.measurements[i];
+        gps_measurement* src = &data.measurements[i];
+        dst->size  = sizeof(*dst);
+        fieldp_copy(dst, src, flags);
+        fieldp_copy(dst, src, prn);
+        fieldp_copy(dst, src, time_offset_ns);
+        fieldp_copy(dst, src, state);
+        fieldp_copy(dst, src, received_gps_tow_ns);
+        fieldp_copy(dst, src, received_gps_tow_uncertainty_ns);
+        fieldp_copy(dst, src, c_n0_dbhz);
+        fieldp_copy(dst, src, pseudorange_rate_mps);
+        fieldp_copy(dst, src, pseudorange_rate_uncertainty_mps);
+        fieldp_copy(dst, src, accumulated_delta_range_state);
+        fieldp_copy(dst, src, accumulated_delta_range_m);
+        fieldp_copy(dst, src, accumulated_delta_range_uncertainty_m);
+        fieldp_copy(dst, src, pseudorange_m);
+        fieldp_copy(dst, src, pseudorange_uncertainty_m);
+        fieldp_copy(dst, src, code_phase_chips);
+        fieldp_copy(dst, src, code_phase_uncertainty_chips);
+        fieldp_copy(dst, src, carrier_frequency_hz);
+        fieldp_copy(dst, src, carrier_cycles);
+        fieldp_copy(dst, src, carrier_phase);
+        fieldp_copy(dst, src, carrier_phase_uncertainty);
+        fieldp_copy(dst, src, loss_of_lock);
+        fieldp_copy(dst, src, bit_number);
+        fieldp_copy(dst, src, time_from_last_bit_ms);
+        fieldp_copy(dst, src, doppler_shift_hz);
+        fieldp_copy(dst, src, doppler_shift_uncertainty_hz);
+        fieldp_copy(dst, src, multipath_indicator);
+        fieldp_copy(dst, src, snr_db);
+        fieldp_copy(dst, src, elevation_deg);
+        fieldp_copy(dst, src, elevation_uncertainty_deg);
+        fieldp_copy(dst, src, azimuth_deg);
+        fieldp_copy(dst, src, azimuth_uncertainty_deg);
+        fieldp_copy(dst, src, used_in_fix);
+    }
+
+    // To do things like field_copy(gd, data, clock)
+    {
+        GpsClock*  dst = &gd.clock;
+        gps_clock* src = &data.clock;
+        dst->size = sizeof(*dst);
+        fieldp_copy(dst, src, flags);
+        fieldp_copy(dst, src, leap_second);
+        fieldp_copy(dst, src, type);
+        fieldp_copy(dst, src, time_ns);
+        fieldp_copy(dst, src, time_uncertainty_ns);
+        fieldp_copy(dst, src, full_bias_ns);
+        fieldp_copy(dst, src, bias_ns);
+        fieldp_copy(dst, src, bias_uncertainty_ns);
+        fieldp_copy(dst, src, drift_nsps);
+        fieldp_copy(dst, src, drift_uncertainty_nsps);
+    }
+    g_gpshal_ctx.meas_cbs->measurement_callback(&gd);
+}
+
+static void update_gnss_measurements(gnss_data data) {
+    size_t i;
+    GnssData_ext gd;
+    //dump_gnss_data(data);
+    gd.size = sizeof(gd);
+    field_copy(gd, data, measurement_count);
+    for (i = 0; i < MTK_HAL_GNSS_MAX_MEASUREMENT; i++) {
+        GnssMeasurement*  dst = &gd.measurements[i].legacyMeasurement;
+        gnss_measurement*  src = &data.measurements[i];
+        dst->size  = sizeof(*dst);
+        fieldp_copy(dst, src, flags);
+        fieldp_copy(dst, src, svid);
+        fieldp_copy(dst, src, constellation);
+        fieldp_copy(dst, src, time_offset_ns);
+        fieldp_copy(dst, src, state);
+        fieldp_copy(dst, src, received_sv_time_in_ns);
+        fieldp_copy(dst, src, received_sv_time_uncertainty_in_ns);
+        fieldp_copy(dst, src, c_n0_dbhz);
+        fieldp_copy(dst, src, pseudorange_rate_mps);
+        fieldp_copy(dst, src, pseudorange_rate_uncertainty_mps);
+        fieldp_copy(dst, src, accumulated_delta_range_state);
+        fieldp_copy(dst, src, accumulated_delta_range_m);
+        fieldp_copy(dst, src, accumulated_delta_range_uncertainty_m);
+        fieldp_copy(dst, src, carrier_frequency_hz);
+        fieldp_copy(dst, src, carrier_cycles);
+        fieldp_copy(dst, src, carrier_phase);
+        fieldp_copy(dst, src, carrier_phase_uncertainty);
+        fieldp_copy(dst, src, multipath_indicator);
+        fieldp_copy(dst, src, snr_db);
+        fieldp_copy(&gd.measurements[i], src, agc_level_db);
+    }
+    // To do things like field_copy(gd, data, clock)
+    {
+        GnssClock*  dst = &gd.clock;
+        gnss_clock* src = &data.clock;
+        dst->size = sizeof(*dst);
+        fieldp_copy(dst, src, flags);
+        fieldp_copy(dst, src, leap_second);
+        fieldp_copy(dst, src, time_ns);
+        fieldp_copy(dst, src, time_uncertainty_ns);
+        fieldp_copy(dst, src, full_bias_ns);
+        fieldp_copy(dst, src, bias_ns);
+        fieldp_copy(dst, src, bias_uncertainty_ns);
+        fieldp_copy(dst, src, drift_nsps);
+        fieldp_copy(dst, src, drift_uncertainty_nsps);
+        fieldp_copy(dst, src, hw_clock_discontinuity_count);
+    }
+
+    g_gpshal_ctx.meas_cbs->gnss_measurement_callback(&gd);
+}
+static void update_gps_navigation(gps_nav_msg msg) {
+  //  GPSHAL_DEBUG_FUNC_SCOPE;
+    GpsNavigationMessage gnm;
+    //dump_gps_nav_msg(msg);
+    gnm.size = sizeof(gnm);
+    field_copy(gnm, msg, prn);
+    field_copy(gnm, msg, type);
+    field_copy(gnm, msg, status);
+    field_copy(gnm, msg, message_id);
+    field_copy(gnm, msg, submessage_id);
+    field_copy(gnm, msg, data_length);
+    gnm.data = (uint8_t*) msg.data;
+    g_gpshal_ctx.navimsg_cbs->navigation_message_callback(&gnm);
+}
+
+static void update_gnss_navigation(gnss_nav_msg msg) {
+    GnssNavigationMessage gnm;
+    //dump_gnss_nav_msg(msg);
+    gnm.size = sizeof(gnm);
+    field_copy(gnm, msg, svid);
+    field_copy(gnm, msg, type);
+    field_copy(gnm, msg, status);
+    field_copy(gnm, msg, message_id);
+    field_copy(gnm, msg, submessage_id);
+    field_copy(gnm, msg, data_length);
+    gnm.data = (uint8_t*) msg.data;
+    g_gpshal_ctx.navimsg_cbs->gnss_navigation_message_callback(&gnm);
+}
+
+static void request_wakelock() {
+   // GPSHAL_DEBUG_FUNC_SCOPE;
+    g_gpshal_ctx.gps_cbs->acquire_wakelock_cb();
+}
+static void release_wakelock() {
+   // GPSHAL_DEBUG_FUNC_SCOPE;
+    g_gpshal_ctx.gps_cbs->release_wakelock_cb();
+}
+static void request_utc_time() {
+   // GPSHAL_DEBUG_FUNC_SCOPE;
+    g_gpshal_ctx.gps_cbs->request_utc_time_cb();
+}
+static void request_data_conn(struct sockaddr_storage* addr) {
+  //  GPSHAL_DEBUG_FUNC_SCOPE;
+    UNUSED(addr);
+    AGpsStatus as;
+    as.size   = sizeof(AGpsStatus);  // our imp supports v3
+    as.type   = AGPS_TYPE_SUPL;
+    as.status = GPS_REQUEST_AGPS_DATA_CONN;
+    // as.ipaddr = INADDR_NONE; // not used in v3
+    as.addr   = *addr;
+    g_gpshal_ctx.agps_cbs->status_cb(&as);
+}
+static void release_data_conn() {
+    // GPSHAL_DEBUG_FUNC_SCOPE;
+    AGpsStatus as;
+    as.size   = sizeof(AGpsStatus_v1);  // use v1 size to omit optional fields
+    as.type   = AGPS_TYPE_SUPL;
+    as.status = GPS_RELEASE_AGPS_DATA_CONN;
+    g_gpshal_ctx.agps_cbs->status_cb(&as);
+}
+static void request_ni_notify(int session_id, agps_notify_type type, const char* requestor_id,
+        const char* client_name, ni_encoding_type requestor_id_encoding,
+        ni_encoding_type client_name_encoding) {
+    /*LOGD("  session_id=%d type=%d requestor_id=[%s] client_name=[%s] requestor_id_encoding=%d client_name_encoding=%d",
+        session_id, type, requestor_id, client_name, requestor_id_encoding, client_name_encoding);*/
+    GpsNiNotification gnn;
+    gnn.size = sizeof(gnn);
+    gnn.notification_id = session_id;
+    gnn.ni_type = GPS_NI_TYPE_UMTS_SUPL;
+    switch (type) {
+        case AGPS_NOTIFY_TYPE_NOTIFY_ONLY:
+            gnn.notify_flags = GPS_NI_NEED_NOTIFY;
+            break;
+        case AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER:
+            gnn.notify_flags = GPS_NI_NEED_NOTIFY|GPS_NI_NEED_VERIFY;
+            break;
+        case AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER:
+            gnn.notify_flags = GPS_NI_NEED_NOTIFY|GPS_NI_NEED_VERIFY;
+            break;
+        case AGPS_NOTIFY_TYPE_PRIVACY:
+            gnn.notify_flags = GPS_NI_PRIVACY_OVERRIDE;
+            break;
+        default:
+            gnn.notify_flags = 0;
+    }
+    gnn.timeout          = 8;
+    gnn.default_response = GPS_NI_RESPONSE_NORESP;
+    MNLD_STRNCPY(gnn.requestor_id, requestor_id,sizeof(gnn.requestor_id));
+    MNLD_STRNCPY(gnn.text,client_name,sizeof(gnn.text));
+    gnn.requestor_id_encoding = requestor_id_encoding;
+    gnn.text_encoding         = client_name_encoding;
+    gnn.extras[0] = 0;  // be an empty string ""
+    g_gpshal_ctx.gpsni_cbs->notify_cb(&gnn);
+}
+static void request_set_id(request_setid flags) {
+    //LOGD("  flags=0x%x", flags);
+    if (g_gpshal_ctx.agpsril_cbs) {
+        g_gpshal_ctx.agpsril_cbs->request_setid(flags);
+    }
+}
+static void request_ref_loc(request_refloc flags) {
+    //LOGD("  flags=0x%x", flags);
+    if (g_gpshal_ctx.agpsril_cbs) {
+        g_gpshal_ctx.agpsril_cbs->request_refloc(flags);
+    }
+}
+static void output_vzw_debug(const char* str) {
+    int len;
+    len = strlen(str)+1;
+    if (len > VZW_DEBUG_STRING_MAXLEN) {
+        len = VZW_DEBUG_STRING_MAXLEN;
+    }
+    LOGD("len=%d str=%s", len, str);
+    VzwDebugData vzwdebugdata;
+    vzwdebugdata.size = sizeof(VzwDebugData);
+    memcpy(vzwdebugdata.vzw_msg_data, str, len);
+    vzwdebugdata.vzw_msg_data[VZW_DEBUG_STRING_MAXLEN - 1] = 0;
+
+    if (g_gpshal_ctx.vzw_debug_cbs) {
+        g_gpshal_ctx.vzw_debug_cbs->vzw_debug_cb(&vzwdebugdata);
+    }
+}
+
+static void update_gnss_name(const char* name, int length) {
+    LOGD("length=%d, name=%s", length, name);
+    if (g_gpshal_ctx.gps_cbs) {
+        g_gpshal_ctx.gps_cbs->set_name_cb(name, length);
+    }
+}
+
+static void request_nlp(bool independentFromGnss) {
+    LOGD("request nlp[%d]", independentFromGnss);
+    if (g_gpshal_ctx.gps_cbs) {
+        g_gpshal_ctx.gps_cbs->request_location_cb(independentFromGnss);
+    }
+}
+
+static mnl2hal_interface gpshal_mnl2hal_interface = {
+    update_mnld_reboot,
+    update_location,
+    update_gps_status,
+    update_gps_sv,
+    update_nmea,
+    update_gps_capabilities,
+    update_gps_measurements,
+    update_gps_navigation,
+    update_gnss_measurements,
+    update_gnss_navigation,
+    request_wakelock,
+    release_wakelock,
+    request_utc_time,
+    request_data_conn,
+    release_data_conn,
+    request_ni_notify,
+    request_set_id,
+    request_ref_loc,
+    output_vzw_debug,
+    update_gnss_name,
+    request_nlp,
+};
+
+//=========================================================
+
+void gpshal_worker_thread(void *arg) {
+   // GPSHAL_DEBUG_FUNC_SCOPE;
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    UNUSED(arg);
+
+    while (true) {
+        int i;
+        int n;
+
+        n = epoll_wait(g_gpshal_ctx.fd_worker_epoll, events, MAX_EPOLL_EVENT, -1);
+
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("epoll_wait failure reason=[%s]%d", strerror(errno), errno);
+                return;
+            }
+        }
+
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_gpshal_ctx.fd_mnl2hal) {
+                if (events[i].events & EPOLLIN) {
+                    mnl2hal_hdlr(g_gpshal_ctx.fd_mnl2hal,
+                            &gpshal_mnl2hal_interface);
+                }
+            } else {
+                LOGE("%s() unknown fd=%d",
+                        __func__, events[i].data.fd);
+            }
+        }
+    }  // of while (true)
+}
diff --git a/src/connectivity/gps/gps_hal/src/gpsinf.c b/src/connectivity/gps/gps_hal/src/gpsinf.c
new file mode 100644
index 0000000..b8cb228
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/gpsinf.c
@@ -0,0 +1,395 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include "gpshal.h"
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "gpshal_param_check.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gpsinf"
+#endif
+
+extern DebugData mnlDebugData; //for GNSS HIDL v1.1 GPS debug interface
+
+//=========================================================
+
+extern struct hw_module_t HAL_MODULE_INFO_SYM;
+
+//=========================================================
+// Gps Measurement Interface
+
+// Thread: BackgroundThread
+//      GpsMeasurementsProvider uses GpsLocationProvider's handler
+static int measinf_init(GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking) {
+    g_gpshal_ctx.meas_cbs = callbacks;
+    int ret = hal2mnl_set_gps_measurement(true, enableFullTracking);
+    return (ret > 0)?
+            GPS_GEOFENCE_OPERATION_SUCCESS :
+            GPS_GEOFENCE_ERROR_GENERIC;
+}
+
+// Thread: BackgroundThread
+//      GpsMeasurementsProvider uses GpsLocationProvider's handler
+static void measinf_close(void) {
+    hal2mnl_set_gps_measurement(false, false);
+}
+
+const GpsMeasurementInterface_ext mtk_gps_meas_inf = {
+    sizeof(GpsMeasurementInterface_ext),
+    measinf_init,
+    measinf_close
+};
+
+//=========================================================
+// Gps Navigation Message Interface
+
+// Thread: BackgroundThread
+// GpsNavigationMessageProvider uses GpsLocationProvider's handler
+static int navimsginf_init(GpsNavigationMessageCallbacks* callbacks) {
+    g_gpshal_ctx.navimsg_cbs = callbacks;
+    int ret = hal2mnl_set_gps_navigation(true);
+    return (ret > 0)?
+            GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS :
+            GPS_NAVIGATION_MESSAGE_ERROR_GENERIC;
+}
+
+// Thread: BackgroundThread
+//      GpsNavigationMessageProvider uses GpsLocationProvider's handler
+static void navimsginf_close(void) {
+    hal2mnl_set_gps_navigation(false);
+}
+
+const GpsNavigationMessageInterface mtk_navi_msg_inf = {
+    sizeof(GpsNavigationMessageInterface),
+    navimsginf_init,
+    navimsginf_close
+};
+
+static int vzwdebuginf_init(VzwDebugCallbacks* callbacks) {
+    g_gpshal_ctx.vzw_debug_cbs = callbacks;
+    return 0;
+}
+
+static void vzwdebuginf_set(bool enabled) {
+    hal2mnl_set_vzw_debug(enabled);
+}
+
+const VzwDebugInterface mtk_vzw_debug_inf = {
+    sizeof(VzwDebugInterface),
+    vzwdebuginf_init,
+    vzwdebuginf_set
+};
+
+static void gnss_configuration_update(const char* config_data, int32_t length) {
+    hal2mnl_update_gnss_config(config_data, length);
+}
+
+static void gnss_setBlacklist(long long* blacklist, int32_t size) {
+    //hal2mnl_setBlacklist(blacklist, size);
+    UNUSED(blacklist);
+    UNUSED(size);
+}
+
+const GnssConfigurationInterface_ext mtk_gnss_config_inf = {
+    sizeof(GnssConfigurationInterface_ext),
+    gnss_configuration_update,
+    gnss_setBlacklist
+};
+
+static bool get_internal_state(DebugData* debugData) {
+    memcpy(debugData, &mnlDebugData, sizeof(DebugData));
+    return true;
+}
+
+const GpsDebugInterface_ext mtk_gps_debug_inf = {
+    sizeof(GpsDebugInterface_ext),
+    get_internal_state
+};
+
+//=========================================================
+// Implementation of
+//     Gps Iterface
+
+// Thread: Main thread of system server
+// Call seq:
+//     LocationManagerService.systemRunning
+//     LocationManagerService.loadProvidersLocked
+//     GpsLocationProvider.static
+//     android_location_GpsLocationProvider_class_init_native
+//     sGpsInterface->get_extension
+static const void* gpsinf_get_extension(const char* name) {
+#ifndef CONFIG_GPS_MT3303
+    if (strcmp(name, AGPS_INTERFACE) == 0) {
+        return &mtk_agps_inf;
+    }
+    if (strcmp(name, GPS_NI_INTERFACE) == 0) {
+        return &mtk_gps_ni_inf;
+    }
+    if (strcmp(name, AGPS_RIL_INTERFACE) == 0) {
+        return &mtk_agps_ril_inf;
+    }
+#endif
+    if (strcmp(name, GPS_MEASUREMENT_INTERFACE) == 0) {
+       return &mtk_gps_meas_inf;
+    }
+    if (strcmp(name, GPS_NAVIGATION_MESSAGE_INTERFACE) == 0) {
+       return &mtk_navi_msg_inf;
+    }
+
+    if (strcmp(name, VZW_DEBUG_INTERFACE) == 0) {
+       return &mtk_vzw_debug_inf;
+    }
+
+#if 0
+    if (strcmp(name, GPS_GEOFENCING_INTERFACE) == 0) {
+       return &mtkGeofence_inf;
+    }
+#endif
+
+#if 0  // not supported, even in our MP branches
+    if (!strcmp(name, GPS_GEOFENCING_INTERFACE))
+        return &mtk_gps_geofencing_inf;
+#endif
+
+    if (!strcmp(name, GNSS_CONFIGURATION_INTERFACE))
+        return &mtk_gnss_config_inf;
+
+#if 0  // not ready, even in Google's GPS JNI
+    if (strcmp(name, SUPL_CERTIFICATE_INTERFACE) == 0) {
+       return &mtk_supl_cert_inf;
+    }
+#endif
+#if 0  // Similar to our EPO but we will do it in mnld.
+    if (!strcmp(name, GPS_XTRA_INTERFACE))
+        return &mtk_gps_xtra_inf;
+#endif
+    if (!strcmp(name, GPS_DEBUG_INTERFACE)) {
+        return &mtk_gps_debug_inf;
+    }
+    return NULL;  // unsupported extension
+}
+
+// Thread: BackgroundThread
+//     Its looper is shared by a lot of services including
+//         LocationManagerService's handler
+//         GpsLocationProvider's handler
+//         GpsLocationProvider's broadcast receiver
+// Call seq:
+//     GpsLocationProvider.ProviderHandler.handleMessage
+//     GpsLocationProvider.handleEnable
+//     GpsLocationProvider.native_init
+//     android_location_GpsLocationProvider_init
+//     sGpsInterface->init
+static int gpsinf_init(GpsCallbacks_ext* callbacks) {
+    // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+    if (gpshal_gpscbs_save(callbacks) != 0) {
+        return -1;    //  error
+    }
+
+    gpshal_set_gps_state_intent(GPSHAL_STATE_INIT);
+    gpshal2mnl_gps_init();
+    return 0;  // OK to init
+}
+
+// Thread: BackgroundThread
+static int gpsinf_start(void) {
+    // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+    gpshal_set_gps_state_intent(GPSHAL_STATE_START);
+    gpshal2mnl_gps_start();
+    return 0;  // OK to start
+}
+
+// Thread: BackgroundThread
+static int gpsinf_stop(void) {
+    // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+    gpshal_set_gps_state_intent(GPSHAL_STATE_STOP);
+    gpshal2mnl_gps_stop();
+    return 0;  // OK to stop
+}
+
+// Thread: BackgroundThread
+static void gpsinf_cleanup(void) {
+    // GPSHAL_DEBUG_FUNC_SCOPE2(g_gpshal_ctx.mutex_gps_state_intent);
+    gpshal_set_gps_state_intent(GPSHAL_STATE_CLEANUP);
+    gpshal2mnl_gps_cleanup();
+}
+
+// Thread: BackgroundThread
+static int gpsinf_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty) {
+    hal2mnl_gps_inject_time(time, timeReference, uncertainty);
+    return 0;  // 0:ok,   non-zero: error; but GPS JNI will ignore it
+}
+
+// Thread: BackgroundThread
+//     NetworkLocationListener uses the looper of GpsLocationProvider's handler
+static int gpsinf_inject_location(
+        double latitude,
+        double longitude,
+        float  accuracy) {
+    hal2mnl_gps_inject_location(latitude, longitude, accuracy);
+    return 0;  // 0:ok,   non-zero: error; but GPS JNI will ignore it
+}
+
+// Thread: Binder Thread of LocationManagerService
+//
+// Call seq:
+//     LocationManagerService.sendExtraCommand
+//     GpsLocationProvider.sendExtraCommand
+//     GpsLocationProvider.deleteAidingData
+//     GpsLocationProvider.native_delete_aiding_data
+//     android_location_GpsLocationProvider_delete_aiding_data
+//     sGpsInterface->delete_aiding_data
+static void gpsinf_delete_aiding_data(GpsAidingData flags) {
+    hal2mnl_gps_delete_aiding_data(flags);
+}
+
+// Thread: BackgroundThread or ???
+//     GpsLocationProvider's handler may call it
+//     GpsLocationProvider's mBroadcastReceiver may call it (PowerManager's intent)
+static int gpsinf_set_position_mode(
+        GpsPositionMode mode,
+        GpsPositionRecurrence recurrence,
+        uint32_t min_interval,
+        uint32_t preferred_accuracy,
+        uint32_t preferred_time,
+        bool lowPowerMode) {
+    hal2mnl_gps_set_position_mode(
+            mode,
+            recurrence,
+            min_interval,
+            preferred_accuracy,
+            preferred_time,
+            lowPowerMode);
+    return 0;  // 0:ok,   non-zero: error; GLP will show log if error
+}
+
+static int gpsinf_inject_fused_location(
+        double latitude,
+        double longitude,
+        float  accuracy) {
+    // TODO:  hal2mnl_gps_inject_fused_location(latitude, longitude, accuracy);
+    UNUSED(latitude);
+    UNUSED(longitude);
+    UNUSED(accuracy);
+    return 0;  // 0:ok,   non-zero: error; but GPS JNI will ignore it
+}
+
+static const GpsInterface_ext  mtk_gps_inf = {
+    sizeof(GpsInterface_ext),
+    gpsinf_init,
+    gpsinf_start,
+    gpsinf_stop,
+    gpsinf_cleanup,
+    gpsinf_inject_time,
+    gpsinf_inject_location,
+    gpsinf_delete_aiding_data,
+    gpsinf_set_position_mode,
+    gpsinf_get_extension,
+    gpsinf_inject_fused_location,
+};
+
+#ifdef __ANDROID_OS__
+//=========================================================
+// Between
+//     Gps Interface
+//     Hardware Module Interface
+
+static const GpsInterface_ext* gps_device__get_gps_interface(
+        __unused struct gps_device_t_ext* device) {
+    GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM;
+    hal2mnl_hal_reboot();
+    return &mtk_gps_inf;
+}
+
+static const struct gps_device_t_ext gps_device = {
+    .common = {                           // hw_device_t
+        .tag     = HARDWARE_DEVICE_TAG,
+        .version = 0,                     // GPS JNI will not use it
+        .module  = &HAL_MODULE_INFO_SYM,
+        .reserved = {0},
+        .close   = NULL                   // GPS JNI will not call it
+        },
+    .get_gps_interface = gps_device__get_gps_interface
+};
+
+//=========================================================
+// Implementation of
+//     Hardware Module Interface
+
+static int gps_hw_module_open(
+        __unused const struct hw_module_t* module,
+        __unused char const* id,
+        struct hw_device_t** device) {
+    GPS_HW_MODULE_OPEN__CHECK_PARAM;
+    *device = (struct hw_device_t*)&gps_device;
+    return 0;  // OK: refer to the cpp of GPS JNI
+}
+
+static struct hw_module_methods_t gps_hw_module_methods = {
+    .open = gps_hw_module_open
+};
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 1,
+    .version_minor = 0,
+    .id  = GPS_HARDWARE_MODULE_ID,
+    .name   = "MediaTek GPS Hardware Module",
+    .author = "MediaTek, Inc.",
+    .methods = &gps_hw_module_methods,
+    .dso     = NULL,
+    .reserved = {0}
+};
+#else
+//=========================================================
+// Between
+//     Gps Interface
+//     Hardware Module Interface
+
+const GpsInterface_ext* gps_device__get_gps_interface(struct gps_device_t_ext* device) 
+{
+    LOGD("welcome enter libgpshal world\n");
+    hal2mnl_hal_reboot();
+
+    return &mtk_gps_inf;
+}
+
+const struct gps_device_t_ext linux_gps_device = {
+    .get_gps_interface = gps_device__get_gps_interface
+};
+
+#endif //__ANDROID_OS__
diff --git a/src/connectivity/gps/gps_hal/src/gpsinf3337.c b/src/connectivity/gps/gps_hal/src/gpsinf3337.c
new file mode 100644
index 0000000..d59291c
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/gpsinf3337.c
@@ -0,0 +1,2290 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include <errno.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <math.h>
+#include <time.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <semaphore.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <linux/mtk_agps_common.h>
+#include <cutils/android_filesystem_config.h>
+
+#include "hardware/gps_mtk.h"
+#include "gpshal.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include <termios.h>
+#include "mtk_auto_log.h"
+
+#define LOCATION_NLP_FIX MTK_GPS_DATA_PATH"LOCATION.DAT"
+#define  LOG_TAG  "gps_mtk_3337"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+#endif
+
+
+
+/* the name of the controlled socket */
+#define  GPS_POWER_NAME       "/dev/gps"
+#define  GPS_TTY_NAME       "/dev/ttyMT1"
+
+#define  MNLD_HAL2GPS       "/dev/mt3337_gpsonly"
+#define MNL_CONFIG_STATUS   "persist.vendor.radio.mnl.prop"
+
+#define PMTK_SOCKET_COM_PORT 49995
+#define PMTK_SERVER_BACKLOG 5
+#define INVALID_SOCKET -1
+#define INVALID_FD -1
+#define  GPS_OP   "AT%GPS"
+#define  GNSS_OP  "AT%GNSS"
+#define  GPS_AT_ACK_SIZE        60
+
+#define MTKEPO_SV_NUMBER 32
+#define MTKEPO_RECORD_SIZE 72
+#define MTKEPO_SEGMENT_NUM (30 * 4)
+
+#define  GPS_DEBUG  1
+#define  NEMA_DEBUG 0   /*the flag works if GPS_DEBUG is defined*/
+#if GPS_DEBUG
+#define  TRC(f)       ALOGD("%s", __func__)
+#define  ERR(f, ...)  ALOGE("%s: line = %d" f, __func__,__LINE__, ##__VA_ARGS__)
+#define  WAN(f, ...)  ALOGW("%s: line = %d" f, __func__, __LINE__,##__VA_ARGS__)
+#define DBG(f, ...) ALOGD("%s: line = %d" f, __func__, __LINE__,##__VA_ARGS__)
+#define VER(f, ...) ((void)0) //((void)0)//
+#else
+#  define DBG(...)    ((void)0)
+#  define VER(...)    ((void)0)
+#endif
+
+#define GPS_POWER_IOCTL _IOW('G', 0, int)
+static int flag_unlock = 0;
+GpsStatus sta;
+
+extern struct hw_module_t HAL_MODULE_INFO_SYM;
+
+typedef  unsigned int             UINT4;
+typedef  signed int               INT4;
+typedef unsigned char           UINT8;
+typedef signed char             INT8;
+typedef unsigned short int      UINT16;
+typedef signed short int        INT16;
+typedef unsigned int            UINT32;
+typedef signed int              INT32;
+typedef signed long long       INT64;
+
+#pragma pack(4) // Align by 4 byte
+typedef struct
+{
+   UINT32 size;
+   UINT16 flag;
+   INT16 leapsecond;
+   UINT8 type;
+   INT64 TimeInNs;
+   double TimeUncertaintyInNs;
+   INT64 FullBiasInNs;
+   double BiasInNs;
+   double BiasUncertaintyInNs;
+   double DriftInNsPerSec;
+   double DriftUncertaintyInNsPerSec;
+}MTK_GPS_CLOCK;
+#pragma pack()
+
+typedef struct{
+    GpsUtcTime time;
+    int64_t timeReference;
+    int uncertainty;
+} ntp_context;
+
+typedef struct{
+    double latitude;
+    double longitude;
+    float accuracy;
+    struct timespec ts;
+    unsigned char  type;
+    unsigned char  started;
+} nlp_context;
+
+/*****************************************************************************/
+/*    MTK device control                                                  */
+/*****************************************************************************/
+enum {
+    MNL_CMD_UNKNOWN = -1,
+    /*command send from GPS HAL*/
+    MNL_CMD_INIT            = 0x00,
+    MNL_CMD_CLEANUP         = 0x01,
+    MNL_CMD_STOP            = 0x02,
+    MNL_CMD_START           = 0x03,
+    MNL_CMD_RESTART         = 0x04,    /*restart MNL process*/
+    MNL_CMD_RESTART_HOT     = 0x05,    /*restart MNL by PMTK command: hot start*/
+    MNL_CMD_RESTART_WARM    = 0x06,    /*restart MNL by PMTK command: warm start*/
+    MNL_CMD_RESTART_COLD    = 0x07,    /*restart MNL by PMTK command: cold start*/
+    MNL_CMD_RESTART_FULL    = 0x08,    /*restart MNL by PMTK command: full start*/
+    MNL_CMD_RESTART_AGPS    = 0x09,    /*restart MNL by PMTK command: AGPS start*/
+    MNL_CMD_GPSMEASUREMENT_INIT = 0x15,
+    MNL_CMD_GPSMEASUREMENT_CLOSE = 0x16,
+
+
+    MNL_CMD_GPSNAVIGATION_INIT = 0x17,
+    MNL_CMD_GPSNAVIGATION_CLOSE = 0x18,
+    MNL_CMD_GPS_LOG_WRITE = 0x40,
+
+    MNL_CMD_ENABLE_AGPS_DEBUG = 0x42,
+    MNL_CMD_DISABLE_AGPS_DEBUG = 0x43,
+};
+
+enum {
+    HAL_CMD_STOP_UNKNOWN = -1,
+    HAL_CMD_MNL_DIE = 0x41,
+    HAL_CMD_GPS_ICON = 0x42,
+
+    MNL_CMD_GPS_INJECT_TIME = 0x46,
+    MNL_CMD_GPS_INJECT_LOCATION = 0x47,
+    MNL_CMD_GPS_INJECT_TIME_REQ = 0x48,
+    MNL_CMD_GPS_INJECT_LOCATION_REQ = 0x49,
+
+    MNL_CMD_GPS_NLP_LOCATION_REQ = 0x4a,
+    HAL_CMD_MEASUREMENT= 0x76,
+    HAL_CMD_NAVIGATION= 0x77,
+    HAL_CMD_SWITCH_AGPS_DEBUG_DONE = 0x44,
+    HAL_CMD_SWITCH_AGPS_DEBUG_FAIL = 0X45,
+};
+
+
+
+#define M_START 0
+#define M_STOP 1
+#define M_CLEANUP 2
+#define M_INIT 3
+#define M_THREAD_EXIT 4
+#define M_MNLDIE 5
+typedef struct sync_lock
+{
+    pthread_mutex_t mutx;
+    pthread_cond_t con;
+    int condtion;
+}SYNC_LOCK_T;
+
+static SYNC_LOCK_T lock_for_sync[] = {{PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+                                    {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+                                    {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+                                    {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+                                    {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0},
+                                    {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER, 0}};
+
+const char* gps_native_thread = "GPS NATIVE THREAD";
+const char* gps_pmtk_thread = "GPS PMTK THREAD";
+const char* gps_nmea_read_thread = "GPS NMEA READ THREAD";
+const char* gps_send_epo_thread = "GPS SEND EPO THREAD";
+static GpsCallbacks callback_backup;
+static int start_flag = 0;
+static int g_delete_aiding_data_flag = 0;
+
+//for different SV parse
+typedef enum{
+    UNKNOWN_SV = 0,
+    GPS_SV,
+    GLONASS_SV,
+    BDS_SV,
+    GALILEO_SV,
+}SV_TYPE;
+static float report_time_interval = 0;
+static int started = 0;
+
+//#define  NMEA_MAX_SIZE  83
+#define  NMEA_MAX_SIZE  255
+/*maximum number of SV information in GPGSV*/
+#define  NMEA_MAX_SV_INFO 4
+#define  LOC_FIXED(pNmeaReader) ((pNmeaReader->fix_mode == 2) || (pNmeaReader->fix_mode ==3))
+typedef struct {
+    int     pos;
+    int     overflow;
+    int     utc_year;
+    int     utc_mon;
+    int     utc_day;
+    int     utc_diff;
+    GpsLocation  fix;
+
+    /*
+     * The fix flag extracted from GPGSA setence: 1: No fix; 2 = 2D; 3 = 3D
+     * if the fix mode is 0, no location will be reported via callback
+     * otherwise, the location will be reported via callback
+     */
+    int     fix_mode;
+    /*
+     * Indicate that the status of callback handling.
+     * The flag is used to report GPS_STATUS_SESSION_BEGIN or GPS_STATUS_SESSION_END:
+     * (0) The flag will be set as true when callback setting is changed via nmea_reader_set_callback
+     * (1) GPS_STATUS_SESSION_BEGIN: receive location fix + flag set + callback is set
+     * (2) GPS_STATUS_SESSION_END:   receive location fix + flag set + callback is null
+     */
+    int     cb_status_changed;
+    int     sv_count;           /*used to count the number of received SV information*/
+    GnssSvStatus  sv_status;
+    GpsCallbacks callbacks;
+    char    in[ NMEA_MAX_SIZE + 1 ];
+} NmeaReader;
+
+typedef struct {
+    pthread_t               thread;
+    int                     server_fd;
+}PMTKThread;
+
+/* this is the state of our connection to the daemon */
+typedef struct {
+    int                     init;  // to check whether, have been initialized
+    int                     pow_fd; //power ctrl
+    int                     tty_fd; //for read nmea
+    GpsCallbacks            callbacks; // up layer callback
+    pthread_t               thread;
+    PMTKThread              pmtk_thread[1];
+    pthread_t               nmea_read_thread;
+    int                     control[2];
+    int                     test_time;
+    int                     epoll_hd;
+    int                     flag;
+    int                     start_flag;
+} GpsState;
+
+static GpsState  _gps_state[1];
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****       C O N N E C T I O N   S T A T E                 *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+
+/* commands sent to the gps thread */
+enum {
+    CMD_QUIT  = 0,
+    CMD_START = 1,
+    CMD_STOP  = 2,
+    CMD_RESTART = 3,
+    CMD_DOWNLOAD = 4,
+
+    CMD_TEST_START = 10,
+    CMD_TEST_STOP = 11,
+    CMD_TEST_SMS_NO_RESULT = 12,
+    CMD_EPO_DOWNLOAD_DONE = 13,
+};
+
+
+static int gps_nmea_end_tag = 0;
+
+int sv_used_in_fix[256] = {0};    // for multiple sv display
+
+unsigned char calc_nmea_checksum( const char* sentence);
+void send_assistance_data (int iYr, int iMo, int iDay, int iHr, char * timeInfo, int iTimeLen);
+
+static void get_condition(SYNC_LOCK_T *lock)
+{
+    int ret = 0;
+
+    ret = pthread_mutex_lock(&(lock->mutx));
+    DBG("ret get_mutex lock = %d\n",ret);
+
+    while (!lock->condtion)
+    {
+        DBG("ret get_cond wait = %d\n" ,ret);
+        ret = pthread_cond_wait(&(lock->con), &(lock->mutx));
+    }
+
+    lock->condtion = 0;
+    DBG("ret get_mutex unlock = %d\n",ret);
+    ret = pthread_mutex_unlock(&(lock->mutx));
+    DBG("test");
+
+    return;
+}
+
+static void release_condition(SYNC_LOCK_T *lock)
+{
+    int ret = 0;
+
+
+    ret = pthread_mutex_lock(&(lock->mutx));
+    DBG("ret release_mutex lock = %d\n",ret);
+
+    lock->condtion= 1;
+    ret = pthread_cond_signal(&(lock->con));
+    DBG ("ret release_cond_signal = %d\n",ret);
+
+    ret = pthread_mutex_unlock(&(lock->mutx));
+    DBG("ret release_unlock= %d\n",ret);
+
+    return;
+}
+
+int mtk_restart(unsigned char cmd)
+{
+    char buf[] = {cmd};
+    TRC();
+    return 0;
+}
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****       N M E A   T O K E N I Z E R                     *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+
+typedef struct {
+    const char*  p;
+    const char*  end;
+} Token;
+
+#define  MAX_NMEA_TOKENS  24
+
+typedef struct {
+    int     count;
+    Token   tokens[ MAX_NMEA_TOKENS ];
+} NmeaTokenizer;
+
+static int
+nmea_tokenizer_init( NmeaTokenizer*  t, const char*  p, const char*  end ) {
+    int    count = 0;
+    char*  q;
+
+    // the initial '$' is optional
+    if (p < end && p[0] == '$')
+        p += 1;
+
+    // remove trailing newline
+    if (end > p && end[-1] == '\n') {
+        end -= 1;
+        if (end > p && end[-1] == '\r')
+            end -= 1;
+    }
+
+    // get rid of checksum at the end of the sentecne
+    if (end >= p+3 && end[-3] == '*') {
+        end -= 3;
+    }
+
+    while (p < end) {
+        const char*  q = p;
+
+        q = memchr(p, ',', end-p);
+        if (q == NULL)
+            q = end;
+
+        if (q >= p) {
+            if (count < MAX_NMEA_TOKENS) {
+                t->tokens[count].p   = p;
+                t->tokens[count].end = q;
+                count += 1;
+            }
+        }
+        if (q < end)
+            q += 1;
+
+        p = q;
+    }
+
+    t->count = count;
+    DBG(" t->count is %d", t->count);
+    return count;
+}
+
+static Token
+nmea_tokenizer_get( NmeaTokenizer*  t, int  index )
+{
+    Token  tok;
+    static const char*  dummy = "";
+
+    if (index < 0 || index >= t->count) {
+        tok.p = tok.end = dummy;
+    } else
+        tok = t->tokens[index];
+
+    return tok;
+}
+
+
+static int
+str2int( const char*  p, const char*  end )
+{
+    int   result = 0;
+    int   len    = end - p;
+    int   sign = 1;
+
+    if (*p == '-')
+    {
+        sign = -1;
+        p++;
+        len = end - p;
+    }
+
+    for ( ; len > 0; len--, p++ )
+    {
+        int  c;
+
+        if (p >= end)
+            goto Fail;
+
+        c = *p - '0';
+        if ((unsigned)c >= 10)
+            goto Fail;
+
+        result = result*10 + c;
+    }
+    return  sign*result;
+
+Fail:
+    return -1;
+}
+
+static double
+str2float( const char*  p, const char*  end )
+{
+    int   result = 0;
+    int   len    = end - p;
+    char  temp[16];
+
+    if (len >= (int)sizeof(temp))
+        return 0.;
+
+    memcpy( temp, p, len );
+    temp[len] = 0;
+    return strtod( temp, NULL );
+}
+
+static void mtk_gps_update_location(nlp_context * location)
+{
+    FILE *fp = NULL;
+
+    fp = fopen(LOCATION_NLP_FIX, "w");
+    if (fp != NULL)
+    {
+        size_t count = 0;
+        count = fwrite(location, sizeof(nlp_context), 1, fp);
+        if (count != 1)
+        {
+            DBG("write count:%d, errno:%s\n", count, strerror(errno));
+        }
+        fclose(fp);
+    }
+}
+
+static bool g_EpoSend = false;
+static void mtk_gps_send_EPO()
+{
+    time_t timep;
+    struct tm* pq;
+    time(&timep);
+    pq = gmtime(&timep);
+    char strBuf[200], outBuf[200];
+    memset(strBuf, 0, sizeof(strBuf));
+    memset(outBuf, 0, sizeof(outBuf));
+    sprintf(strBuf, "PMTK740,%d,%d,%d,%d,%d,%d",pq->tm_year + 1900, pq->tm_mon + 1, pq->tm_mday, pq->tm_hour, pq->tm_min, pq->tm_sec);
+    sprintf(outBuf, "$%s*%02X\r\n", strBuf, calc_nmea_checksum(strBuf));
+    DBG("final PMTK is %s, size is %d, len is %d", outBuf, sizeof(outBuf), strlen(outBuf));
+    send_assistance_data(pq->tm_year + 1900, pq->tm_mon + 1, pq->tm_mday, pq->tm_hour, outBuf, strlen(outBuf));
+}
+
+/*****************************************/
+/*****************************************/
+/*****                                                       *****/
+/*****       PowerGPS PMTK handle                 *****/
+/*****                                                       *****/
+/****************************************/
+/****************************************/
+
+static bool g_ThreadExitPMTKIn = false;//flag for PowerGPS thread exist
+static int g_hPowerGPS = INVALID_FD;//PowerGPS socket handle
+static NmeaReader  g_NmeaReader[1];
+
+/***************Receive From PowerGPS********************/
+void * pmtk_input_func(void * arg)
+{
+    int bytes = 0;
+    int ret = 0;
+    char pmtk_buf[200];
+    char  cmd = CMD_RESTART;
+    GpsState*   state = (GpsState*) arg;
+
+    while(g_ThreadExitPMTKIn)
+    {
+        memset(pmtk_buf, 0, sizeof(pmtk_buf));
+        bytes = read(g_hPowerGPS, pmtk_buf, 200);
+
+        if (bytes > 0)
+        {
+            DBG("!!!!!!!!!! PowerGPS pass : %s, lenth is %d", pmtk_buf, bytes);
+
+            do {
+                ret=write( state->control[0], &cmd, 1);
+            }
+            while (ret < 0 && errno == EINTR);
+            do {
+                ret=write( state->tty_fd, pmtk_buf, bytes);
+            }while (ret < 0 && errno == EINTR);
+            if (ret < 0)
+                DBG("!!!!!!!!!!!PowerGPS write FAIL, errno is %d  (%s)", errno, strerror(errno));
+            else
+                DBG("!!!!!!!!!!!!!!PowerGPS write succeed, ret is %d", ret);
+            if (strstr(pmtk_buf, "PMTK101")
+                || strstr(pmtk_buf, "PMTK102")
+                || strstr(pmtk_buf, "PMTK103")
+                || strstr(pmtk_buf, "PMTK104"))
+            {
+                g_EpoSend = true;
+                DBG("!!!!!!!PowerGPS got A START %s", pmtk_buf);
+            }
+        }
+        else
+        {
+            if (bytes == 0)
+            { //client close
+                DBG("!!!!!!socket client close");
+                break;
+            }
+            else
+            {
+                usleep(200000);  // sleep 200 ms
+                DBG("!!!!!!socket error = %d (%s)\r\n", errno, strerror(errno));
+            }
+        }
+    }
+    return NULL;
+}
+
+/***************Output To PowerGPS********************/
+void pmtk_output_func(char * buf, int * length)
+{
+    if (buf[(*length) - 2] != '\r'){
+        buf[(*length) - 1] = '\r';
+        buf[(*length)] = '\n';
+        (*length) += 1;
+    }
+    int len = (*length);
+    int ret = 0;
+    int written = 0;
+    int retry = 0;
+    if (g_hPowerGPS != INVALID_FD)
+    {
+        while( (written != len) && (retry <5))
+        {
+            ret = write(g_hPowerGPS, buf + written, len - written);
+            if (ret < 0)
+            {
+                retry++;
+            }
+            else
+            {
+                written += ret;
+            }
+        }
+    }
+}
+
+void powergps_thread_exit(int sig_no, int server_fd)
+{
+    if(server_fd != INVALID_SOCKET)
+    {
+        close(server_fd);
+        server_fd == INVALID_SOCKET;
+    }
+    pthread_exit((void *)0);
+}
+
+void signal_action_handle(int signum, siginfo_t * info, void *myact)
+{
+    DBG("######got Signal : %d", signum);
+}
+
+/*
+ *Create Socket Server to listen PMTK from PowerGPS
+ */
+void* powergps_pmtk_receive_thread( void*  arg )
+{
+    TRC();
+    g_ThreadExitPMTKIn = true;
+    GpsState*   state = (GpsState*) arg;
+    int server_fd = state->pmtk_thread->server_fd;
+
+    int conn_fd = INVALID_SOCKET, on;
+    struct sockaddr_in server_addr;
+    struct sockaddr_in client_addr;
+    socklen_t size;
+    int hdlsig = SIGUSR1;
+    struct sigaction sa;
+    char buf[128];
+
+    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+    {
+        DBG("socket error = %d (%s)\r\n", errno, strerror(errno));
+        pthread_exit((void *)0);
+        return NULL;
+    }
+    DBG("########### socket create SUCCESS - pid == %d, fd == %d", getpid(), server_fd);
+
+    /* Enable address reuse */
+    on = 1;
+    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
+    {
+        close(server_fd);
+        pthread_exit((void *)0);
+        return NULL;
+    }
+    DBG("########### socket set SUCCESS");
+
+    server_addr.sin_family = AF_INET;   /*host byte order*/
+    server_addr.sin_port = htons(PMTK_SOCKET_COM_PORT); /*short, network byte order*/
+    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*automatically fill with my IP*/
+    memset(server_addr.sin_zero, 0x00, sizeof(server_addr.sin_zero));
+
+    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
+    {
+        close(server_fd);
+        pthread_exit((void *)0);
+        return NULL;
+    }
+    DBG("########### socket bind SUCCESS");
+
+    if (listen(server_fd, PMTK_SERVER_BACKLOG) == -1)
+    {
+        close(server_fd);
+        pthread_exit((void *)0);
+        return NULL;
+    }
+    DBG("########### socket listen SUCCESS");
+
+    sa.sa_handler = SIG_IGN;
+    sa.sa_sigaction = signal_action_handle;
+    sa.sa_flags = (0 | SA_SIGINFO);
+    sigemptyset(&sa.sa_mask);
+   if (sigaction(SIGPIPE, &sa, NULL) < 0)
+    {
+        DBG("sigaction error \r\n");
+    }
+
+    while (g_ThreadExitPMTKIn)
+    {
+        size = sizeof(client_addr);
+        DBG("########### waiting the client..........");
+        conn_fd = accept(server_fd, (struct sockaddr*)&client_addr, &size);
+        DBG("########### client comes in..........");
+
+        if (conn_fd <= 0)
+        {
+            DBG("######### no client");
+            close(server_fd);
+            break;
+        }
+        else
+        {
+            g_hPowerGPS = conn_fd;
+            pmtk_input_func(state);
+        }
+    }
+    powergps_thread_exit(0, server_fd);//call pthread_exit() in this function, the code after this sentence will not be executed
+    return NULL;
+}
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****       N M E A   P A R S E R                           *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+
+static void
+nmea_reader_update_utc_diff( NmeaReader* const r )
+{
+    time_t         now = time(NULL);
+    struct tm      tm_local;
+    struct tm      tm_utc;
+    unsigned long  time_local, time_utc;
+
+    gmtime_r( &now, &tm_utc );
+    localtime_r( &now, &tm_local );
+
+    time_local = mktime(&tm_local);
+    time_utc = mktime(&tm_utc);
+    r->utc_diff = time_utc - time_local;
+}
+
+
+static void
+nmea_reader_init( NmeaReader* const r )
+{
+    memset( r, 0, sizeof(*r) );
+
+    r->pos      = 0;
+    r->overflow = 0;
+    r->utc_year = -1;
+    r->utc_mon  = -1;
+    r->utc_day  = -1;
+    r->utc_diff = 0;
+    r->callbacks.location_cb= NULL;
+    r->callbacks.status_cb= NULL;
+    r->callbacks.gnss_sv_status_cb= NULL;
+    r->sv_count = 0;
+    r->fix_mode = 0;    /*no fix*/
+    r->cb_status_changed = 0;
+    memset((void*)&r->sv_status, 0x00, sizeof(r->sv_status));
+    memset((void*)&r->in, 0x00, sizeof(r->in));
+
+    nmea_reader_update_utc_diff( r );
+    r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
+    r->fix.accuracy = 10;
+}
+
+static void
+nmea_reader_set_callback( NmeaReader* const r, GpsCallbacks* const cbs)
+{
+    if (!r) {           /*this should not happen*/
+        return;
+    } else if (!cbs) {  /*unregister the callback */
+        return ;
+    } else {/*register the callback*/
+        r->sv_count = r->sv_status.num_svs = 0;
+        r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
+        r->fix.accuracy = 10;
+    }
+}
+
+
+static int
+nmea_reader_update_time( NmeaReader* const r, Token  tok ) {
+    int        hour, minute;
+    double     seconds;
+    struct tm  tm;
+    time_t     fix_time;
+
+    if (tok.p + 6 > tok.end)
+        return -1;
+
+    memset((void*)&tm, 0x00, sizeof(tm));
+    if (r->utc_year < 0) {
+        // no date yet, get current one
+        time_t  now = time(NULL);
+        gmtime_r( &now, &tm );
+        r->utc_year = tm.tm_year + 1900;
+        r->utc_mon  = tm.tm_mon + 1;
+        r->utc_day  = tm.tm_mday;
+    }
+
+    hour    = str2int(tok.p,   tok.p+2);
+    minute  = str2int(tok.p+2, tok.p+4);
+    seconds = str2float(tok.p+4, tok.end);
+
+    tm.tm_hour = hour;
+    tm.tm_min  = minute;
+    tm.tm_sec  = (int) seconds;
+    tm.tm_year = r->utc_year - 1900;
+    tm.tm_mon  = r->utc_mon - 1;
+    tm.tm_mday = r->utc_day;
+    tm.tm_isdst = -1;
+
+    if (mktime(&tm) == (time_t)-1)
+        ERR("mktime error: %d %s\n", errno, strerror(errno));
+
+    nmea_reader_update_utc_diff(r);
+
+    fix_time = mktime(&tm) - r->utc_diff;
+    DBG("fix_time: %d\n",fix_time);
+    r->fix.timestamp = (long long)fix_time * 1000;
+    return 0;
+}
+
+static int
+nmea_reader_update_date( NmeaReader* const r, Token  date, Token  time )
+{
+    Token  tok = date;
+    int    day, mon, year;
+
+    if (tok.p + 6 != tok.end) {
+        ERR("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
+        return -1;
+    }
+    day  = str2int(tok.p, tok.p+2);
+    mon  = str2int(tok.p+2, tok.p+4);
+    year = str2int(tok.p+4, tok.p+6) + 2000;
+
+    if ((day|mon|year) < 0) {
+        ERR("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
+        return -1;
+    }
+
+    r->utc_year  = year;
+    r->utc_mon   = mon;
+    r->utc_day   = day;
+
+    return nmea_reader_update_time( r, time );
+}
+
+
+static double
+convert_from_hhmm( Token  tok )
+{
+    double  val     = str2float(tok.p, tok.end);
+    int     degrees = (int)(floor(val) / 100);
+    double  minutes = val - degrees*100.;
+    double  dcoord  = degrees + minutes / 60.0;
+    return dcoord;
+}
+
+
+static int
+nmea_reader_update_latlong( NmeaReader* const r,
+                            Token        latitude,
+                            char         latitudeHemi,
+                            Token        longitude,
+                            char         longitudeHemi ) {
+    double   lat, lon;
+    Token    tok;
+
+    tok = latitude;
+    if (tok.p + 6 > tok.end) {
+        return -1;
+    }
+    lat = convert_from_hhmm(tok);
+    if (latitudeHemi == 'S')
+        lat = -lat;
+
+    tok = longitude;
+    if (tok.p + 6 > tok.end) {
+        return -1;
+    }
+    lon = convert_from_hhmm(tok);
+    if (longitudeHemi == 'W')
+        lon = -lon;
+
+    r->fix.flags    |= GPS_LOCATION_HAS_LAT_LONG;
+    r->fix.latitude  = lat;
+    r->fix.longitude = lon;
+    return 0;
+}
+
+static int
+nmea_reader_update_altitude( NmeaReader* const r,
+                             Token        altitude,
+                             Token        units ) {
+    double  alt;
+    Token   tok = altitude;
+
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= GPS_LOCATION_HAS_ALTITUDE;
+    r->fix.altitude = str2float(tok.p, tok.end);
+    return 0;
+}
+
+
+static int
+nmea_reader_update_bearing( NmeaReader* const r,
+                            Token        bearing )
+{
+    double  alt;
+    Token   tok = bearing;
+
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= GPS_LOCATION_HAS_BEARING;
+    r->fix.bearing  = str2float(tok.p, tok.end);
+    return 0;
+}
+
+
+static int
+nmea_reader_update_speed( NmeaReader* const r,
+                          Token        speed )
+{
+    double  alt;
+    Token   tok = speed;
+
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= GPS_LOCATION_HAS_SPEED;
+
+    //Modify by ZQH to convert the speed unit from knot to m/s
+    //r->fix.speed    = str2float(tok.p, tok.end);
+    r->fix.speed = str2float(tok.p, tok.end) / 1.942795467;
+    return 0;
+}
+
+//Add by LCH for accuracy
+static int
+nmea_reader_update_accuracy( NmeaReader* const r,
+                             Token accuracy )
+{
+    double  alt;
+    Token   tok = accuracy;
+
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= GPS_LOCATION_HAS_ACCURACY;
+    r->fix.accuracy = str2float(tok.p, tok.end);
+    return 0;
+}
+
+static int
+nmea_reader_update_sv_status( NmeaReader* r, int sv_index,
+                              int id, Token elevation,
+                              Token azimuth, Token snr)
+{
+    //int prn = str2int(id.p, id.end);
+    int prn = id;
+
+    if ((prn <= 0) || (prn < 65 && prn > GPS_MAX_SVS)|| ((prn > 96) && (prn < 200)) || (prn > 232) || (r->sv_count >= GNSS_MAX_SVS)) {
+        VER("sv_status: ignore (%d)", prn);
+        return 0;
+    }
+    sv_index = r->sv_count+r->sv_status.num_svs;
+    if(GNSS_MAX_SVS <= sv_index)
+    {
+        ERR("ERR: sv_index=[%d] is larger than GNSS_MAX_SVS.\n", sv_index);
+        return 0;
+    }
+
+    if ((prn > 0) && (prn < 32)) {
+        r->sv_status.gnss_sv_list[sv_index].svid = prn;
+        r->sv_status.gnss_sv_list[sv_index].constellation = GPS_SV;
+    } else if ((prn >= 65) && (prn <= 96)) {
+        r->sv_status.gnss_sv_list[sv_index].svid = prn-64;
+        r->sv_status.gnss_sv_list[sv_index].constellation = GLONASS_SV;
+    } else if ((prn >= 201) && (prn <= 237)) {
+        r->sv_status.gnss_sv_list[sv_index].svid = prn-200;
+        r->sv_status.gnss_sv_list[sv_index].constellation = BDS_SV;
+    } else if ((prn >= 401) && (prn <= 436)) {
+        r->sv_status.gnss_sv_list[sv_index].svid = prn-400;
+        r->sv_status.gnss_sv_list[sv_index].constellation = GALILEO_SV;
+    } else {
+        DBG("sv_status: ignore (%d)", prn);
+        return 0;
+    }
+
+    r->sv_status.gnss_sv_list[sv_index].c_n0_dbhz = str2float(snr.p, snr.end);
+    r->sv_status.gnss_sv_list[sv_index].elevation = str2int(elevation.p, elevation.end);
+    r->sv_status.gnss_sv_list[sv_index].azimuth = str2int(azimuth.p, azimuth.end);
+    if(1 == sv_used_in_fix[prn]){
+        r->sv_status.gnss_sv_list[sv_index].flags |= 0x04;;
+    }else{
+        r->sv_status.gnss_sv_list[sv_index].flags &= 0xFB;
+    }
+    r->sv_count++;
+    DBG("sv_status(%2d): %2d, %d, %2f, %3f, %2f, %d",
+        sv_index, r->sv_status.gnss_sv_list[sv_index].svid, r->sv_status.gnss_sv_list[sv_index].constellation,
+        r->sv_status.gnss_sv_list[sv_index].elevation, r->sv_status.gnss_sv_list[sv_index].azimuth,
+        r->sv_status.gnss_sv_list[sv_index].c_n0_dbhz, r->sv_status.gnss_sv_list[sv_index].flags);
+    return 0;
+}
+
+static int
+nmea_reader_parse( NmeaReader* const r )
+{
+   /* we received a complete sentence, now parse it to generate
+    * a new GPS fix...
+    */
+    NmeaTokenizer  tzer[1];
+    Token          tok;
+    Token          mtok;
+    SV_TYPE sv_type = 0;
+
+  /*
+    if (r->pos < 9) {
+        ERR("Too short. discarded. '%.*s'", r->pos, r->in);
+        return;
+    }
+    */
+
+    nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
+
+#if NEMA_DEBUG
+    {
+        int  n;
+        DBG("Found %d tokens", tzer->count);
+        for (n = 0; n < tzer->count; n++) {
+            Token  tok = nmea_tokenizer_get(tzer,n);
+            DBG("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
+        }
+    }
+#endif
+
+    tok = nmea_tokenizer_get(tzer, 0);
+    if (tok.p + 5 > tok.end) {
+        ERR("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
+        return -1;
+    }
+
+    // ignore first two characters.
+    mtok.p = tok.p; //Mark the first two char for GPS,GLONASS,BDS SV parse.
+    if(!memcmp(mtok.p, "BD", 2)){
+        sv_type = BDS_SV;
+        DBG("BDS SV type");
+    } else if (!memcmp(mtok.p, "GP", 2)) {
+        sv_type = GPS_SV;
+    } else if (!memcmp(mtok.p, "GL", 2)) {
+        sv_type = GLONASS_SV;
+    } else if (!memcmp(mtok.p, "GA", 2)) {
+        sv_type = GALILEO_SV;
+    }
+    #if NEMA_DEBUG
+    LOGD("SV type: %d", sv_type);
+    #endif
+    tok.p += 2;
+    if ( !memcmp(tok.p, "GGA", 3) )
+    {
+        if (tzer->count < 14)
+            return 0;
+        // GPS fix
+        Token  tok_time          = nmea_tokenizer_get(tzer,1);
+        Token  tok_latitude      = nmea_tokenizer_get(tzer,2);
+        Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,3);
+        Token  tok_longitude     = nmea_tokenizer_get(tzer,4);
+        Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
+        Token  tok_altitude      = nmea_tokenizer_get(tzer,9);
+        Token  tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
+
+        nmea_reader_update_time(r, tok_time);
+        nmea_reader_update_latlong(r, tok_latitude,
+                                      tok_latitudeHemi.p[0],
+                                      tok_longitude,
+                                      tok_longitudeHemi.p[0]);
+        nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
+
+    }
+    else if ( !memcmp(mtok.p, "GPGSA", 5)||!memcmp(mtok.p, "BDGSA", 5)||!memcmp(mtok.p, "GLGSA", 5)) {
+        if (tzer->count < 18)
+            return 0;
+        Token tok_fix = nmea_tokenizer_get(tzer, 2);
+        int idx, max = 12; /*the number of satellites in GPGSA*/
+
+        r->fix_mode = str2int(tok_fix.p, tok_fix.end);
+
+        if (LOC_FIXED(r)) { /* 1: No fix; 2: 2D; 3: 3D*/
+            for (idx = 0; idx < max; idx++) {
+                Token tok_satellite = nmea_tokenizer_get(tzer, idx+3);
+                if (tok_satellite.p == tok_satellite.end) {
+                    break;
+                }
+                int sate_id = str2int(tok_satellite.p, tok_satellite.end);
+                if (sv_type == BDS_SV){
+                    sate_id += 200;
+                }
+                if (sate_id >= 1 && sate_id <= 32) {  //GP
+                    sv_used_in_fix[sate_id] = 1;
+                }else if(sate_id >= 193 && sate_id <= 197){
+                    sv_used_in_fix[sate_id] = 0;
+                    continue;
+                }else if(sate_id >= 65 && sate_id <= 96){  //GL
+                    sv_used_in_fix[sate_id] = 1;
+                }else if(sate_id >= 201 && sate_id <= 232){  //BD
+                    sv_used_in_fix[sate_id] = 1;
+
+                }
+                else{
+                    break;
+                }
+            }
+        }
+    }
+ //VER("GPGSA: mask 0x%x", r->sv_status.used_in_fix_mask);
+    else if ( !memcmp(tok.p, "RMC", 3) ) {
+        if (tzer->count < 13)
+            return 0;
+        Token  tok_time          = nmea_tokenizer_get(tzer,1);
+        Token  tok_fixStatus     = nmea_tokenizer_get(tzer,2);
+        Token  tok_latitude      = nmea_tokenizer_get(tzer,3);
+        Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,4);
+        Token  tok_longitude     = nmea_tokenizer_get(tzer,5);
+        Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
+        Token  tok_speed         = nmea_tokenizer_get(tzer,7);
+        Token  tok_bearing       = nmea_tokenizer_get(tzer,8);
+        Token  tok_date          = nmea_tokenizer_get(tzer,9);
+
+        if (tok_fixStatus.p[0] == 'A') {
+            nmea_reader_update_date( r, tok_date, tok_time );
+            nmea_reader_update_latlong( r, tok_latitude,
+                    tok_latitudeHemi.p[0],
+                    tok_longitude,
+                    tok_longitudeHemi.p[0] );
+            nmea_reader_update_bearing( r, tok_bearing );
+            nmea_reader_update_speed( r, tok_speed );
+        }
+    }
+    else if ( !memcmp(tok.p, "GSV", 3) ) {
+        if (tzer->count < 4)
+            return 0;
+        Token tok_num = nmea_tokenizer_get(tzer,1); //number of messages
+        Token tok_seq = nmea_tokenizer_get(tzer,2); //sequence number
+        Token tok_cnt = nmea_tokenizer_get(tzer,3); //Satellites in view
+        int num = str2int(tok_num.p, tok_num.end);
+        int seq = str2int(tok_seq.p, tok_seq.end);
+        int cnt = str2int(tok_cnt.p, tok_cnt.end);
+        int sv_base = (seq - 1)*NMEA_MAX_SV_INFO;
+        int sv_num = cnt - sv_base;
+        int idx, base = 4, base_idx;
+        if (sv_num > NMEA_MAX_SV_INFO)
+            sv_num = NMEA_MAX_SV_INFO;
+        if (seq == 1)   /*if sequence number is 1, a new set of GSV will be parsed*/
+            r->sv_count = 0;
+        for (idx = 0; idx < sv_num; idx++) {
+            base_idx = base*(idx+1);
+            Token tok_id  = nmea_tokenizer_get(tzer, base_idx+0);
+            int sv_id = str2int(tok_id.p, tok_id.end);
+            if (sv_type == BDS_SV)
+                sv_id += 200;
+            else if (sv_type == GALILEO_SV)
+                sv_id += 400;
+            Token tok_ele = nmea_tokenizer_get(tzer, base_idx+1);
+            Token tok_azi = nmea_tokenizer_get(tzer, base_idx+2);
+            Token tok_snr = nmea_tokenizer_get(tzer, base_idx+3);
+            nmea_reader_update_sv_status(r, sv_base+idx, sv_id, tok_ele, tok_azi, tok_snr);
+        }
+        if (seq == num) {
+            if (r->sv_count <= cnt) {
+                r->sv_status.num_svs += r->sv_count;
+            }
+            else {
+                ERR("GPGSV incomplete (%d/%d), ignored!", r->sv_count, cnt);
+                r->sv_count = r->sv_status.num_svs = 0;
+            }
+        }
+    }
+    //Add for Accuracy
+    else if ( !memcmp(tok.p, "ACCURACY", 8)) {
+        if((r->fix_mode == 3)||(r->fix_mode == 2)) {
+            Token  tok_accuracy = nmea_tokenizer_get(tzer,1);
+            nmea_reader_update_accuracy(r, tok_accuracy);
+        }
+    }
+    else if ( !(memcmp(mtok.p, "GPBOD", 5)
+              && memcmp(mtok.p, "GPBWC", 5)
+              && memcmp(mtok.p, "GPGLL", 5)
+              && memcmp(mtok.p, "GPHDT", 5)
+              && memcmp(mtok.p, "GPROO", 5)
+              && memcmp(mtok.p, "GPRMA", 5)
+              && memcmp(mtok.p, "GPRMB", 5)
+              && memcmp(mtok.p, "GPRTE", 5)
+              && memcmp(mtok.p, "GPTRF", 5)
+              && memcmp(mtok.p, "GPSTN", 5)
+              && memcmp(mtok.p, "GPVBW", 5)
+              && memcmp(mtok.p, "GPVTG", 5)
+              && memcmp(mtok.p, "GPWPL", 5)
+              && memcmp(mtok.p, "GPXTE", 5)
+              && memcmp(mtok.p, "GPZDA", 5)))
+    {
+        tok.p -= 2;
+    }
+    else if ( !memcmp(mtok.p, "PMTK", 4))
+    {
+        tok.p -=2;
+        DBG("PMTK is %s", r->in);
+        if ( !memcmp(mtok.p, "PMTK010,002", 11) && g_EpoSend)
+        {
+            DBG("we got some START, ready to send EPO data");
+            callback_backup.create_thread_cb(gps_send_epo_thread, mtk_gps_send_EPO, NULL);
+            g_EpoSend = false;
+        }
+		/* disable QZSS start */
+        else if ( !memcmp(mtok.p, "PMTK010,001", 11))
+        {
+            DBG("we got some START, ready to send 352 cmd");
+			int temp_ret = 0;
+            temp_ret = write(_gps_state->tty_fd, "$PMTK352,1*2B\r\n", 15);
+			DBG("hao test : temp_ret is %d", temp_ret);
+            //g_EpoSend = false;
+        }
+        else if ( !memcmp(mtok.p, "PMTK001,352,3", 13))
+        {
+            DBG("received 352,3 response");
+        }
+        /* disable QZSS end */
+        return 0;
+    }
+    else {
+        tok.p -= 2;
+        return 0;
+    }
+    if (!LOC_FIXED(r)) {
+        VER("Location is not fixed, ignored callback\n");
+    }
+    else if (r->fix.flags != 0 && gps_nmea_end_tag) {
+#if NEMA_DEBUG
+        char   temp[256];
+        char*  p   = temp;
+        char*  end = p + sizeof(temp);
+        struct tm   utc;
+
+        p += snprintf( p, end-p, "sending fix" );
+        if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
+            p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude);
+        }
+        if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
+            p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
+        }
+        if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
+            p += snprintf(p, end-p, " speed=%g", r->fix.speed);
+        }
+        if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
+            p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
+        }
+        if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
+            p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
+            DBG("GPS accuracy=%g\n", r->fix.accuracy);
+        }
+        gmtime_r( (time_t*) &r->fix.timestamp, &utc );
+        p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
+        VER(temp);
+#endif
+        callback_backup.location_cb(&r->fix);
+        {
+            nlp_context fix_location;
+            fix_location.latitude = r->fix.latitude;
+            fix_location.longitude= r->fix.longitude;
+            fix_location.accuracy= r->fix.accuracy;
+            fix_location.type = 1;
+            fix_location.started = started;
+            fix_location.ts.tv_sec = r->fix.timestamp/1000;
+            fix_location.ts.tv_nsec = (r->fix.timestamp%1000) * 1000*1000;
+            mtk_gps_update_location(&fix_location);
+        }
+        r->fix.flags = GPS_LOCATION_HAS_ACCURACY;
+    }
+
+    DBG("r->sv_status.num_svs = %d, gps_nmea_end_tag = %d", r->sv_status.num_svs,gps_nmea_end_tag);
+    if (r->sv_status.num_svs != 0 && gps_nmea_end_tag)
+    {
+        int idx;
+        r->sv_status.size = sizeof(GnssSvStatus);
+        callback_backup.gnss_sv_status_cb(&r->sv_status);
+        r->sv_count = r->sv_status.num_svs = 0;
+        memset( sv_used_in_fix, 0, 256*sizeof(int));
+    }
+    return 1;
+}
+
+
+static void
+nmea_reader_addc( NmeaReader* const r, int  c )
+{
+    int ret = 0;
+    if (r->overflow) {
+        r->overflow = (c != '\n');
+        return;
+    }
+
+    if (r->pos >= (int) sizeof(r->in)-1 ) {
+        r->overflow = 1;
+        r->pos      = 0;
+        DBG("nmea sentence overflow\n");
+        return;
+    }
+
+    r->in[r->pos] = (char)c;
+    r->pos       += 1;
+    //DBG(" r->in[%d] is %c, r->pos is %d", r->pos, r->in[r->pos], r->pos);
+    if (c == '\n')
+    {
+        //r->pos < 9 :too short
+        if (gps_nmea_end_tag == 1 && r->pos >= 9) {
+            ret = nmea_reader_parse( r );
+            if (ret == 1)
+            {
+                DBG("ready to send : %s, strlen is %d, sizeof is %d", r->in, strlen(r->in), sizeof(r->in));
+                callback_backup.nmea_cb( r->fix.timestamp, r->in, r->pos );
+                pmtk_output_func( r->in, &(r->pos));
+            }
+            if (ret == 0)
+            {
+                pmtk_output_func(r->in, &(r->pos));
+            }
+            r->pos = 0;
+        }
+        else {
+            r->pos -=1;
+        }
+    }
+}
+
+static int
+epoll_register( int  epoll_fd, int  fd )
+{
+    struct epoll_event  ev;
+    int                 ret, flags;
+
+    /* important: make the fd non-blocking */
+    flags = fcntl(fd, F_GETFL);
+    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+    ev.events  = EPOLLIN;
+    ev.data.fd = fd;
+    do {
+        ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
+    } while (ret < 0 && errno == EINTR);
+    if(ret < 0)
+        ERR("epoll ctl error, error num is %d\n, message is %s\n", errno, strerror(errno));
+    return ret;
+}
+
+
+static int
+epoll_deregister( int  epoll_fd, int  fd )
+{
+    int  ret;
+    do {
+        ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
+void
+mtk_gps_start_driver()
+{
+    int fp = open("/dev/mt3337_gpsonly", O_RDWR);
+    if (fp == -1) {
+        DBG("open dev/mt3337_gpsonly fail, errorno is %d", errno);
+    }
+    else {
+        ioctl(fp, GPS_POWER_IOCTL, 1);
+        usleep(1000*200);
+        ioctl(fp, GPS_POWER_IOCTL, 0);
+        usleep(1000*200);
+        ioctl(fp, GPS_POWER_IOCTL, 1);
+    }
+    close(fp);
+}
+
+void
+mtk_gps_reset_driver()
+{
+    int fp = open("/dev/mt3337_gpsonly", O_RDWR);
+    if (fp == -1) {
+        DBG("open dev/mt3337_gpsonly fail, errorno is %d", errno);
+    }
+    else {
+        ioctl(fp, GPS_POWER_IOCTL, 0);
+        usleep(1000*1000);
+        ioctl(fp, GPS_POWER_IOCTL, 1);
+    }
+    close(fp);
+}
+
+void
+mtk_gps_stop_driver()
+{
+    int fp = open("/dev/mt3337_gpsonly", O_RDWR);
+    if (fp == -1) {
+        DBG("open dev/mt3337_gpsonly fail, errorno is %d", errno);
+    }
+    else {
+        ioctl(fp, GPS_POWER_IOCTL, 0);
+    }
+    close(fp);
+}
+
+void
+mnl_load_property()
+{
+    char result[512] = {0};
+    int iEpoDisable = 0;
+    int iHotstillEnable = 0;
+    GpsState*  s = _gps_state;
+    int ret = 0;
+    if (property_get(MNL_CONFIG_STATUS, result, NULL))
+    {
+        iEpoDisable = result[7] - '0';
+        if (iEpoDisable == 0)
+        {
+            ret = write(s->tty_fd, "$PMTK127*36\r\n", 13);
+            DBG("we r going to clear EPO data, ret is %d", ret);
+        }
+        iHotstillEnable = result[4] - '0';
+        if (iHotstillEnable == 1)
+        {
+            ret = write(s->tty_fd, "$PMTK869,1,1*35\r\n", 17);
+            DBG("we r going to enable easy, ret is %d", ret);
+        }
+        else
+        {
+            ret = write(s->tty_fd, "$PMTK869,1,0*36\r\n", 17);
+            DBG("we r going to disable easy, ret is %d", ret);
+        }
+    }
+    else
+    {
+        DBG("YGPS config not set yet");
+    }
+}
+
+unsigned char
+calc_nmea_checksum( const char* sentence)
+{
+    unsigned char checksum = 0;
+    while (*sentence)
+    {
+        checksum ^= (unsigned char)*sentence++;
+    }
+
+    return checksum;
+}
+
+//translate UTC to GPS_Hour
+int
+utc_to_gps_hour( int iYr, int iMo, int iDay, int iHr)
+{
+    int iYearsElapsed;
+    int iDaysElapsed;
+    int iLeapDays;
+    int i;
+
+    const unsigned short doy[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+    iYearsElapsed = iYr - 1980;
+    i = 0;
+    iLeapDays = 0;
+
+    while (i <= iYearsElapsed)
+    {
+        if ((i % 100) == 20)
+        {
+            if ((i % 400) == 20)
+            {
+                iLeapDays++;
+            }
+        }
+        else if ((i % 4) == 0)
+        {
+            iLeapDays++;
+        }
+        i++;
+    }
+    if ((iYearsElapsed % 100) == 20)
+    {
+        if (((iYearsElapsed % 400) == 20) && (iMo <= 2))
+        {
+            iLeapDays--;
+        }
+    }
+    else if (((iYearsElapsed % 4) == 0) && (iMo <= 2))
+    {
+        iLeapDays--;
+    }
+    iDaysElapsed = iYearsElapsed*365 + (int)doy[iMo - 1] + iDay + iLeapDays - 6;
+
+    return (iDaysElapsed * 24 + iHr);
+}
+
+void
+send_assistance_data (int iYr, int iMo, int iDay, int iHr, char * timeInfo, int iTimeLen)
+{
+    TRC();
+    int fp, ret = 0;
+    int i, segment, epo_gps_hour, current_gps_hour;
+    unsigned epobuf[MTKEPO_RECORD_SIZE/sizeof(unsigned)];
+    char strbuf[200], outbuf[200];
+    GpsState*  s = _gps_state;
+    // open EPO file and read the header (assume EPO file has passed integrity check)
+    fp = open(MTK_GPS_DATA_PATH"EPOHAL.DAT", O_RDONLY);
+    if (fp < 0)
+    {
+        DBG("!!!!!!no EPO file ERROR: %d, %s", errno, strerror(errno));
+        return;
+    }
+    ret = read(fp, &epo_gps_hour, sizeof(int));
+    epo_gps_hour &= 0x00FFFFFF;
+
+    current_gps_hour = utc_to_gps_hour(iYr, iMo, iDay, iHr);
+    segment = (current_gps_hour - epo_gps_hour) / 6;
+    if ((segment < 0) || (segment >= MTKEPO_SEGMENT_NUM))
+    {
+        DBG("!!!!!segment ERROR : %d", segment);
+        return;
+    }
+    // read binary EPO data and sent it to MT3339
+    lseek(fp, segment*(MTKEPO_RECORD_SIZE)*(MTKEPO_SV_NUMBER), SEEK_SET);
+    DBG("ready to write time info before send EPO data");
+    ret = write(s->tty_fd, timeInfo, iTimeLen);
+    usleep(1000*200);
+    for (i = 0; i < MTKEPO_SV_NUMBER; i++)
+    {
+        read(fp, epobuf, MTKEPO_RECORD_SIZE);
+        // assume host system is little-endian
+        sprintf(strbuf,"PMTK721,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X",
+        i+1,
+        epobuf[0], epobuf[1], epobuf[2], epobuf[3], epobuf[4], epobuf[5],
+        epobuf[6], epobuf[7], epobuf[8], epobuf[9], epobuf[10], epobuf[11],
+        epobuf[12], epobuf[13], epobuf[14], epobuf[15], epobuf[16], epobuf[17]);
+        sprintf(outbuf, "$%s*%02X\r\n", strbuf, calc_nmea_checksum(strbuf));
+        // send them by UART
+        DBG("!!!!this EPO data len is %d,data is : %s", strlen(outbuf), outbuf); // for demo
+        for (int j = 0; j < 3; j++)
+        {
+            ret = write(s->tty_fd, outbuf, strlen(outbuf));
+            if (ret < 0)
+                DBG("Write EPO data fail, errno is %d", errno);
+            else
+                j = 3;
+        }
+        if (i%10 == 0)
+            usleep(1000*200);
+    }
+    close(fp);
+}
+
+/*for reducing the function call to get data from kernel*/
+static char buffGGA[2048];
+/*gps nmea read thread */
+static bool g_NmeaReadStart = false;
+static bool g_ThreadExistNmeaRead = false;
+static bool g_GpsDriverStart = false;
+static pthread_mutex_t g_mutx;
+
+void
+gps_read_nmea_from_uart_thread(void* arg)
+{
+    g_ThreadExistNmeaRead = true;
+    GpsState*   state = (GpsState*) arg;
+    int fd = state->tty_fd;
+    while (g_ThreadExistNmeaRead)
+    {
+        if(g_GpsDriverStart && g_NmeaReadStart)
+        {
+            int  nn, ret;
+            memset(buffGGA, 0, sizeof(buffGGA));
+            ret = read( fd, buffGGA, sizeof(buffGGA) );
+            gps_nmea_end_tag = 0;
+
+            DBG("before PARSE buffer[%d] is:%s.", ret, buffGGA);
+            memset(g_NmeaReader->in, 0, sizeof(g_NmeaReader->in));
+            for (nn = 0; nn < ret && g_GpsDriverStart; nn++)
+            {
+                if(nn == (ret-1))
+                    gps_nmea_end_tag = 1;
+
+                nmea_reader_addc( g_NmeaReader, buffGGA[nn] );
+            }
+            g_NmeaReadStart = false;
+        }
+        usleep(100);
+    }
+    DBG("gps_read_nmea_from_uart_thread exit!");
+}
+/* this is the main thread, it waits for commands from gps_state_start/stop and,
+ * when started, messages from the GPS daemon. these are simple NMEA sentences
+ * that must be parsed to be converted into GPS fixes sent to the framework
+ */
+void
+gps_state_thread( void*  arg )
+{
+    static float count = 0;
+    GpsState*   state = (GpsState*) arg;
+    state->test_time += 1;
+    int         tty_fd     = state->tty_fd;
+    int         control_fd = state->control[1];
+    int         pow_fd     = state->pow_fd;
+
+    int epoll_fd = state->epoll_hd;
+    int         test_started = 0;
+
+    nmea_reader_init( g_NmeaReader );
+
+    // register control file descriptors for polling
+    if(epoll_register( epoll_fd, control_fd ) < 0)
+        ERR("control_fd register control_fd error, error num is %d\n, message is %s\n", errno, strerror(errno));
+    if(epoll_register( epoll_fd, tty_fd) < 0)
+        ERR("tty_fd register control_fd error, error num is %d\n, message is %s\n", errno, strerror(errno));
+    //if(epoll_register( epoll_fd, pow_fd) < 0)
+    if(epoll_add_fd( epoll_fd, pow_fd) < 0)
+        ERR("pow_fd register control_fd error, error num is %d\n, message is %s\n", errno, strerror(errno));
+
+    release_condition(&lock_for_sync[M_INIT]);
+
+    // now loop
+    for (;;)
+    {
+        struct epoll_event   events[5];
+        int                  ne, nevents;
+        nevents = epoll_wait( epoll_fd, events, 5, -1 );
+        if (nevents < 0)
+        {
+            if (errno != EINTR)
+                ERR("epoll_wait() unexpected error: %s", strerror(errno));
+            continue;
+        }
+
+        for (ne = 0; ne < nevents; ne++)
+        {
+            if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0)
+            {
+                ERR("EPOLLERR or EPOLLHUP after epoll_wait() !?");
+                goto Exit;
+            }
+            if ((events[ne].events & EPOLLIN) != 0)
+            {
+                int  fd = events[ne].data.fd;
+
+                if (fd == pow_fd)
+                {
+                    ERR("!!!!!!!!!!!EPO donwload done");
+                    char  cmd = 255;
+                    int   ret;
+
+                    //socket
+                    char epo_buff[100] = {0};
+                    int offset = 0;
+                    int read_len;
+
+                    read_len = safe_recvfrom(fd, epo_buff, sizeof(epo_buff));
+                    if (read_len <= 0) {
+                        DBG("@@@@@@@@@gpsinf3337() safe_recvfrom() failed read_len=%d", read_len);
+                        break;
+                    }
+                    cmd = get_int(epo_buff, &offset, sizeof(epo_buff));
+
+                    if (cmd == CMD_EPO_DOWNLOAD_DONE) {
+                        DBG("@@@@@@@@@@@@got the EPO download msg");
+                        callback_backup.create_thread_cb(gps_send_epo_thread, mtk_gps_send_EPO, NULL);
+                    }
+                }
+                else if (fd == control_fd)
+                {
+                    char  cmd = 255;
+                    int   ret;
+                    do {
+                        ret = read( fd, &cmd, 1 );
+                    } while (ret < 0 && errno == EINTR);
+
+                    if (cmd == CMD_QUIT) {
+                        DBG("gps thread quitting on demand");
+                        goto Exit;
+                    }
+                    else if (cmd == CMD_START) {
+                        if (!started) {
+                            started = 1;
+                            nmea_reader_set_callback( g_NmeaReader, &state->callbacks);
+                            switch (g_delete_aiding_data_flag) {
+                                case 1:
+                                    DBG("Last time's delete_aiding : hot start");
+                                    ret = write(tty_fd, "$PMTK101*32\r\n", 13);
+                                    g_EpoSend = true;
+                                    break;
+                                case 2:
+                                    DBG("Last time's delete_aiding : warm start");
+                                    ret = write(tty_fd, "$PMTK102*31\r\n", 13);
+                                    g_EpoSend = true;
+                                    break;
+                                case 3:
+                                    DBG("Last time's delete_aiding : cold start");
+                                    ret = write(tty_fd, "$PMTK103*30\r\n", 13);
+                                    g_EpoSend = true;
+                                    break;
+                                case 4:
+                                    DBG("Last time's delete_aiding : full start");
+                                    ret = write(tty_fd, "$PMTK104*37\r\n", 13);
+                                    g_EpoSend = true;
+                                    break;
+                                default:
+                                    break;
+                            }
+                            g_delete_aiding_data_flag = 0;
+                        }
+                    }
+                    else if (cmd == CMD_STOP) {
+                        if (started) {
+                            started = 0;
+                            nmea_reader_set_callback( g_NmeaReader, NULL );
+                            release_condition(&lock_for_sync[M_STOP]);
+                            DBG("CMD_STOP has been receiving from HAL thread, release lock so can handle CLEAN_UP\n");
+                        }
+                    }
+                    else if (cmd == CMD_RESTART) {
+                        g_NmeaReader->fix_mode = 0;
+                        DBG("gps 3337 restart!!!!");
+                    }
+                }
+                else if (fd == tty_fd)
+                {
+                    if(!flag_unlock)
+                    {
+                        release_condition(&lock_for_sync[M_START]);
+                        flag_unlock = 1;
+                        DBG("got first NMEA sentence, release lock to set state ENGINE ON, SESSION BEGIN");
+                    }
+                    if(report_time_interval > ++count){
+                        DBG("[trace]count is %f\n", count);
+                        //int ret = read( fd, buff, sizeof(buff) );
+                        continue;
+                    }
+                    count = 0;
+                    g_NmeaReadStart = true;
+                }
+            }
+        }
+    }
+Exit:
+    DBG("HAL thread is exiting, release lock to clean resources\n");
+    release_condition(&lock_for_sync[M_CLEANUP]);
+    return;
+}
+static void
+gps_state_done( GpsState*  s )
+{
+    TRC();
+    char   cmd = CMD_QUIT;
+
+    write( s->control[0], &cmd, 1 );
+    get_condition(&lock_for_sync[M_CLEANUP]);
+
+    g_ThreadExitPMTKIn = false;
+    g_hPowerGPS = INVALID_FD;
+    pthread_join(s->pmtk_thread->thread, NULL);
+    g_ThreadExistNmeaRead = false;
+    pthread_join(s->nmea_read_thread, NULL);
+
+    close( s->control[0] ); s->control[0] = -1;
+    close( s->control[1] ); s->control[1] = -1;
+    close( s->pow_fd ); s->pow_fd = -1;
+    close( s->tty_fd ); s->tty_fd = -1;
+    close(s->epoll_hd); s->epoll_hd = -1;
+    s->init = 0;
+    s->test_time -= 1;
+    DBG("GPS cleanup done");
+
+    return;
+}
+
+
+static void
+gps_state_start( GpsState*  s )
+{
+    char  cmd = CMD_START;
+    int   ret;
+
+    do { ret=write( s->control[0], &cmd, 1 ); }
+    while (ret < 0 && errno == EINTR);
+
+    if (ret != 1)
+        ERR("%s: could not send CMD_START command: ret=%d: %s",
+          __FUNCTION__, ret, strerror(errno));
+}
+
+static void
+gps_state_stop( GpsState*  s )
+{
+    char  cmd = CMD_STOP;
+    int   ret;
+
+    do { ret=write( s->control[0], &cmd, 1 ); }
+    while (ret < 0 && errno == EINTR);
+
+    if (ret != 1)
+        ERR("%s: could not send CMD_STOP command: ret=%d: %s",
+          __FUNCTION__, ret, strerror(errno));
+}
+
+static void
+gps_state_restart( GpsState*  s )
+{
+    char  cmd = CMD_RESTART;
+    int   ret;
+
+    do { ret=write( s->control[0], &cmd, 1 ); }
+    while (ret < 0 && errno == EINTR);
+
+    if (ret != 1)
+        ERR("%s: could not send CMD_RESTART command: ret=%d: %s",
+          __FUNCTION__, ret, strerror(errno));
+}
+
+
+static void
+gps_state_init( GpsState*  state )
+{
+    state->control[0] = -1;
+    state->control[1] = -1;
+    state->pow_fd     = -1;
+    state->tty_fd     = -1;
+
+    TRC();
+
+    //socket
+    state->pow_fd = socket_bind_udp(MNLD_HAL2GPS);
+    socket_set_blocking(state->pow_fd, 0);
+    if (state->pow_fd < 0) {
+        ERR("no gps hardware detected: %s:%d, %s", MNLD_HAL2GPS, state->pow_fd, strerror(errno));
+        return;
+    }
+
+    state->tty_fd = open(GPS_TTY_NAME, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (state->tty_fd < 0) {
+        close(state->pow_fd);
+        state->pow_fd = -1;
+        ERR("no gps hardware detected: %s:%d, %s", GPS_TTY_NAME, state->tty_fd, strerror(errno));
+        return;
+    }
+    struct termios options;
+    int i4_baud = B115200;
+    tcgetattr(state->tty_fd, &options);
+    cfsetispeed(&options, i4_baud);
+    cfsetospeed(&options, i4_baud);
+
+    options.c_cflag |= (CLOCAL | CREAD);
+    options.c_cflag &= ~PARENB;
+    options.c_cflag &= ~CSTOPB;
+    options.c_cflag &= ~CSIZE;
+    options.c_cflag &= ~PARODD;
+    options.c_cflag |= CS8;
+    options.c_cflag &= ~CRTSCTS;
+    options.c_lflag &= ~(ISIG | ECHO);
+    options.c_oflag &= ~OPOST;
+    options.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXON | BRKINT );
+    options.c_cc[VMIN] = 1;
+    options.c_cc[VTIME] = 0;
+    tcsetattr(state->tty_fd, TCSANOW, &options);
+
+    int epoll_fd = epoll_create(3);
+    state->epoll_hd = epoll_fd;
+
+    if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
+        ERR("could not create thread control socket pair: %s", strerror(errno));
+        goto Fail;
+    }
+    state->thread = callback_backup.create_thread_cb(gps_native_thread, gps_state_thread, state);
+    if (!state->thread){
+        ERR("could not create gps thread: %s", strerror(errno));
+        goto Fail;
+    }
+
+    DBG("gps state initialized, the thread is %d\n", (int)state->thread);
+    if (!g_ThreadExitPMTKIn)
+    {
+    state->pmtk_thread->thread= callback_backup.create_thread_cb(gps_pmtk_thread, powergps_pmtk_receive_thread, state);
+    if (!state->pmtk_thread->thread){
+        ERR("could not create gps pmtk thread: %s", strerror(errno));
+        goto Fail;
+        }
+    }
+
+    if (!g_ThreadExistNmeaRead)
+    {
+        state->nmea_read_thread = callback_backup.create_thread_cb(gps_nmea_read_thread, gps_read_nmea_from_uart_thread, state);
+        if (!state->nmea_read_thread){
+            ERR("could not create nmea read thread: %s", strerror(errno));
+            goto Fail;
+        }
+    }
+
+    DBG("gps PMTK initialized, the thread is %d\n", (int)state->pmtk_thread->thread);
+
+    return;
+
+Fail:
+    gps_state_done( state );
+}
+
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****       I N T E R F A C E                               *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+static int
+mtk_gps_mt3337_init(GpsCallbacks* callbacks)
+{
+    TRC();
+    GpsState*  s = _gps_state;
+    int get_time = 20;
+    int res = 0;
+    if(s->init)
+        return 0;
+    s->callbacks = *callbacks;
+    callback_backup = *callbacks;
+
+    gps_state_init(s);
+    get_condition(&lock_for_sync[M_INIT]);
+    usleep(1000*1);
+    s->init = 1;
+    DBG("Set GPS_CAPABILITY_SCHEDULING \n");
+    callback_backup.set_capabilities_cb(GPS_CAPABILITY_SCHEDULING);
+
+    if (gpshal_gpscbs_save(callbacks) != 0) {
+        return -1;    //  error
+    }
+
+    gpshal_set_gps_state_intent(GPSHAL_STATE_INIT);
+    gpshal2mnl_gps_init();
+    return 0;
+}
+
+static void
+mtk_gps_mt3337_cleanup(void)
+{
+    GpsState*  s = _gps_state;
+
+    TRC();
+
+    if(s->start_flag)
+    get_condition(&lock_for_sync[M_STOP]); //make sure gps_stop has set state to GPS_STATUS_ENGINE_OFF by callback function
+    if(lock_for_sync[M_STOP].condtion == 1)
+    {
+        lock_for_sync[M_STOP].condtion = 0; //make sure gps_stop has set state to GPS_STATUS_ENGINE_OFF in next time
+    }
+    if (s->init)
+        gps_state_done(s);
+    gpshal_set_gps_state_intent(GPSHAL_STATE_CLEANUP);
+    gpshal2mnl_gps_cleanup();
+    DBG("mtk_gps_cleanup done");
+}
+
+int
+mtk_gps_mt3337_start()
+{
+    TRC();
+    GpsState*  s = _gps_state;
+    int err;
+    int count=0;
+
+
+    if (!s->init) {
+        ERR("%s: called with uninitialized state !!", __FUNCTION__);
+        return -1;
+    }
+
+    while(s->start_flag == 1)
+    {
+        usleep(100000);
+        count++;
+        DBG("mtk_gps_start:start_flag = %d delay=%d \n",s->start_flag,count*100);
+    }
+    mtk_gps_start_driver();
+    g_GpsDriverStart = true;
+    DBG("mtk_gps_mt3337_start done!!!!");
+    mnl_load_property();
+
+    get_condition(&lock_for_sync[M_START]);
+    gps_state_start(s);
+
+    sta.status = GPS_STATUS_ENGINE_ON;
+    callback_backup.status_cb(&sta);
+    sta.status = GPS_STATUS_SESSION_BEGIN;
+    callback_backup.status_cb(&sta);
+
+    callback_backup.acquire_wakelock_cb();//avoid cpu to sleep
+    s->start_flag = 1;
+
+    gpshal_set_gps_state_intent(GPSHAL_STATE_START);
+    gpshal2mnl_gps_start();
+    return 0;
+}
+
+int
+mtk_gps_mt3337_stop()
+{
+    TRC();
+    GpsState*  s = _gps_state;
+    int err;
+    int count=0;
+
+    if (!s->init) {
+        ERR("%s: called with uninitialized state !!", __FUNCTION__);
+        return -1;
+    }
+
+    while(s->start_flag == 0)
+    {
+        usleep(100000);
+        count++;
+        DBG("mtk_gps_stop:start_flag = %d delay=%d \n",s->start_flag,count*100);
+    }
+    s->start_flag = 0;
+
+    mtk_gps_stop_driver();
+    g_GpsDriverStart = false;
+    flag_unlock = 0;
+    gps_state_stop(s);
+    gpshal_set_gps_state_intent(GPSHAL_STATE_STOP);
+    gpshal2mnl_gps_stop();
+
+    callback_backup.release_wakelock_cb();
+    DBG("mtk_gps_mt3337_STOP done!!!!");
+    return 0;
+}
+
+static int
+mtk_gps_mt3337_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty)
+{
+    ntp_context inject_ntp;
+    long long time_s = 0;
+    int offset = 0;
+
+    TRC();
+    time_s = time/1000;
+    DBG("inject time= %lld,ctime = %s, timeReference = %lld,uncertainty =%d\n", time,ctime(&time_s), timeReference,uncertainty);
+    memcpy(&(inject_ntp.time),&time,sizeof(GpsUtcTime));
+    inject_ntp.timeReference = timeReference;
+    inject_ntp.uncertainty = uncertainty;
+
+    //do not support detail function
+    return 0;
+}
+
+static int
+mtk_gps_mt3337_inject_location(double latitude, double longitude, float accuracy)
+{
+    nlp_context nlp_location;
+    int offset = 0;
+
+    if(clock_gettime(CLOCK_MONOTONIC , &nlp_location.ts) == -1)
+    {
+        ERR("clock_gettime failed reason=[%s]\n",strerror(errno));
+        return -1;
+    }
+    DBG("ts.tv_sec= %lld,ts.tv_nsec = %lld\n", nlp_location.ts.tv_sec,nlp_location.ts.tv_nsec);
+    DBG("inject location lati= %f, longi = %f,accuracy =%f\n", latitude, longitude,accuracy);
+
+    //do not support detail function
+    return 0;
+}
+
+static void
+mtk_gps_mt3337_delete_aiding_data(GpsAidingData flags)
+{
+    /*workaround to trigger hot/warm/cold/full start*/
+    #define FLAG_HOT_START  GPS_DELETE_RTI
+    #define FLAG_WARM_START GPS_DELETE_EPHEMERIS
+    #define FLAG_COLD_START (GPS_DELETE_EPHEMERIS | GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO | GPS_DELETE_UTC | GPS_DELETE_HEALTH)
+    #define FLAG_FULL_START (GPS_DELETE_ALL)
+    #define FLAG_AGPS_START (GPS_DELETE_EPHEMERIS | GPS_DELETE_ALMANAC | GPS_DELETE_POSITION | GPS_DELETE_TIME | GPS_DELETE_IONO | GPS_DELETE_UTC)
+    GpsState*  s = _gps_state;
+    int ret;
+
+    DBG("%s:0x%X\n", __FUNCTION__, flags);
+
+    gps_state_restart(s);
+
+    if (flags == FLAG_HOT_START)
+    {
+        mtk_restart(MNL_CMD_RESTART_HOT);
+        if (g_GpsDriverStart)
+        {
+            DBG("GPS driver still start!!! send it HOT_START!!!");
+            ret = write(s->tty_fd, "$PMTK101*32\r\n", 13);
+            if (ret < 0)
+                DBG("HOT_START FAILED!!! error is %d : %s", errno, strerror(errno));
+            g_EpoSend = true;
+        }
+        else
+        {
+            g_delete_aiding_data_flag = 1;
+        }
+    }
+    else if (flags == FLAG_WARM_START)
+    {
+        mtk_restart(MNL_CMD_RESTART_WARM);
+        if (g_GpsDriverStart)
+        {
+            DBG("GPS driver still start!!! send it WARM_START!!!");
+            ret = write(s->tty_fd, "$PMTK102*31\r\n", 13);
+            if (ret < 0)
+                DBG("WARM_START FAILED!!! error is %d : %s", errno, strerror(errno));
+            g_EpoSend = true;
+        }
+        else
+        {
+            g_delete_aiding_data_flag = 2;
+        }
+    }
+    else if (flags == FLAG_COLD_START)
+    {
+        mtk_restart(MNL_CMD_RESTART_HOT);
+        if (g_GpsDriverStart)
+        {
+            DBG("GPS driver still start!!! send it COLD_START!!!");
+            ret = write(s->tty_fd, "$PMTK103*30\r\n", 13);
+            if (ret < 0)
+                DBG("COLD_START FAILED!!! error is %d : %s", errno, strerror(errno));
+            g_EpoSend = true;
+        }
+        else
+        {
+            g_delete_aiding_data_flag = 3;
+        }
+    }
+    else if (flags == FLAG_FULL_START)
+    {
+        mtk_restart(MNL_CMD_RESTART_HOT);
+        if (g_GpsDriverStart)
+        {
+            DBG("GPS driver still start!!! send it COLD_START!!!");
+            ret = write(s->tty_fd, "$PMTK104*37\r\n", 13);
+            if (ret < 0)
+                DBG("FULL_START FAILED!!! error is %d : %s", errno, strerror(errno));
+            g_EpoSend = true;
+        }
+        else
+        {
+            g_delete_aiding_data_flag = 4;
+        }
+    }
+    else if(flags == FLAG_AGPS_START)
+    {
+        DBG("Send MNL_CMD_RESTART_AGPS in HAL\n");
+        mtk_restart(MNL_CMD_RESTART_AGPS);
+    }
+}
+
+static int mtk_gps_mt3337_set_position_mode(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time)
+{
+    // FIXME - support fix_frequency
+    // only standalone supported for now.
+    DBG("set report location time interval is %d\n", min_interval);
+    if(min_interval <= 1000)
+        report_time_interval = 1;
+    else
+        report_time_interval = (float)min_interval/1000;
+    DBG("set report location time interval is %f s\n", report_time_interval);
+    TRC();
+    return 0;
+}
+
+static const void*
+mtk_gps_mt3337_get_extension(const char* name)
+{
+    TRC();
+    DBG("mtk_gps_get_extension name=[%s]\n", name);
+    if (strcmp(name, AGPS_RIL_INTERFACE) == 0) {
+        return &mtk_agps_ril_inf;
+    }
+/*
+#if EPO_SUPPORT
+    if (!strcmp(name, GPS_XTRA_INTERFACE))
+        return (void*)(&mtkGpsXtraInterface);
+#endif
+*/
+    return NULL;
+}
+
+static const GpsInterface  mtkGpsInterface = {
+    sizeof(GpsInterface),
+    mtk_gps_mt3337_init,
+    mtk_gps_mt3337_start,
+    mtk_gps_mt3337_stop,
+    mtk_gps_mt3337_cleanup,
+    mtk_gps_mt3337_inject_time,
+    mtk_gps_mt3337_inject_location,
+    mtk_gps_mt3337_delete_aiding_data,
+    mtk_gps_mt3337_set_position_mode,
+    mtk_gps_mt3337_get_extension,
+};
+
+//=========================================================
+// Between
+//     Gps Interface
+//     Hardware Module Interface
+
+static const GpsInterface* gps_device__get_gps_interface(
+        __unused struct gps_device_t* device) {
+    /*
+     * hao mt3337 modify
+     * GPS_DEVICE__GET_GPS_INTERFACE__CHECK_PARAM;
+     * hal2mnl_hal_reboot();
+     */
+    return &mtkGpsInterface;
+}
+
+static const struct gps_device_t gps_device = {
+    .common = {                           // hw_device_t
+        .tag     = HARDWARE_DEVICE_TAG,
+        .version = 0,                     // GPS JNI will not use it
+        .module  = &HAL_MODULE_INFO_SYM,
+        .reserved = {0},
+        .close   = NULL                   // GPS JNI will not call it
+        },
+    .get_gps_interface = gps_device__get_gps_interface
+};
+
+
+static int open_gps(const struct hw_module_t* module, char const* name,
+        struct hw_device_t** device)
+{
+    DBG("open_gps HAL 1\n");
+    *device = (struct hw_device_t*)&gps_device;
+    return 0;
+}
+
+
+static struct hw_module_methods_t gps_module_methods = {
+    .open = open_gps
+};
+
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 1,
+    .version_minor = 0,
+    .id  = GPS_HARDWARE_MODULE_ID,
+    .name   = "MediaTek GPS Hardware Module",
+    .author = "MediaTek, Inc.",
+    .methods = &gps_module_methods,
+    .dso     = NULL,
+    .reserved = {0}
+};
diff --git a/src/connectivity/gps/gps_hal/src/hal2mnl_interface.c b/src/connectivity/gps/gps_hal/src/hal2mnl_interface.c
new file mode 100644
index 0000000..4d6945b
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/hal2mnl_interface.c
@@ -0,0 +1,623 @@
+#include "hal2mnl_interface.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+int log_dbg_level = L_DEBUG;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "hal2mnl"
+#endif
+
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+static float count = 0;
+static float report_time_interval = 0;
+
+int hal2mnl_hal_reboot() {
+    LOGI("hal2mnl_hal_reboot");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+    put_int(buff, &offset, HAL2MNL_HAL_REBOOT);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_init() {
+    LOGI("hal2mnl_gps_init");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_INIT);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_start() {
+    LOGI("hal2mnl_gps_start");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_START);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+int hal2mnl_gps_stop() {
+    LOGI("hal2mnl_gps_stop");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_STOP);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_cleanup() {
+    LOGI("hal2mnl_gps_cleanup");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_CLEANUP);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty) {
+    /*LOGD("hal2mnl_gps_inject_time  time=%zd time_reference=%zd uncertainty=%d",
+        time, time_reference, uncertainty);*/
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_INJECT_TIME);
+    put_long(buff, &offset, time);
+    put_long(buff, &offset, time_reference);
+    put_int(buff, &offset, uncertainty);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_inject_location(double lat, double lng, float acc) {
+    // LOGD("hal2mnl_gps_inject_location  lat,lng %f,%f acc=%f", lat, lng, acc);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_INJECT_LOCATION);
+    put_double(buff, &offset, lat);
+    put_double(buff, &offset, lng);
+    put_float(buff, &offset, acc);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_delete_aiding_data(int flags) {
+    LOGD("flag=0x%x", flags);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_DELETE_AIDING_DATA);
+    put_int(buff, &offset, flags);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_gps_set_position_mode(gps_pos_mode mode, gps_pos_recurrence recurrence,
+    int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode) {
+    LOGD("mode=%d recurrence=%d min_interval=%d preferred_acc=%d preferred_time=%d lowpowermode=%d",
+        mode, recurrence, min_interval, preferred_acc, preferred_time, lowPowerMode);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_SET_POSITION_MODE);
+    put_int(buff, &offset, mode);
+    put_int(buff, &offset, recurrence);
+    put_int(buff, &offset, min_interval);
+    put_int(buff, &offset, preferred_acc);
+    put_int(buff, &offset, preferred_time);
+    put_byte(buff, &offset, lowPowerMode);
+
+    if (min_interval <= 1000) {
+        report_time_interval = 1;
+    } else {
+        report_time_interval = (float)min_interval/1000;
+    }
+    LOGD("set report location time interval is %f s\n", report_time_interval);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_data_conn_open(const char* apn) {
+    LOGD("apn=[%s]", apn);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_DATA_CONN_OPEN);
+    put_string(buff, &offset, apn);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_data_conn_open_with_apn_ip_type(const char* apn, apn_ip_type ip_type) {
+    LOGD("apn=[%s] ip_type=%d",
+        apn, ip_type);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE);
+    put_string(buff, &offset, apn);
+    put_int(buff, &offset, ip_type);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_data_conn_closed() {
+    LOGD("hal2mnl_data_conn_closed");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_DATA_CONN_CLOSED);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_data_conn_failed() {
+    LOGD("hal2mnl_data_conn_failed");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_DATA_CONN_FAILED);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_set_server(agps_type type, const char* hostname, int port) {
+    LOGD("type=%d hostname=[%s] port=%d",
+        type, hostname, port);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_SET_SERVER);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, hostname);
+    put_int(buff, &offset, port);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+    return 0;
+}
+
+int hal2mnl_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid) {
+    LOGD("ype=%d mcc=%d mnc=%d lac=%d cid=%d",
+        type, mcc, mnc, lac, cid);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_SET_REF_LOCATION);
+    put_int(buff, &offset, type);
+    put_int(buff, &offset, mcc);
+    put_int(buff, &offset, mnc);
+    put_int(buff, &offset, lac);
+    put_int(buff, &offset, cid);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_set_id(agps_id_type type, const char* setid) {
+    LOGD("type=%d setid=[%s]", type, setid);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_SET_ID);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, setid);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+
+int hal2mnl_ni_message(char* msg, int len) {
+    LOGD("len=%d", len);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_NI_MESSAGE);
+    put_binary(buff, &offset, msg, len);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+#if defined(__LINUX_OS__)
+int hal2mnl_send_pmtk(char* msg, int len) {
+    LOGD("len=%d", len);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_SEND_PMTK);
+    put_binary(buff, &offset, msg, len);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+#endif
+
+int hal2mnl_ni_respond(int notif_id, ni_user_response_type user_response) {
+    LOGD("notif_id=%d user_response=%d",
+        notif_id, user_response);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_NI_RESPOND);
+    put_int(buff, &offset, notif_id);
+    put_int(buff, &offset, user_response);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_update_network_state(int connected, network_type type, int roaming,
+    const char* extra_info) {
+    LOGD("connected=%d type=%d roaming=%d extra_info=[%s]",
+        connected, type, roaming, extra_info);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_UPDATE_NETWORK_STATE);
+    put_int(buff, &offset, connected);
+    put_int(buff, &offset, type);
+    put_int(buff, &offset, roaming);
+    put_string(buff, &offset, extra_info);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_update_network_availability(int available, const char* apn) {
+    LOGD("available=%d apn=[%s]",
+        available, apn);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_UPDATE_NETWORK_AVAILABILITY);
+    put_int(buff, &offset, available);
+    put_string(buff, &offset, apn);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_set_gps_measurement(bool enabled, bool enableFullTracking) {
+    LOGD("enabled=%d, flag=%d", enabled, enableFullTracking);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_MEASUREMENT);
+    put_int(buff, &offset, enabled);
+    put_int(buff, &offset, enableFullTracking);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_set_gps_navigation(bool enabled) {
+    LOGD("enabled=%d", enabled);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GPS_NAVIGATION);
+    put_int(buff, &offset, enabled);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_set_vzw_debug(bool enabled) {
+    LOGD("enabled = %d\n", enabled);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_VZW_DEBUG);
+    put_int(buff, &offset, enabled);
+
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+int hal2mnl_update_gnss_config(const char* config_data, int length) {
+    LOGD("data length:%d\n", length);
+    int offset = 0;
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, HAL2MNL_GNSS_CONFIG);
+    put_int(buff, &offset, length);
+    put_string(buff, &offset, config_data);
+    return safe_sendto(MTK_HAL2MNL, buff, offset);
+}
+
+// -1 means failure
+int mnl2hal_hdlr(int fd, mnl2hal_interface* hdlr) {
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    int ver;
+    mnl2hal_cmd cmd;
+    int read_len;
+    int ret = 0;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("mnl2hal_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+    ver = get_int(buff, &offset, sizeof(buff));
+    UNUSED(ver);
+    cmd = get_int(buff, &offset, sizeof(buff));
+
+    switch (cmd) {
+    case MNL2HAL_MNLD_REBOOT: {
+        if (hdlr->mnld_reboot) {
+            hdlr->mnld_reboot();
+        } else {
+            LOGE("mnl2hal_hdlr() mnld_reboot is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_LOCATION: {
+        if (report_time_interval > ++count) {
+            LOGD("count is %f, interval is %f\n", count, report_time_interval);
+            break;
+        }
+        count = 0;
+
+        if (hdlr->location) {
+            gps_location location;
+            get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(gps_location));
+            hdlr->location(location);
+        } else {
+            LOGE("mnl2hal_hdlr() location is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GPS_STATUS: {
+        if (hdlr->gps_status) {
+            gps_status status;
+            get_binary(buff, &offset, (char*)&status, sizeof(buff), sizeof(gps_status));
+            hdlr->gps_status(status);
+        } else {
+            LOGE("mnl2hal_hdlr() gps_status is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GPS_SV: {
+        if (hdlr->gps_sv) {
+            gnss_sv_info sv;
+            get_binary(buff, &offset, (char*)&sv, sizeof(buff), sizeof(gnss_sv_info));
+            hdlr->gps_sv(sv);
+        } else {
+            LOGE("mnl2hal_hdlr() gps_sv is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_NMEA: {
+        if (hdlr->nmea) {
+            int64_t timestamp = get_long(buff, &offset, sizeof(buff));
+            char* nmea = get_string(buff, &offset, sizeof(buff));
+            int used_length = nmea - buff;
+            int max_length = sizeof(buff) - used_length;
+            int length = get_int(buff, &offset, sizeof(buff));
+            length = MIN(length,max_length);
+            hdlr->nmea(timestamp, nmea, length);
+        } else {
+            LOGE("mnl2hal_hdlr() nmea is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GPS_CAPABILITIES: {
+        if (hdlr->gps_capabilities) {
+            gps_capabilites capabilities;
+            get_binary(buff, &offset, (char*)&capabilities, sizeof(buff), sizeof(gps_capabilites));
+            hdlr->gps_capabilities(capabilities);
+        } else {
+            LOGE("mnl2hal_hdlr() gps_capabilities is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GPS_MEASUREMENTS: {
+        if (hdlr->gps_measurements) {
+            gps_data data;
+            get_binary(buff, &offset, (char*)&data, sizeof(buff), sizeof(gps_data));
+            hdlr->gps_measurements(data);
+        } else {
+            LOGE("mnl2hal_hdlr() gps_measurements is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GPS_NAVIGATION: {
+        if (hdlr->gps_navigation) {
+            gps_nav_msg msg;
+            get_binary(buff, &offset, (char*)&msg, sizeof(buff), sizeof(gps_nav_msg));
+            hdlr->gps_navigation(msg);
+        } else {
+            LOGE("mnl2hal_hdlr() gps_navigation is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GNSS_MEASUREMENTS: {
+        if (hdlr->gnss_measurements) {
+            gnss_data data;
+            get_binary(buff, &offset, (char*)&data, sizeof(buff), sizeof(gnss_data));
+            hdlr->gnss_measurements(data);
+        } else {
+            LOGE("mnl2hal_hdlr() gnss_measurements is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_GNSS_NAVIGATION: {
+        if (hdlr->gnss_navigation) {
+            gnss_nav_msg msg;
+            get_binary(buff, &offset, (char*)&msg, sizeof(buff), sizeof(gnss_nav_msg));
+            hdlr->gnss_navigation(msg);
+        } else {
+            LOGE("mnl2hal_hdlr() gnss_navigation is NULL");
+            ret = -1;
+        }
+        break;
+    }
+
+    case MNL2HAL_REQUEST_WAKELOCK: {
+        if (hdlr->request_wakelock) {
+            hdlr->request_wakelock();
+        } else {
+            LOGE("mnl2hal_hdlr() request_wakelock is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_RELEASE_WAKELOCK: {
+        if (hdlr->release_wakelock) {
+            hdlr->release_wakelock();
+        } else {
+            LOGE("mnl2hal_hdlr() release_wakelock is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_REQUEST_UTC_TIME: {
+        if (hdlr->request_utc_time) {
+            hdlr->request_utc_time();
+        } else {
+            LOGE("mnl2hal_hdlr() request_utc_time is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_REQUEST_DATA_CONN: {
+        if (hdlr->request_data_conn) {
+            struct sockaddr_storage addr;
+            get_binary(buff, &offset, (char*)&addr, sizeof(buff), sizeof(addr));
+            hdlr->request_data_conn(&addr);
+        } else {
+            LOGE("mnl2hal_hdlr() request_data_conn is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_RELEASE_DATA_CONN: {
+        if (hdlr->release_data_conn) {
+            hdlr->release_data_conn();
+        } else {
+            LOGE("mnl2hal_hdlr() release_data_conn is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_REQUEST_NI_NOTIFY: {
+        if (hdlr->request_ni_notify) {
+            int session_id = get_int(buff, &offset, sizeof(buff));
+            agps_notify_type type = get_int(buff, &offset, sizeof(buff));
+            char* requestor_id = get_string(buff, &offset, sizeof(buff));
+            char* client_name = get_string(buff, &offset, sizeof(buff));
+            ni_encoding_type requestor_id_encoding = get_int(buff, &offset, sizeof(buff));
+            ni_encoding_type client_name_encoding  = get_int(buff, &offset, sizeof(buff));
+            hdlr->request_ni_notify(session_id, type, requestor_id, client_name,
+                requestor_id_encoding, client_name_encoding);
+        } else {
+            LOGE("mnl2hal_hdlr() request_ni_notify is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_REQUEST_SET_ID: {
+        if (hdlr->request_set_id) {
+            request_setid flags = get_int(buff, &offset, sizeof(buff));
+            hdlr->request_set_id(flags);
+        } else {
+            LOGE("mnl2hal_hdlr() request_set_id is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_REQUEST_REF_LOC: {
+        if (hdlr->request_ref_loc) {
+            request_refloc flags = get_int(buff, &offset, sizeof(buff));
+            hdlr->request_ref_loc(flags);
+        } else {
+            LOGE("mnl2hal_hdlr() request_ref_loc is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_VZW_DEBUG_OUTPUT: {
+        if (hdlr->output_vzw_debug) {
+            char* str = get_string(buff, &offset, sizeof(buff));
+            hdlr->output_vzw_debug(str);
+        } else {
+            LOGE("mnl2hal_hdlr() output_vzw_debug is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_UPDATE_GNSS_NAME: {
+        if (hdlr->update_gnss_name) {
+            int length = get_int(buff, &offset, sizeof(buff));
+            char* name = get_string(buff, &offset, sizeof(buff));
+            hdlr->update_gnss_name(name, length);
+        } else {
+            LOGE("mnl2hal_hdlr() update_gnss_name is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case MNL2HAL_REQUEST_NLP: {
+        if (hdlr->request_nlp) {
+            bool independentFromGnss = get_byte(buff, &offset, sizeof(buff));
+            hdlr->request_nlp(independentFromGnss);
+        } else {
+            LOGE("mnl2hal_hdlr() update_gnss_name is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    default: {
+        LOGE("mnl2hal_hdlr() unknown cmd=%d", cmd);
+        ret = -1;
+        break;
+    }
+    }
+
+    return ret;
+}
+
+// -1 means failure
+int create_mnl2hal_fd() {
+    int fd = socket_bind_udp(MTK_MNL2HAL);
+    socket_set_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/gps_hal/src/hal_mnl_interface_common.c b/src/connectivity/gps/gps_hal/src/hal_mnl_interface_common.c
new file mode 100644
index 0000000..5a691a1
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/hal_mnl_interface_common.c
@@ -0,0 +1,173 @@
+#include <inttypes.h>
+
+#include "hal_mnl_interface_common.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gpshal_dump"
+#endif
+
+#if 0
+void dump_gps_location(gps_location in) {
+    LOGD("===== dump_gps_location ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("lat=%f", in.lat);
+    LOGD("lng=%f", in.lng);
+    LOGD("alt=%f", in.alt);
+    LOGD("speed=%f", in.speed);
+    LOGD("bearing=%f", in.bearing);
+    LOGD("accuracy=%f", in.accuracy);
+    LOGD("timestamp=%"PRId64, in.timestamp);
+}
+
+void dump_gnss_sv(gnss_sv in) {
+    LOGD("===== dump_gnss_sv ====");
+    LOGD("prn=%d", in.svid);
+    LOGD("constellation=%d", in.constellation);
+    LOGD("snr=%f", in.c_n0_dbhz);
+    LOGD("elevation=%f", in.elevation);
+    LOGD("azimuth=%f", in.azimuth);
+    LOGD("flags=%d", in.flags);
+}
+
+void dump_gnss_sv_info(gnss_sv_info in) {
+    int i = 0;
+    LOGD("===== dump_gnss_sv_info ====");
+    LOGD("num_svs=%d", in.num_svs);
+    for (i = 0; i < in.num_svs; i++) {
+        LOGD("i=%d", i);
+        dump_gnss_sv(in.sv_list[i]);
+    }
+}
+
+void dump_gps_measurement(gps_measurement in) {
+    LOGD("===== dump_gps_measurement ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("prn=%d", in.prn);
+    LOGD("time_offset_ns=%f", in.time_offset_ns);
+    LOGD("state=0x%x", in.state);
+    LOGD("received_gps_tow_ns=%"PRId64, in.received_gps_tow_ns);
+    LOGD("received_gps_tow_uncertainty_ns=%"PRId64, in.received_gps_tow_uncertainty_ns);
+    LOGD("c_n0_dbhz=%f", in.c_n0_dbhz);
+    LOGD("pseudorange_rate_mps=%f", in.pseudorange_rate_mps);
+    LOGD("pseudorange_rate_uncertainty_mps=%f", in.pseudorange_rate_uncertainty_mps);
+    LOGD("accumulated_delta_range_state=0x%x", in.accumulated_delta_range_state);
+    LOGD("accumulated_delta_range_m=%f", in.accumulated_delta_range_m);
+    LOGD("accumulated_delta_range_uncertainty_m=%f", in.accumulated_delta_range_uncertainty_m);
+    LOGD("pseudorange_m=%f", in.pseudorange_m);
+    LOGD("pseudorange_uncertainty_m=%f", in.pseudorange_uncertainty_m);
+    LOGD("code_phase_chips=%f", in.code_phase_chips);
+    LOGD("code_phase_uncertainty_chips=%f", in.code_phase_uncertainty_chips);
+    LOGD("carrier_frequency_hz=%f", in.carrier_frequency_hz);
+    LOGD("carrier_cycles=%"PRId64, in.carrier_cycles);
+    LOGD("carrier_phase=%f", in.carrier_phase);
+    LOGD("carrier_phase_uncertainty=%f", in.carrier_phase_uncertainty);
+    LOGD("loss_of_lock=%d", in.loss_of_lock);
+    LOGD("bit_number=%d", in.bit_number);
+    LOGD("time_from_last_bit_ms=%d", in.time_from_last_bit_ms);
+    LOGD("doppler_shift_hz=%f", in.doppler_shift_hz);
+    LOGD("doppler_shift_uncertainty_hz=%f", in.doppler_shift_uncertainty_hz);
+    LOGD("multipath_indicator=%d", in.multipath_indicator);
+    LOGD("snr_db=%f", in.snr_db);
+    LOGD("elevation_deg=%f", in.elevation_deg);
+    LOGD("elevation_uncertainty_deg=%f", in.elevation_uncertainty_deg);
+    LOGD("azimuth_deg=%f", in.azimuth_deg);
+    LOGD("azimuth_uncertainty_deg=%f", in.azimuth_uncertainty_deg);
+    LOGD("used_in_fix=%d", in.used_in_fix);
+}
+
+void dump_gps_clock(gps_clock in) {
+    LOGD("===== dump_gps_clock ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("leap_second=%d", in.leap_second);
+    LOGD("type=%d", in.type);
+    LOGD("time_ns=%"PRId64, in.time_ns);
+    LOGD("time_uncertainty_ns=%f", in.time_uncertainty_ns);
+    LOGD("full_bias_ns=%"PRId64, in.full_bias_ns);
+    LOGD("bias_ns=%f", in.bias_ns);
+    LOGD("bias_uncertainty_ns=%f", in.bias_uncertainty_ns);
+    LOGD("drift_nsps=%f", in.drift_nsps);
+    LOGD("drift_uncertainty_nsps=%f", in.drift_uncertainty_nsps);
+}
+
+void dump_gps_data(gps_data in) {
+    size_t i = 0;
+    LOGD("===== dump_gps_data ====");
+    LOGD("measurement_count=%zu", in.measurement_count);
+    for (i = 0; i < in.measurement_count; i++) {
+        LOGD("i=%zu", i);
+        dump_gps_measurement(in.measurements[i]);
+    }
+    dump_gps_clock(in.clock);
+}
+
+void dump_gps_nav_msg(gps_nav_msg in) {
+    LOGD("===== dump_gps_nav_msg ====");
+    LOGD("prn=%d", in.prn);
+    LOGD("type=%d", in.type);
+    LOGD("status=0x%x", in.status);
+    LOGD("message_id=%d", in.message_id);
+    LOGD("submessage_id=%d", in.submessage_id);
+    LOGD("data_length=%zu", in.data_length);
+}
+
+void dump_gnss_data(gnss_data in) {
+    size_t i = 0;
+    LOGD("===== dump_gnss_data ====");
+    LOGD("measurement_count=%zu", in.measurement_count);
+    for (i = 0; i < in.measurement_count; i++) {
+        LOGD("i=%zu", i);
+        dump_gnss_measurement(in.measurements[i]);
+    }
+    dump_gnss_clock(in.clock);
+}
+
+void dump_gnss_measurement(gnss_measurement in) {
+    LOGD("===== dump_gnss_measurement ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("svid=%d", in.svid);
+    LOGD("constellation=0x%x", in.constellation);
+    LOGD("time_offset_ns=%f", in.time_offset_ns);
+    LOGD("state=0x%x", in.state);
+    LOGD("received_gps_tow_ns=%"PRId64, in.received_sv_time_in_ns);
+    LOGD("received_gps_tow_uncertainty_ns=%"PRId64, in.received_sv_time_uncertainty_in_ns);
+    LOGD("c_n0_dbhz=%f", in.c_n0_dbhz);
+    LOGD("pseudorange_rate_mps=%f", in.pseudorange_rate_mps);
+    LOGD("pseudorange_rate_uncertainty_mps=%f", in.pseudorange_rate_uncertainty_mps);
+    LOGD("accumulated_delta_range_state=0x%x", in.accumulated_delta_range_state);
+    LOGD("accumulated_delta_range_m=%f", in.accumulated_delta_range_m);
+    LOGD("accumulated_delta_range_uncertainty_m=%f", in.accumulated_delta_range_uncertainty_m);;
+    LOGD("carrier_frequency_hz=%f", in.carrier_frequency_hz);
+    LOGD("carrier_cycles=%"PRId64, in.carrier_cycles);
+    LOGD("carrier_phase=%f", in.carrier_phase);
+    LOGD("carrier_phase_uncertainty=%f", in.carrier_phase_uncertainty);
+    LOGD("multipath_indicator=%d", in.multipath_indicator);
+    LOGD("snr_db=%f", in.snr_db);
+}
+
+void dump_gnss_clock(gnss_clock in) {
+    LOGD("===== dump_gnss_clock ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("leap_second=%d", in.leap_second);
+    LOGD("time_ns=%"PRId64, in.time_ns);
+    LOGD("time_uncertainty_ns=%f", in.time_uncertainty_ns);
+    LOGD("full_bias_ns=%"PRId64, in.full_bias_ns);
+    LOGD("bias_ns=%f", in.bias_ns);
+    LOGD("bias_uncertainty_ns=%f", in.bias_uncertainty_ns);
+    LOGD("drift_nsps=%f", in.drift_nsps);
+    LOGD("drift_uncertainty_nsps=%f", in.drift_uncertainty_nsps);
+    LOGD("hw_clock_discontinuity_count=%d", in.hw_clock_discontinuity_count);
+}
+
+void dump_gnss_nav_msg(gnss_nav_msg in) {
+    LOGD("===== dump_gnss_nav_msg ====");
+    LOGD("svid=%d", in.svid);
+    LOGD("type=%d", in.type);
+    LOGD("status=0x%x", in.status);
+    LOGD("message_id=%d", in.message_id);
+    LOGD("submessage_id=%d", in.submessage_id);
+    LOGD("data_length=%zu", in.data_length);
+}
+#endif
diff --git a/src/connectivity/gps/gps_hal/src/mtk_auto_log.c b/src/connectivity/gps/gps_hal/src/mtk_auto_log.c
new file mode 100644
index 0000000..33ab38f
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/mtk_auto_log.c
@@ -0,0 +1,109 @@
+/*
+* 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.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "mtk_auto_log.h"
+
+#if defined(__LINUX_OS__)
+// -1 means failure
+int get_time_str(char* buf, int len) {
+    struct timeval  tv;
+    struct timezone tz;
+    struct tm      *tm;
+
+    gettimeofday(&tv, &tz);
+    tm = localtime(&tv.tv_sec);
+
+    memset(buf, 0, len);
+    sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+        tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+        tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+    return 0;
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+    ALOGI("Current debug level=%d", *dst_level);
+
+    if (src_level < L_VERBOSE || src_level >  L_SUPPRESS)
+    {
+        ALOGE("Invalid debug level, level=%d", src_level);
+        ALOGE("  [level] -");
+        ALOGE("  QUIET      = 6");
+        ALOGE("  ASSERT     = 5");
+        ALOGE("  ERROR      = 4");
+        ALOGE("  WARNING    = 3");
+        ALOGE("  INFO       = 2");
+        ALOGE("  DEBUG      = 1");
+        ALOGE("  LOGALL     = 0");
+        return -1;
+    }
+
+    *dst_level = src_level;
+
+    ALOGI("New debug level=%d", *dst_level);
+
+#elif defined(__LINUX_OS__)
+
+    printf("Current debug level=%d\n", *dst_level);
+
+    if (src_level < L_VERBOSE || src_level >  L_SUPPRESS)
+    {
+        printf("Invalid debug level, level=%d\n", src_level);
+        printf("  [level] -\n");
+        printf("  QUIET      = 6\n");
+        printf("  ASSERT     = 5\n");
+        printf("  ERROR      = 4\n");
+        printf("  WARNING    = 3\n");
+        printf("  INFO       = 2\n");
+        printf("  DEBUG      = 1\n");
+        printf("  LOGALL     = 0\n");
+        return -1;
+    }
+
+    *dst_level = src_level;
+
+    printf("New debug level=%d\n", *dst_level);
+
+#endif
+    return 0;
+}
diff --git a/src/connectivity/gps/gps_hal/src/mtk_lbs_utility.c b/src/connectivity/gps/gps_hal/src/mtk_lbs_utility.c
new file mode 100644
index 0000000..cd51ad9
--- /dev/null
+++ b/src/connectivity/gps/gps_hal/src/mtk_lbs_utility.c
@@ -0,0 +1,296 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h>  // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>  // usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h>  // inet_addr
+#include <sys/un.h>  // struct sockaddr_un
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <signal.h>
+#include <semaphore.h>
+
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_lbs_utility"
+#endif
+
+void msleep(int interval) {
+    usleep(interval * 1000);
+}
+
+// in millisecond
+time_t get_tick() {
+    struct timespec ts;
+    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+        LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+        return -1;
+    }
+    return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+time_t get_time_in_millisecond() {
+    struct timespec ts;
+    if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+        LOGE("get_time_in_millisecond  failed reason=[%s]", strerror(errno));
+        return -1;
+    }
+    return ((long long)ts.tv_sec*1000) + ((long long)ts.tv_nsec/1000000);
+}
+#ifdef __LINUX_OS__ 
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+timer_t init_timer_id(timer_callback cb, int id) {
+    struct sigevent sevp;
+    timer_t timerid;
+
+    memset(&sevp, 0, sizeof(sevp));
+    sevp.sigev_value.sival_int = id;
+    sevp.sigev_notify = SIGEV_THREAD;
+    sevp.sigev_notify_function = cb;
+
+    if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {
+        LOGE("timer_create  failed reason=[%s]", strerror(errno));
+        return (timer_t)-1;
+    }
+    return timerid;
+}
+
+// -1 means failure
+timer_t init_timer(timer_callback cb) {
+    return init_timer_id(cb, 0);
+}
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds) {
+    struct itimerspec expire;
+    expire.it_interval.tv_sec = 0;
+    expire.it_interval.tv_nsec = 0;
+    expire.it_value.tv_sec = milliseconds/1000;
+    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+    return timer_settime(timerid, 0, &expire, NULL);
+}
+
+// -1 means failure
+int stop_timer(timer_t timerid) {
+    return start_timer(timerid, 0);
+}
+
+// -1 means failure
+int deinit_timer(timer_t timerid) {
+    if (timer_delete(timerid) == -1) {
+        // errno
+        return -1;
+    }
+    return 0;
+}
+
+#endif
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = EPOLLIN;
+    // don't set the fd to edge trigger
+    // the some event like accept may be lost if two or more clients are connecting to server at the same time
+    // level trigger is preferred to avoid event lost
+    // do not set EPOLLOUT due to it will always trigger when write is available
+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        LOGE("epoll_add_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+            strerror(errno), errno, epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+// -1 failed
+int epoll_add_fd2(int epfd, int fd, uint32_t events) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = events;
+    // don't set the fd to edge trigger
+    // the some event like accept may be lost if two or more clients are connecting to server at the same time
+    // level trigger is preferred to avoid event lost
+    // do not set EPOLLOUT due to it will always trigger when write is available
+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        LOGE("epoll_add_fd2() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+            strerror(errno), errno, epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+int epoll_del_fd(int epfd, int fd) {
+    struct epoll_event  ev;
+    int                 ret;
+
+    if (epfd == -1)
+        return -1;
+
+    ev.events  = EPOLLIN;
+    ev.data.fd = fd;
+    do {
+        ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
+// -1 failed
+int epoll_mod_fd(int epfd, int fd, uint32_t events) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = events;
+    if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+        LOGE("epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+            strerror(errno), errno, epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_bind_udp(const char* path) {
+    int fd;
+    struct sockaddr_un addr;
+
+    fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("socket_bind_udp() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    LOGD("fd=%d,path=%s\n", fd, path);
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_path[0] = 0;
+    MNLD_STRNCPY(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);
+    addr.sun_family = AF_UNIX;
+    unlink(path);
+
+    if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+        LOGE("socket_bind_udp() bind() failed path=[%s] reason=[%s]%d",
+            addr.sun_path+1, strerror(errno), errno);
+        close(fd);
+        return -1;
+    }else
+        LOGI("bind ok path=[%s]", addr.sun_path+1);
+    return fd;
+}
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking) {
+    if (fd < 0) {
+        LOGE("socket_set_blocking() invalid fd=%d", fd);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags == -1) {
+        LOGE("socket_set_blocking() fcntl() failed invalid flags=%d reason=[%s]%d",
+            flags, strerror(errno), errno);
+        return -1;
+    }
+
+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len) {
+    int ret = 0;
+    struct sockaddr_un addr;
+    int retry = 10;
+    int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("safe_sendto() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){
+        LOGE("fcntl failed reason=[%s]%d",
+                    strerror(errno), errno);
+
+        close(fd);
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_path[0] = 0;
+    MNLD_STRNCPY(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);
+    addr.sun_family = AF_UNIX;
+
+    while ((ret = sendto(fd, buff, len, 0,
+        (const struct sockaddr *)&addr, sizeof(addr))) == -1) {
+        if (errno == EINTR) {
+            LOGE("errno==EINTR\n");
+            continue;
+        }
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                LOGE("errno==EAGAIN\n");
+                continue;
+            }
+        }
+        LOGE("safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",
+            path, ret, strerror(errno), errno);
+        break;
+    }
+
+    close(fd);
+    return ret;
+}
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len) {
+    int ret = 0;
+    int retry = 10;
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){
+        LOGE("fcntl failed reason=[%s]%d",
+                    strerror(errno), errno);
+
+        close(fd);
+        return -1;
+    }
+
+    while ((ret = recvfrom(fd, buff, len, 0,
+         NULL, NULL)) == -1) {
+        LOGW("safe_recvfrom() ret=%d len=%d", ret, len);
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("safe_recvfrom() recvfrom() failed reason=[%s]%d",
+            strerror(errno), errno);
+        break;
+    }
+    return ret;
+}
diff --git a/src/connectivity/gps/lbs_hidl_service/Android.backup b/src/connectivity/gps/lbs_hidl_service/Android.backup
new file mode 100644
index 0000000..562ca85
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/Android.backup
@@ -0,0 +1,57 @@
+LOCAL_PATH := $(call my-dir)

+

+include $(CLEAR_VARS)

+LOCAL_MODULE := lbs_hidl_service-impl

+LOCAL_PROPRIETARY_MODULE := true

+

+LOCAL_C_INCLUDES += \

+    $(LOCAL_PATH)/mtk_socket_utils/inc \

+

+LOCAL_SRC_FILES := \

+    lbs_hidl_service.cpp \

+    mtk_socket_utils/src/mtk_socket_data_coder.c \

+    mtk_socket_utils/src/mtk_socket_utils.c \

+

+

+LOCAL_SHARED_LIBRARIES := \

+    liblog \

+    libcutils \

+    libdl \

+    libbase \

+    libhardware \

+    libbinder \

+    libhidlbase \

+    libhidltransport \

+    libutils \

+    vendor.mediatek.hardware.lbs@1.0_vendor \

+

+include $(BUILD_SHARED_LIBRARY)

+

+

+include $(CLEAR_VARS)

+

+LOCAL_MODULE := lbs_hidl_service

+LOCAL_PROPRIETARY_MODULE := true

+LOCAL_INCLUDE_MTK_GLOBAL_CONFIGS := no

+LOCAL_INIT_RC := lbs_hidl_service.rc

+

+LOCAL_C_INCLUDES += \

+    $(LOCAL_PATH)/mtk_socket_utils/inc \

+

+LOCAL_SRC_FILES := \

+    service.cpp \

+

+LOCAL_SHARED_LIBRARIES := \
+    liblog \

+    libcutils \
+    libdl \
+    libbase \

+    libhardware \
+    libbinder \

+    libhidlbase \
+    libhidltransport \
+    libutils \

+    vendor.mediatek.hardware.lbs@1.0_vendor \

+    lbs_hidl_service-impl \

+

+include $(BUILD_EXECUTABLE)

diff --git a/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.cpp b/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.cpp
new file mode 100644
index 0000000..1ed5ee2
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.cpp
@@ -0,0 +1,573 @@
+#include <android/log.h>
+#include <unistd.h>    // usleep
+#include <sys/epoll.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <cutils/properties.h>
+
+#include <hidl/LegacySupport.h>
+
+#include "lbs_hidl_service.h"
+
+namespace vendor {
+namespace mediatek {
+namespace hardware {
+namespace lbs {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::wp;
+using ::android::status_t;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hidl::base::V1_0::IBase;
+
+char g_ver[] = "1.05";
+// 1.01 add agps_apn <-> lbs hidl service
+// 1.02 add mnld -> lbs hidl service
+// 1.03 add synchronization for HIDL callback from server to client
+// 1.04 add HAL callback return value check
+// 1.05 add handler timer to restart
+
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "lbs_hidl_service", __VA_ARGS__);
+#define LOGE  LOGD
+
+#define LBS_HANDLER_TIMEOUT        (30 * 1000)
+#define MAX_EPOLL_EVENT 50
+typedef void (* timer_callback)(sigval_t sig);
+int g_epfd = epoll_create(MAX_EPOLL_EVENT);
+int handleCase = 0;
+
+// LPPe Service
+sp<LbsHidlService> hidlLPPeAgps;
+sp<LbsHidlService> hidlLPPeWlan;
+sp<LbsHidlService> hidlLPPeBT;
+sp<LbsHidlService> hidlLPPeSensor;
+sp<LbsHidlService> hidlLPPeNetwork;
+sp<LbsHidlService> hidlLPPeIpAddr;
+sp<LbsHidlService> hidlLPPeLbs;
+sp<LbsHidlService> hidlApn2Agps;
+sp<LbsHidlService> hidlMnld2NlpUtils;
+sp<LbsHidlService> hidlMnld2DebugService;
+sp<LbsHidlService> hidlDebugService2Mnld;
+sp<LbsHidlService> hidlMeta2Mnld;
+
+
+// LocationEM, CMCC AGPS Settings, OP01
+sp<LbsHidlService> hidlAgpsInterface;
+sp<AgpsDebugInterfaceHidlService> hidlAgpsDebugInterface;
+sp<Agps2ApnHidlService> hidlAgps2Apn;
+
+
+void covertVector2Array(std::vector<uint8_t> in, char* out) {
+    int size = in.size();
+    for(int i = 0; i < size; i++) {
+        out[i] = in.at(i);
+    }
+}
+
+void covertArray2Vector(const char* in, int len, std::vector<uint8_t>& out) {
+    out.clear();
+    for(int i = 0; i < len; i++) {
+        out.push_back(in[i]);
+    }
+}
+
+void dump_vector(std::vector<uint8_t>& vec) {
+    LOGD("dump_vector() size=%d\n", (int)vec.size());
+    for(int i = 0; i < (int)vec.size(); i++) {
+        LOGD(" i=%d %02x\n", i, vec.at(i) & 0xff);
+    }
+}
+
+void dump_buff(const char* buff, int len) {
+    int i = 0;
+    LOGD("dump_buff() len=%d\n", len);
+    for(i = 0; i < len; i++) {
+        LOGD(" i=%d %02x\n", i, buff[i] & 0xff);
+    }
+}
+
+static void msleep(int interval) {
+    usleep(interval * 1000);
+}
+
+//-1 failed
+int epoll_add_fd(int epfd, int fd) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = EPOLLIN;
+    //don't set the fd to edge trigger
+    //the some event like accept may be lost if two or more clients are connecting to server at the same time
+    //level trigger is preferred to avoid event lost
+    //do not set EPOLLOUT due to it will always trigger when write is available
+    if(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        LOGE("epoll_add_fd() epoll_ctl() failure reason=[%s]  epfd=%d fd=%d\n", strerror(errno), epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+//LbsHidlService
+LbsHidlService::LbsHidlService(const char* name) :
+        mLbsHidlDeathRecipient(new LbsHidlDeathRecipient(this)) {
+
+    safe_strncpy(mName, name, sizeof(mName));
+    status_t status;
+    status = this->registerAsService(mName);
+    if(status != 0) {
+        LOGE("[%s] LbsHidlService() registerAsService() for name=[%s] failed status=[%d]",
+            g_ver, mName, status);
+    }
+    mLbsCallback = nullptr;
+    sem_init(&mSem, 0, 1);
+}
+
+LbsHidlService::~LbsHidlService() {
+    LOGD("[%s] ~LbsHidlService()", g_ver);
+    sem_destroy(&mSem);
+}
+
+Return<void> LbsHidlService::setCallback(const sp<ILbsCallback>& callback) {
+    LOGD("[%s][%s] setCallback()", g_ver, mName);
+    mLbsCallback = callback;
+    mLbsCallback->linkToDeath(mLbsHidlDeathRecipient, 0);
+    return Void();
+}
+
+Return<bool> LbsHidlService::sendToServer(const hidl_vec<uint8_t>& data) {
+    std::vector<uint8_t> tmp = data;
+    bool ret = false;
+    LOGE("[%s][%s] sendToServer() size=[%d] TBD!!!!", g_ver, mName, (int)tmp.size());
+    dump_vector(tmp);
+    return ret;
+}
+
+Return<bool> LbsHidlService::sendToServerWithCallback(const sp<ILbsCallback>& callback, const hidl_vec<uint8_t>& data) {
+    UNUSED(callback);
+    std::vector<uint8_t> tmp = data;
+    bool ret = false;
+    LOGE("[%s][%s] sendToServerWithCallback() size=[%d] TBD!!!", g_ver, mName, (int)tmp.size());
+    dump_vector(tmp);
+    return ret;
+}
+
+void LbsHidlService::handleHidlDeath() {
+    sem_wait(&mSem);
+    LOGD("[%s][%s] handleHidlDeath()", g_ver, mName);
+    mLbsCallback = nullptr;
+    sem_post(&mSem);
+}
+
+bool LbsHidlService::handleSocketEvent(int fd) {
+    int _ret;
+    int _offset = 0;
+    char _buff[16 * 1024] = {0};
+
+    _ret = read(fd, _buff, sizeof(_buff));
+    LOGD("[%s][%s] handleSocketEvent() ret=[%d]", g_ver, mName, _ret);
+    if(_ret == -1) {
+        LOGE("[%s][%s] handleSocketEvent() read() failed, fd=%d err=[%s]%d",
+            g_ver, mName, fd, strerror(errno), errno);
+        return false;
+    }
+    sem_wait(&mSem);
+    if(mLbsCallback != nullptr) {
+        std::vector<uint8_t> tmp;
+        covertArray2Vector(_buff, _ret, tmp);
+        auto ret = mLbsCallback->callbackToClient(tmp);
+        if (!ret.isOk()) {
+            LOGE("[%s][%s] handleSocketEvent() callbackToClient() failed", g_ver, mName);
+        }
+    }
+    sem_post(&mSem);
+    return true;
+}
+
+//UdpHidlService
+UdpHidlService::UdpHidlService(const char* name) : LbsHidlService(name) {
+    mtk_socket_client_init_local(&mSocketLPPe, mName, SOCK_NS_ABSTRACT);
+}
+
+Return<bool> UdpHidlService::sendToServer(const hidl_vec<uint8_t>& data) {
+    std::vector<uint8_t> tmp = data;
+    LOGD("[%s][%s] sendToServer() size=[%d]", g_ver, mName, (int)tmp.size());
+
+
+    if(!mtk_socket_client_connect(&mSocketLPPe)) {
+        LOGE("[%s][%s] sendToServer() mtk_socket_client_connect() failed", g_ver, mName);
+        return false;
+    }
+    //dump_vector(tmp);
+    char _buff[16 * 1024] = {0};
+    int _offset = (int)tmp.size();
+    covertVector2Array(data, _buff);
+    //dump_buff(_buff, _offset);
+    int _ret = mtk_socket_write(mSocketLPPe.fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("[%s][%s] sendToServer() mtk_socket_write() failed", g_ver, mName);
+        return false;
+    }
+    mtk_socket_client_close(&mSocketLPPe);
+    return true;
+}
+
+//AgpsInterfaceHidlService
+AgpsInterfaceHidlService::AgpsInterfaceHidlService(const char* name) : LbsHidlService(name) {
+}
+
+Return<bool> AgpsInterfaceHidlService::sendToServerWithCallback(const sp<ILbsCallback>& callback, const hidl_vec<uint8_t>& data) {
+    std::vector<uint8_t> tmp = data;
+    char buff[16 * 1024] = {0};
+    bool ret = true;
+    int read_len = 0;
+    LOGD("[%s][%s] sendToServerWithCallback() size=%d", g_ver, mName, (int)tmp.size());
+    int fd = mtk_socket_tcp_connect_local("/dev/socket/agpsd2", SOCK_NS_FILESYSTEM);
+    if(fd < 0) {
+        LOGE("[%s][%s] mtk_socket_tcp_connect_local() failed", g_ver, mName);
+        return false;
+    }
+    covertVector2Array(data, buff);
+    read_len = mtk_socket_write(fd, buff, (int)tmp.size());
+    if(read_len == -1) {
+        ret = false;
+    }
+    memset(buff, 0, sizeof(buff));
+    read_len = 0;
+    if(ret) {
+        read_len = read(fd, buff, sizeof(buff));
+    }
+    close(fd);
+    covertArray2Vector(buff, read_len, tmp);
+    auto _ret = callback->callbackToClient(tmp);
+    if (!_ret.isOk()) {
+        LOGE("[%s][%s] sendToServerWithCallback() callbackToClient() failed", g_ver, mName);
+    }
+    return ret;
+}
+
+//AgpsDebugInterfaceHidlService
+AgpsDebugInterfaceHidlService::AgpsDebugInterfaceHidlService(const char* name) : LbsHidlService(name) {
+    mSocketFd = -1;
+    mIsExit = true;
+}
+
+Return<void> AgpsDebugInterfaceHidlService::setCallback(const sp<ILbsCallback>& callback) {
+    LOGD("[%s][%s] setCallback()", g_ver, mName);
+    mLbsCallback = callback;
+    mLbsCallback->linkToDeath(mLbsHidlDeathRecipient, 0);
+    mSocketFd = mtk_socket_tcp_connect_local("/dev/socket/agpsd3", SOCK_NS_FILESYSTEM);
+    if(mSocketFd < 0) {
+        LOGE("[%s][%s] setCallback() mtk_socket_tcp_connect_local() failed", g_ver, mName);
+        return Void();
+    }
+    epoll_add_fd(g_epfd, mSocketFd);
+    mIsExit = false;
+    return Void();
+}
+
+Return<bool> AgpsDebugInterfaceHidlService::sendToServer(const hidl_vec<uint8_t>& data) {
+    std::vector<uint8_t> tmp = data;
+    LOGD("[%s][%s] sendToServer() size=[%d]", g_ver, mName, (int)tmp.size());
+    char buff[16 * 1024] = {0};
+    int read_len = 0;
+    covertVector2Array(data, buff);
+    read_len = mtk_socket_write(mSocketFd, buff, (int)tmp.size());
+    // we don't care the error happens in this scenario
+    UNUSED(read_len);
+    mIsExit = true;
+    return true;
+}
+
+bool AgpsDebugInterfaceHidlService::handleSocketEvent(int fd) {
+    int _ret;
+    char _buff[16 * 1024] = {0};
+
+    _ret = read(fd, _buff, sizeof(_buff));
+    LOGD("[%s][%s] handleSocketEvent() ret=[%d] isExit=[%d]", g_ver, mName, _ret, mIsExit);
+    if(mIsExit) {
+        close(mSocketFd);
+    } else if (_ret <= 0) {
+        LOGE("[%s][%s] handleSocketEvent() read() failed, fd=%d err=[%s]%d",
+            g_ver, mName, fd, strerror(errno), errno);
+        close(mSocketFd);
+        mSocketFd = -1;
+        while(mSocketFd < 0) {
+            msleep(500);
+            mSocketFd = mtk_socket_tcp_connect_local("/dev/socket/agpsd3", SOCK_NS_FILESYSTEM);
+            LOGD("[%s][%s] handleSocketEvent() mtk_socket_tcp_connect_local() mSocketFd=[%d]",
+                g_ver, mName, mSocketFd);
+            if(mSocketFd > 0) {
+                epoll_add_fd(g_epfd, mSocketFd);
+                break;
+            }
+        }
+        LOGD("[%s][%s] handleSocketEvent() re-connect done", g_ver, mName);
+    } else {
+        sem_wait(&mSem);
+        if(mLbsCallback != nullptr) {
+            std::vector<uint8_t> tmp;
+            covertArray2Vector(_buff, _ret, tmp);
+            auto ret = mLbsCallback->callbackToClient(tmp);
+            if (!ret.isOk()) {
+                LOGE("[%s][%s] handleSocketEvent() callbackToClient() failed", g_ver, mName);
+            }
+        }
+        sem_post(&mSem);
+    }
+    return true;
+}
+
+int AgpsDebugInterfaceHidlService::getSocketFd() {
+    return mSocketFd;
+}
+
+
+//Agps2ApnHidlService,  lbs hidl service -> agps_apn
+Agps2ApnHidlService::Agps2ApnHidlService(const char* name) : UdpHidlService(name) {
+    mSocketFd = -1;
+}
+
+Return<void> Agps2ApnHidlService::setCallback(const sp<ILbsCallback>& callback) {
+    LbsHidlService::setCallback(callback);
+
+    mSocketFd = mtk_socket_server_bind_local("mtk_agps2framework", SOCK_NS_ABSTRACT);
+    if(mSocketFd < 0) {
+        LOGE("[%s][%s] setCallback() mtk_socket_server_bind_local(mtk_agps2framework) failed", g_ver, mName);
+        return Void();
+    }
+    epoll_add_fd(g_epfd, mSocketFd);
+    return Void();
+}
+
+void Agps2ApnHidlService::handleHidlDeath() {
+    LbsHidlService::handleHidlDeath();
+
+    if (mSocketFd < 0) {
+        LOGE("[%s][%s] handleHidlDeath() error mSocketFd: %d", g_ver, mName, mSocketFd);
+        return;
+    }
+    close(mSocketFd);
+    mSocketFd = -1;
+}
+
+int Agps2ApnHidlService::getSocketFd() {
+    return mSocketFd;
+}
+
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+
+timer_t init_timer_id(timer_callback cb, int id) {
+    struct sigevent sevp;
+    timer_t timerid;
+
+    memset(&sevp, 0, sizeof(sevp));
+    sevp.sigev_value.sival_int = id;
+    sevp.sigev_notify = SIGEV_THREAD;
+    sevp.sigev_notify_function = cb;
+
+    if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {
+        LOGE("timer_create  failed reason=[%s]", strerror(errno));
+        return (timer_t)-1;
+    }
+    LOGE("successfully timer created id= %d", timerid);
+    return timerid;
+}
+
+// -1 means failure
+timer_t init_timer(timer_callback cb) {
+    return init_timer_id(cb, 0);
+}
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds) {
+    struct itimerspec expire;
+    expire.it_interval.tv_sec = 0;
+    expire.it_interval.tv_nsec = 0;
+    expire.it_value.tv_sec = milliseconds/1000;
+    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+    return timer_settime(timerid, 0, &expire, NULL);
+}
+
+// -1 means failure
+int stop_timer(timer_t timerid) {
+    return start_timer(timerid, 0);
+}
+
+// -1 means failure
+int deinit_timer(timer_t timerid) {
+    if (timer_delete(timerid) == -1) {
+        // errno
+        return -1;
+    }
+    return 0;
+}
+
+
+bool lbs_timeout_restart_enabled(void) {
+    char result[PROPERTY_VALUE_MAX] = {0};
+
+    if((property_get("ro.mtk_hidl_consolidation", result, NULL) != 0) && (result[0] == '1')) {
+        LOGD("LBS_timeout disabled because hidl service consolidation enabled!!!");
+        return false;
+    } else {
+        LOGD("LBS_timeout enabled because hidl service consolidation disabled!!!");
+        return true;
+    }
+}
+
+bool lbs_timeout_ne_enabled(void) {
+    char result[PROPERTY_VALUE_MAX] = {0};
+
+    if((property_get("debug.gps.mnld.ne", result, NULL) != 0) && (result[0] == '1')) {
+        LOGD("NE enabled!!!");
+        return true;
+    } else {
+        LOGD("NE disabled!!!");
+        return false;
+    }
+}
+
+static void crash_to_debug() {
+    int* crash = 0;
+    *crash = 100;
+}
+
+static void lbs_control_thread_timeout(sigval_t sig) {
+    UNUSED(sig);
+
+    LOGE("lbs_control timeout handleCase = %d", handleCase);
+    if (lbs_timeout_restart_enabled()) {
+        if (lbs_timeout_ne_enabled() == false) {
+            LOGE("lbs_control_thread_timeout() exit.");
+            exit(0);
+        } else {
+            LOGE("lbs_control_thread_timeout() crash here for debugging");
+            crash_to_debug();
+        }
+    }
+}
+
+static void* lbs_hidl_thread(void *arg) {
+    UNUSED(arg);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    int fd_lppe_wlan         = mtk_socket_server_bind_local("mtk_lppe_socket_wlan", SOCK_NS_ABSTRACT);
+    int fd_lppe_bt           = mtk_socket_server_bind_local("mtk_lppe_socket_bt", SOCK_NS_ABSTRACT);
+    int fd_lppe_sensor       = mtk_socket_server_bind_local("mtk_lppe_socket_sensor", SOCK_NS_ABSTRACT);
+    int fd_lppe_network      = mtk_socket_server_bind_local("mtk_lppe_socket_network", SOCK_NS_ABSTRACT);
+    int fd_lppe_ipaddr       = mtk_socket_server_bind_local("mtk_lppe_socket_ipaddr", SOCK_NS_ABSTRACT);
+    int fd_lppe_lbs          = mtk_socket_server_bind_local("mtk_lppe_socket_lbs", SOCK_NS_ABSTRACT);
+    int fd_mnld2nlputils     = mtk_socket_server_bind_local("mtk_mnld2nlputils", SOCK_NS_ABSTRACT);
+    int fd_mnld2debugService = mtk_socket_server_bind_local("mtk_mnld2debugService", SOCK_NS_ABSTRACT);
+    timer_t hdlr_timer       = init_timer(lbs_control_thread_timeout);
+
+    epoll_add_fd(g_epfd, fd_lppe_wlan);
+    epoll_add_fd(g_epfd, fd_lppe_bt);
+    epoll_add_fd(g_epfd, fd_lppe_sensor);
+    epoll_add_fd(g_epfd, fd_lppe_network);
+    epoll_add_fd(g_epfd, fd_lppe_ipaddr);
+    epoll_add_fd(g_epfd, fd_lppe_lbs);
+    epoll_add_fd(g_epfd, fd_mnld2nlputils);
+    epoll_add_fd(g_epfd, fd_mnld2debugService);
+
+    while(1) {
+        int i;
+        int n;
+
+        n = epoll_wait(g_epfd, events, MAX_EPOLL_EVENT , -1);
+        if(n == -1) {
+            if(errno == EINTR) {
+                continue;
+            } else {
+                LOGE("[%s] lbs_hidl_thread() epoll_wait() failure reason=[%s]\n", g_ver, strerror(errno));
+                return NULL;
+            }
+        }
+
+        start_timer(hdlr_timer, LBS_HANDLER_TIMEOUT);
+        for(i = 0; i < n; i++) {
+            if(events[i].data.fd == fd_lppe_wlan && events[i].events & EPOLLIN) {
+                handleCase = 1;
+                hidlLPPeWlan->handleSocketEvent(fd_lppe_wlan);
+            } else if(events[i].data.fd == fd_lppe_bt && events[i].events & EPOLLIN) {
+                handleCase = 2;
+                hidlLPPeBT->handleSocketEvent(fd_lppe_bt);
+            } else if(events[i].data.fd == fd_lppe_sensor && events[i].events & EPOLLIN) {
+                handleCase = 3;
+                hidlLPPeSensor->handleSocketEvent(fd_lppe_sensor);
+            } else if(events[i].data.fd == fd_lppe_network && events[i].events & EPOLLIN) {
+                handleCase = 4;
+                hidlLPPeNetwork->handleSocketEvent(fd_lppe_network);
+            } else if(events[i].data.fd == fd_lppe_ipaddr && events[i].events & EPOLLIN) {
+                handleCase = 5;
+                hidlLPPeIpAddr->handleSocketEvent(fd_lppe_ipaddr);
+            } else if(events[i].data.fd == fd_lppe_lbs && events[i].events & EPOLLIN) {
+                handleCase = 6;
+                hidlLPPeLbs->handleSocketEvent(fd_lppe_lbs);
+            } else if(events[i].data.fd == hidlAgpsDebugInterface->getSocketFd() && events[i].events & EPOLLIN) {
+                handleCase = 7;
+                hidlAgpsDebugInterface->handleSocketEvent(hidlAgpsDebugInterface->getSocketFd());
+            } else if(events[i].data.fd == hidlAgps2Apn->getSocketFd() && events[i].events & EPOLLIN) {
+                handleCase = 8;
+                hidlAgps2Apn->handleSocketEvent(hidlAgps2Apn->getSocketFd());
+            } else if(events[i].data.fd == fd_mnld2nlputils && events[i].events & EPOLLIN) {
+                handleCase = 9;
+                hidlMnld2NlpUtils->handleSocketEvent(fd_mnld2nlputils);
+            } else if(events[i].data.fd == fd_mnld2debugService && events[i].events & EPOLLIN) {
+                handleCase = 10;
+                hidlMnld2DebugService->handleSocketEvent(fd_mnld2debugService);
+            }
+        }
+        stop_timer(hdlr_timer);
+    }
+    return NULL;
+}
+
+int cpp_main() {
+    LOGD("[%s] lbs hidl service is running", g_ver);
+
+    ::android::hardware::configureRpcThreadpool(20, true);
+
+    hidlLPPeAgps      = new UdpHidlService("mtk_lppe_socket_agps");
+    hidlLPPeWlan      = new UdpHidlService("mtk_lppe_socket_wlan");
+    hidlLPPeBT        = new UdpHidlService("mtk_lppe_socket_bt");
+    hidlLPPeSensor    = new UdpHidlService("mtk_lppe_socket_sensor");
+    hidlLPPeNetwork   = new UdpHidlService("mtk_lppe_socket_network");
+    hidlLPPeIpAddr    = new UdpHidlService("mtk_lppe_socket_ipaddr");
+    hidlLPPeLbs       = new UdpHidlService("mtk_lppe_socket_lbs");
+
+    // agps_apn -> lbs hidl service
+    hidlApn2Agps = new UdpHidlService("mtk_framework2agps");
+    // lbs hidl service -> agps_apn
+    hidlAgps2Apn = new Agps2ApnHidlService("mtk_agps2framework");
+    // mnld -> lbs hidl service
+    hidlMnld2NlpUtils = new UdpHidlService("mtk_mnld2nlputils");
+    // mnld -> debug service
+    hidlMnld2DebugService = new UdpHidlService("mtk_mnld2debugService");
+    // debug service  -> mnld
+    hidlDebugService2Mnld = new UdpHidlService("mtk_debugService2mnld");
+    // meta  -> mnld
+    hidlMeta2Mnld = new UdpHidlService("mtk_meta2mnld");
+
+    hidlAgpsInterface = new AgpsInterfaceHidlService("AgpsInterface");
+    hidlAgpsDebugInterface = new AgpsDebugInterfaceHidlService("AgpsDebugInterface");
+
+    // ... add more LBS HIDL Service here
+
+    pthread_t pthread1;
+    pthread_create(&pthread1, NULL, lbs_hidl_thread, NULL);
+
+    return 0;
+}
+
+}  // implementation
+}  // namespace V1_0
+}  // namespace lbs
+}  // namespace hardware
+}  // namespace mediatek
+}  // namespace vendor
+
diff --git a/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.h b/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.h
new file mode 100644
index 0000000..d7f7a7d
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.h
@@ -0,0 +1,109 @@
+
+#ifndef __LBS_HIDL_SERVICE_H__
+#define __LBS_HIDL_SERVICE_H__
+
+#include <vendor/mediatek/hardware/lbs/1.0/ILbs.h>
+#include <semaphore.h>
+#include "mtk_socket_utils.h"
+
+namespace vendor {
+namespace mediatek {
+namespace hardware {
+namespace lbs {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::wp;
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hidl::base::V1_0::IBase;
+
+#ifdef UNUSED
+#undef UNUSED
+#endif
+#define UNUSED(expr) do { (void)(expr); } while (0)
+
+class LbsHidlService : public ILbs {
+public:
+    LbsHidlService(const char* name);
+    ~LbsHidlService();
+
+    virtual Return<void> setCallback(const sp<ILbsCallback>& callback) override;
+    virtual Return<bool> sendToServer(const hidl_vec<uint8_t>& data) override;
+    virtual Return<bool> sendToServerWithCallback(const sp<ILbsCallback>& callback, const hidl_vec<uint8_t>& data) override;
+
+    class LbsHidlDeathRecipient : public hidl_death_recipient {
+        public:
+        LbsHidlDeathRecipient(const sp<LbsHidlService> lbs) : mLbs(lbs) {
+        }
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
+            UNUSED(cookie);
+            UNUSED(who);
+            mLbs->handleHidlDeath();
+        }
+        private:
+        sp<LbsHidlService> mLbs;
+    };
+    virtual void handleHidlDeath();
+
+    virtual bool handleSocketEvent(int fd);
+
+protected:
+    char mName[64];
+    sp<ILbsCallback> mLbsCallback;
+    sp<LbsHidlDeathRecipient> mLbsHidlDeathRecipient;
+    sem_t mSem;
+};
+
+class UdpHidlService : public LbsHidlService {
+public:
+    UdpHidlService(const char* name);
+    Return<bool> sendToServer(const hidl_vec<uint8_t>& data) override;
+protected:
+    mtk_socket_fd mSocketLPPe;
+};
+
+class AgpsInterfaceHidlService : public LbsHidlService {
+public:
+    AgpsInterfaceHidlService(const char* name);
+    Return<bool> sendToServerWithCallback(const sp<ILbsCallback>& callback, const hidl_vec<uint8_t>& data) override;
+};
+
+class AgpsDebugInterfaceHidlService : public LbsHidlService {
+public:
+    AgpsDebugInterfaceHidlService (const char* name);
+    Return<void> setCallback(const sp<ILbsCallback>& callback) override;
+    Return<bool> sendToServer(const hidl_vec<uint8_t>& data) override;
+    bool handleSocketEvent(int fd) override;
+    int getSocketFd();
+protected:
+    int mSocketFd;
+    bool mIsExit;
+};
+
+class Agps2ApnHidlService : public UdpHidlService {
+public:
+    Agps2ApnHidlService (const char* name);
+    Return<void> setCallback(const sp<ILbsCallback>& callback) override;
+    void handleHidlDeath() override;
+    int getSocketFd();
+protected:
+    int mSocketFd;
+};
+
+extern int cpp_main();
+
+}  // implementation
+}  // namespace V1_0
+}  // namespace lbs
+}  // namespace hardware
+}  // namespace mediatek
+}  // namespace vendor
+
+#endif  // __LBS_HIDL_SERVICE_H__
+
diff --git a/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.rc b/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.rc
new file mode 100644
index 0000000..b75296c
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/lbs_hidl_service.rc
@@ -0,0 +1,4 @@
+service lbs_hidl_service /vendor/bin/lbs_hidl_service

+    class main

+    user system

+    group system gps radio inet sdcard_r sdcard_rw

diff --git a/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/inc/mtk_socket_data_coder.h b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/inc/mtk_socket_data_coder.h
new file mode 100644
index 0000000..da994d9
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/inc/mtk_socket_data_coder.h
@@ -0,0 +1,50 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool mtk_socket_get_bool(char* buff, int* offset);
+int8_t mtk_socket_get_char(char* buff, int* offset);
+int16_t mtk_socket_get_short(char* buff, int* offset);
+int32_t mtk_socket_get_int(char* buff, int* offset);
+int64_t mtk_socket_get_int64_t(char* buff, int* offset);
+float mtk_socket_get_float(char* buff, int* offset);
+double mtk_socket_get_double(char* buff, int* offset);
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size);
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size);
+int mtk_socket_get_char_array(char* buff, int* offset, int8_t output[], int max_size);
+int mtk_socket_get_short_array(char* buff, int* offset, int16_t output[], int max_size);
+int mtk_socket_get_int_array(char* buff, int* offset, int32_t output[], int max_size);
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size);
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size);
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size);
+int mtk_socket_get_string_array(char* buff, int* offset, strings output, int max_size1, int max_size2);
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input);
+void mtk_socket_put_char(char* buff, int* offset, int8_t input);
+void mtk_socket_put_short(char* buff, int* offset, int16_t input);
+void mtk_socket_put_int(char* buff, int* offset, int32_t input);
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input);
+void mtk_socket_put_float(char* buff, int* offset, float input);
+void mtk_socket_put_double(char* buff, int* offset, double input);
+void mtk_socket_put_string(char* buff, int* offset, const char* input);
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size);
+void mtk_socket_put_char_array(char* buff, int* offset, int8_t input[], int size);
+void mtk_socket_put_short_array(char* buff, int* offset, int16_t input[], int size);
+void mtk_socket_put_int_array(char* buff, int* offset, int32_t input[], int size);
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size);
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size);
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size);
+void mtk_socket_put_string_array(char* buff, int* offset, strings input, int size1, int size2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/inc/mtk_socket_utils.h b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/inc/mtk_socket_utils.h
new file mode 100644
index 0000000..436a2dd
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/inc/mtk_socket_utils.h
@@ -0,0 +1,246 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_UTILS_H__
+#define __MTK_SOCKET_UTILS_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define strings void*
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+typedef enum {
+    SOCK_NS_ABSTRACT = 0,
+    SOCK_NS_FILESYSTEM = 1,
+} mtk_socket_namespace;
+
+typedef struct {
+    int fd;
+    bool is_local;
+    pthread_mutex_t mutex;
+
+    // Network
+    char* host;
+    int port;
+
+    // Local
+    char* path;
+    mtk_socket_namespace namesapce;
+} mtk_socket_fd;
+
+void _mtk_socket_log(int type, const char *fmt, ...);
+
+#define SOCK_LOGD(...) _mtk_socket_log(0, __VA_ARGS__);
+#define SOCK_LOGE(...) _mtk_socket_log(1, __VA_ARGS__);
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port);
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port);
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port);
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd);
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd);
+void mtk_socket_client_close(mtk_socket_fd* sock_fd);
+
+// return -1 means fail
+int mtk_socket_tcp_connect_local(const char* path, mtk_socket_namespace sock_namespace);
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len);
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len);
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout);
+
+
+void mtk_socket_buff_dump(const char* buff, int len);
+
+bool mtk_socket_string_is_equal(char* data1, char* data2);
+bool mtk_socket_string_array_is_equal(strings data1, int data1_size, strings data2, int data2_size, int string_size);
+void mtk_socket_string_array_dump(strings input, int size1, int size2);
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size);
+void mtk_socket_bool_array_dump(bool input[], int size);
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size);
+void mtk_socket_char_array_dump(char input[], int size);
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size);
+void mtk_socket_short_array_dump(short input[], int size);
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size);
+void mtk_socket_int_array_dump(int input[], int size);
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size);
+void mtk_socket_int64_t_array_dump(int64_t input[], int size);
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size);
+void mtk_socket_float_array_dump(float input[], int size);
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size);
+void mtk_socket_double_array_dump(double input[], int size);
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line);
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line);
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line);
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line);
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line);
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line);
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line);
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line);
+
+char *safe_strncpy(char *dest, const char *src, size_t n);
+
+#define ASSERT_EQUAL_INT(d1, d2) \
+{\
+    int _d1 = d1;\
+    int _d2 = d2;\
+    if(_d1 != _d2) {\
+        SOCK_LOGE("%s():%d ASSERT_EQUAL_INT() failed, d1=[%d], d2=[%d]",\
+        __func__, __LINE__, _d1, _d2);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_BOOL(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_bool(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_CHAR(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_char(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_SHORT(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_short(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_INT(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_int(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_INT64_T(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_int64_t(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_FLOAT(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_float(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_DOUBLE(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_double(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRING(buff, offset, expected_value, max_size) \
+{\
+    if(!mtk_socket_expected_string(buff, offset, expected_value, max_size, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRUCT(buff, offset, expected_value, struct_name) \
+{\
+    struct_name _tmp;\
+    struct_name##_decode(buff, offset, &_tmp);\
+    if(!struct_name##_is_equal(&_tmp, expected_value)) {\
+        SOCK_LOGE("%s():%d EXPECTED_STRUCT() %s_is_equal() fail", __func__, __LINE__, #struct_name);\
+        SOCK_LOGE(" ============= read ===============");\
+        struct_name##_dump(&_tmp);\
+        SOCK_LOGE(" ============= expected ===============");\
+        struct_name##_dump(expected_value);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+    type _tmp[max_size] = {0};\
+    int _tmp_num = mtk_socket_get_##type##_array(buff, offset, _tmp, max_size);\
+    if(!mtk_socket_##type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+        SOCK_LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+        SOCK_LOGE(" ============= read ===============");\
+        mtk_socket_##type##_array_dump(_tmp, _tmp_num);\
+        SOCK_LOGE(" ============= expected ===============");\
+        mtk_socket_##type##_array_dump(expected_value, expected_num);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRING_ARRAY(buff, offset, expected_num, expected_value, max_size1, max_size2) \
+{\
+    char _tmp[max_size1][max_size2];\
+    int _tmp_num = mtk_socket_get_string_array(buff, offset, _tmp, max_size1, max_size2);\
+    if(!mtk_socket_string_array_is_equal(expected_value, expected_num, _tmp, _tmp_num, max_size2)) {\
+        SOCK_LOGE("%s():%d expected_string_array() fail", __func__, __LINE__);\
+        SOCK_LOGE(" ============= read ===============");\
+        mtk_socket_string_array_dump(_tmp, _tmp_num, max_size2);\
+        SOCK_LOGE(" ============= expected ===============");\
+        mtk_socket_string_array_dump(expected_value, expected_num, max_size2);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRUCT_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+    type _tmp[max_size];\
+    int _tmp_num = type##_array_decode(buff, offset, _tmp, max_size);\
+    if(!type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+        SOCK_LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+        SOCK_LOGE(" ============= read ===============");\
+        type##_array_dump(_tmp, _tmp_num);\
+        SOCK_LOGE(" ============= expected ===============");\
+        type##_array_dump(expected_value, expected_num);\
+        return false;\
+    }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN(d1, d2) \
+{\
+    if(d1 > d2) {\
+        SOCK_LOGE("%s():%d ASSERT_LESS_EQUAL_THAN() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+        return false;\
+    }\
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/src/mtk_socket_data_coder.c b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/src/mtk_socket_data_coder.c
new file mode 100644
index 0000000..8d37e3d
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/src/mtk_socket_data_coder.c
@@ -0,0 +1,256 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_data_coder.h"
+
+bool mtk_socket_get_bool(char* buff, int* offset) {
+    bool ret = (mtk_socket_get_char(buff, offset) == 0)? false : true;
+    return ret;
+}
+
+int8_t mtk_socket_get_char(char* buff, int* offset) {
+    int8_t ret = buff[*offset];
+    *offset += 1;
+    return ret;
+}
+
+int16_t mtk_socket_get_short(char* buff, int* offset) {
+    int16_t ret = 0;
+    ret |= mtk_socket_get_char(buff, offset) & 0xff;
+    ret |= (mtk_socket_get_char(buff, offset) << 8);
+    return ret;
+}
+
+int32_t mtk_socket_get_int(char* buff, int* offset) {
+    int32_t ret = 0;
+    ret |= mtk_socket_get_short(buff, offset) & 0xffff;
+    ret |= (mtk_socket_get_short(buff, offset) << 16);
+    return ret;
+}
+
+int64_t mtk_socket_get_int64_t(char* buff, int* offset) {
+    int64_t ret = 0;
+    ret |= mtk_socket_get_int(buff, offset) & 0xffffffffL;
+    ret |= ((int64_t)mtk_socket_get_int(buff, offset) << 32);
+    return ret;
+}
+
+float mtk_socket_get_float(char* buff, int* offset) {
+    float ret;
+    int32_t tmp = mtk_socket_get_int(buff, offset);
+    ret = *((float*)&tmp);
+    return ret;
+}
+
+double mtk_socket_get_double(char* buff, int* offset) {
+    double ret;
+    int64_t tmp = mtk_socket_get_int64_t(buff, offset);
+    ret = *((double*)&tmp);
+    return ret;
+}
+
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size) {
+    int size = mtk_socket_get_int(buff, offset);
+    memset(output, 0, max_size);
+    memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+    output[max_size - 1] = 0;
+    *offset += size;
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        bool data = mtk_socket_get_bool(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_char_array(char* buff, int* offset, int8_t output[], int max_size) {
+    int size = mtk_socket_get_int(buff, offset);
+    memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+    *offset += size;
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_short_array(char* buff, int* offset, int16_t output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        int16_t data = mtk_socket_get_short(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int_array(char* buff, int* offset, int32_t output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        int32_t data = mtk_socket_get_int(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        int64_t data = mtk_socket_get_int64_t(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        float data = mtk_socket_get_float(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        double data = mtk_socket_get_double(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_string_array(char* buff, int* offset, strings output, int max_size1, int max_size2) {
+    int i = 0;
+    int size1 = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size1; i++) {
+        if(i < max_size1) {
+            mtk_socket_get_string(buff, offset, output, max_size2);
+            output = (char*)output + max_size2;
+        } else {
+            char tmp[max_size2];
+            mtk_socket_get_string(buff, offset, tmp, max_size2);
+        }
+    }
+    return (size1 > max_size1)? max_size1 : size1;
+}
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input) {
+    mtk_socket_put_char(buff, offset, input);
+}
+
+void mtk_socket_put_char(char* buff, int* offset, int8_t input) {
+    *((int8_t*)&buff[*offset]) = input;
+    *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, int16_t input) {
+    mtk_socket_put_char(buff, offset, input & 0xff);
+    mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int32_t input) {
+    mtk_socket_put_short(buff, offset, input & 0xffff);
+    mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input) {
+    mtk_socket_put_int(buff, offset, input & 0xffffffffL);
+    mtk_socket_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mtk_socket_put_float(char* buff, int* offset, float input) {
+    int32_t* data = (int32_t*)&input;
+    mtk_socket_put_int(buff, offset, *data);
+}
+
+void mtk_socket_put_double(char* buff, int* offset, double input) {
+    int64_t* data = (int64_t*)&input;
+    mtk_socket_put_int64_t(buff, offset, *data);
+}
+
+void mtk_socket_put_string(char* buff, int* offset, const char* input) {
+    int len = strlen(input);
+    mtk_socket_put_int(buff, offset, len);
+    memcpy(&buff[*offset], input, len);
+    *offset += len;
+}
+
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_bool(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_char_array(char* buff, int* offset, int8_t input[], int size) {
+    mtk_socket_put_int(buff, offset, size);
+    memcpy(&buff[*offset], input, size);
+    *offset += size;
+}
+
+void mtk_socket_put_short_array(char* buff, int* offset, int16_t input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_short(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_int_array(char* buff, int* offset, int32_t input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_int(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_int64_t(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_float(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_double(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_string_array(char* buff, int* offset, strings input, int size1, int size2) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size1);
+    for(i = 0; i < size1; i++) {
+        mtk_socket_put_string(buff, offset, (char*)input);
+        input = (char*)input + size2;
+    }
+}
+
diff --git a/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/src/mtk_socket_utils.c b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/src/mtk_socket_utils.c
new file mode 100644
index 0000000..b58328b
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/mtk_socket_utils/src/mtk_socket_utils.c
@@ -0,0 +1,704 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_utils.h"
+#include "mtk_socket_data_coder.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+#if defined(__ANDROID_OS__)
+#include <cutils/log.h>     // Android log
+
+#define ANDROID_LOG_TAG "mtk_socket"
+#endif
+
+
+#if !defined(__ANDROID_OS__)
+//-1 means failure
+static int get_time_str(char* buff, int len) {
+    struct timeval  tv;
+    struct timezone tz;
+    struct tm      *tm;
+
+    gettimeofday(&tv, &tz);
+    tm = localtime(&tv.tv_sec);
+
+    memset(buff, 0, len);
+    sprintf(buff, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+        tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+        tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+    return 0;
+}
+#endif
+
+void _mtk_socket_log(int type, const char *fmt, ...) {
+    char buff[1024] = {0};
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(buff, sizeof(buff), fmt, ap);
+    va_end(ap);
+
+#if defined(__ANDROID_OS__)
+    if(type == 0) {
+        __android_log_print(ANDROID_LOG_DEBUG, ANDROID_LOG_TAG, "%s", buff);
+    } else {
+        __android_log_print(ANDROID_LOG_ERROR, ANDROID_LOG_TAG, "ERR: %s", buff);
+    }
+#else
+    char time_buff[64] = {0};
+    get_time_str(time_buff, sizeof(time_buff));
+    if(type == 0) {
+        printf("%s %s\n", time_buff, buff);
+    } else {
+        printf("%s ERR: %s\n", time_buff, buff);
+    }
+    fflush(stdout);
+#endif
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port) {
+    struct sockaddr_in addr;
+    memset(&addr, 0, sizeof(addr));
+    int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_server_bind_network() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+        SOCK_LOGE("mtk_socket_server_bind_network() bind() failed reason=[%s]%d for port=[%d]",
+            strerror(errno), errno, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port) {
+    struct sockaddr_in6 addr;
+    memset(&addr, 0, sizeof(addr));
+    int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_server_bind_network_ipv6() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    addr.sin6_family = AF_INET6;
+    addr.sin6_port = htons(port);
+    addr.sin6_addr = in6addr_any;
+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+        SOCK_LOGE("mtk_socket_server_bind_network_ipv6() bind() failed reason=[%s]%d for port=[%d]",
+            strerror(errno), errno, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace) {
+    int size;
+    struct sockaddr_un addr;
+    int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_server_bind_local() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+    if(sock_namespace == SOCK_NS_ABSTRACT) {
+        addr.sun_path[0] = 0;
+        memcpy(addr.sun_path + 1, path, strlen(path));
+    } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+        safe_strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+        unlink(addr.sun_path);
+    } else {
+        SOCK_LOGE("mtk_socket_server_bind_local() unknown namespace=[%d]", sock_namespace);
+        close(fd);
+        return -1;
+    }
+    if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+        SOCK_LOGE("mtk_socket_server_bind_local() bind() failed reason=[%s]%d for path=[%s]",
+            strerror(errno), errno, path);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port) {
+    int len = strlen(host);
+    memset(sock_fd, 0, sizeof(*sock_fd));
+    sock_fd->fd = -1;
+    sock_fd->is_local = false;
+    pthread_mutex_init(&sock_fd->mutex, NULL);
+    sock_fd->host = malloc(len + 1);
+    safe_strncpy(sock_fd->host, host, len + 1);
+    sock_fd->port = port;
+}
+
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace) {
+    int len = strlen(path);
+    memset(sock_fd, 0, sizeof(*sock_fd));
+    sock_fd->fd = -1;
+    sock_fd->is_local = true;
+    pthread_mutex_init(&sock_fd->mutex, NULL);
+    sock_fd->path = malloc(len + 1);
+    safe_strncpy(sock_fd->path, path, len + 1);
+    sock_fd->namesapce = sock_namespace;
+}
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd) {
+    mtk_socket_client_close(sock_fd);
+    if(sock_fd->host) {
+        free(sock_fd->host);
+        sock_fd->host = NULL;
+    }
+    if(sock_fd->path) {
+        free(sock_fd->path);
+        sock_fd->path = NULL;
+    }
+}
+
+// return -1 means fail
+int mtk_socket_tcp_connect_local(const char* path, mtk_socket_namespace sock_namespace) {
+    int size;
+    struct sockaddr_un addr;
+    int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_tcp_connect_local() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return false;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_LOCAL;
+    size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+    if(sock_namespace == SOCK_NS_ABSTRACT) {
+        addr.sun_path[0] = 0;
+        memcpy(addr.sun_path + 1, path, strlen(path));
+    } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+        safe_strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+    } else {
+        SOCK_LOGE("mtk_socket_connect_local() unknown namespace=[%d]", sock_namespace);
+        close(fd);
+        return -1;
+    }
+    if (connect(fd, (struct sockaddr *)&addr, size) < 0) {
+        SOCK_LOGE("mtk_socket_connect_local() connect() failed reason=[%s]%d for path=[%s]",
+            strerror(errno), errno, path);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+static bool mtk_socket_connect_local(mtk_socket_fd* sock_fd) {
+    int size;
+    struct sockaddr_un addr;
+    int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_connect_local() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return false;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_LOCAL;
+    size = strlen(sock_fd->path) + offsetof(struct sockaddr_un, sun_path) + 1;
+    if(sock_fd->namesapce == SOCK_NS_ABSTRACT) {
+        addr.sun_path[0] = 0;
+        memcpy(addr.sun_path + 1, sock_fd->path, strlen(sock_fd->path));
+    } else if(sock_fd->namesapce == SOCK_NS_FILESYSTEM) {
+        safe_strncpy(addr.sun_path, sock_fd->path, sizeof(addr.sun_path));
+    } else {
+        SOCK_LOGE("mtk_socket_connect_local() unknown namespace=[%d]", sock_fd->namesapce);
+        close(fd);
+        return false;
+    }
+    if (connect(fd, (struct sockaddr *)&addr, size) < 0) {
+        SOCK_LOGE("mtk_socket_connect_local() connect() failed reason=[%s]%d for path=[%s]",
+            strerror(errno), errno, sock_fd->path);
+        close(fd);
+        return false;
+    }
+    sock_fd->fd = fd;
+    return true;
+}
+
+static int mtk_socket_connect_network_ipv4(struct sockaddr_in* addr) {
+    int port = ntohs(addr->sin_port);
+    char ip_str[64] = {0};
+    inet_ntop(AF_INET, &(addr->sin_addr), ip_str, sizeof(ip_str));
+    int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_connect_network_ipv4() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    //SOCK_LOGD("mtk_socket_connect_network_ipv4() IPv4=[%s] port=[%d]", ip_str, port);
+    if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+        SOCK_LOGE("mtk_socket_connect_network_ipv4() connect() failed reason=[%s]%d for host=[%s] port=[%d]",
+            strerror(errno), errno, ip_str, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+//-1 means failure
+static int mtk_socket_connect_network_ipv6(struct sockaddr_in6* addr) {
+    int port = ntohs(addr->sin6_port);
+    int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        SOCK_LOGE("mtk_socket_connect_network_ipv6() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    //unsigned char* ipv6_addr = addr->sin6_addr.s6_addr;
+    //SOCK_LOGD("mtk_socket_connect_network_ipv6() IPv6=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x] port=[%d]",
+    //    ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3], ipv6_addr[4], ipv6_addr[5], ipv6_addr[6], ipv6_addr[7],
+    //    ipv6_addr[8], ipv6_addr[9], ipv6_addr[10], ipv6_addr[11], ipv6_addr[12], ipv6_addr[13], ipv6_addr[14], ipv6_addr[15],
+    //    port);
+    if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+        SOCK_LOGE("mtk_socket_connect_network_ipv6() connect() failed reason=[%s]%d for port=[%d]",
+            strerror(errno), errno, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+static bool mtk_socket_connect_network(mtk_socket_fd* sock_fd) {
+    struct addrinfo hints;
+    struct addrinfo *result;
+    struct addrinfo *rp;
+    int ret;
+    char port_str[11] = {0};
+    sprintf(port_str, "%u", sock_fd->port);
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_UNSPEC;    // Allow IPv4 or IPv6, AF_UNSPEC, AF_INET, AF_INET6
+    hints.ai_socktype = SOCK_DGRAM;
+    hints.ai_flags = AI_ADDRCONFIG; // check local system
+    hints.ai_protocol = IPPROTO_UDP;
+    ret = getaddrinfo(sock_fd->host, port_str, &hints, &result);
+    if(ret != 0) {
+        SOCK_LOGE("mtk_socket_connect_network() getaddrinfo() failure reason=[%s] %d\n",
+            gai_strerror(ret), ret);
+        return false;
+    }
+    for (rp = result; rp != NULL; rp = rp->ai_next) {
+        if(rp->ai_family == AF_INET) {
+            ret = mtk_socket_connect_network_ipv4((struct sockaddr_in*)rp->ai_addr);
+            if(ret >= 0) {
+                sock_fd->fd = ret;
+                break;
+            }
+        }
+        if(rp->ai_family == AF_INET6) {
+            ret = mtk_socket_connect_network_ipv6((struct sockaddr_in6*)rp->ai_addr);
+            if(ret >= 0) {
+                sock_fd->fd = ret;
+                break;
+            }
+        }
+    }
+    freeaddrinfo(result);
+    if(ret >= 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd) {
+    if(sock_fd->is_local) {
+        return mtk_socket_connect_local(sock_fd);
+    } else {
+        return mtk_socket_connect_network(sock_fd);
+    }
+}
+
+void mtk_socket_client_close(mtk_socket_fd* sock_fd) {
+    if(sock_fd->fd >= 0) {
+        close(sock_fd->fd);
+        sock_fd->fd = -1;
+    }
+}
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len) {
+    int n, retry = 10;
+    if(fd < 0 || buff == NULL || len < 0) {
+        SOCK_LOGE("mtk_socket_read() invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+        return -1;
+    }
+    if(len == 0) {
+        return 0;
+    }
+    while((n = read(fd, buff, len)) < 0) {
+        if(errno == EINTR) continue;
+        if(errno == EAGAIN) {
+            if(retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+            goto exit;
+        }
+        goto exit;
+    }
+    return n;
+exit:
+    SOCK_LOGE("mtk_socket_read() read() failed, fd=[%d] len=[%d] errno=[%s]%d",
+        fd, len, strerror(errno), errno);
+    return -1;
+}
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len) {
+    int n, retry = 10;
+    if(fd < 0 || buff == NULL || len < 0) {
+        SOCK_LOGE("mtk_socket_write() invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+        return -1;
+    }
+    while((n = write(fd, buff, len)) != len) {
+        if(errno == EINTR) continue;
+        if(errno == EAGAIN) {
+            if(retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+            goto exit;
+        }
+        goto exit;
+    }
+    return n;
+exit:
+    SOCK_LOGE("mtk_socket_write() write() failed, fd=[%d] len=[%d] errno=[%s]%d\n",
+        fd, len, strerror(errno), errno);
+    return -1;
+}
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout) {
+    struct pollfd poll_fd[1];
+    int ret = 0;
+    memset(poll_fd, 0, sizeof(poll_fd));
+    poll_fd[0].fd      = fd;
+    poll_fd[0].events  = POLLIN;
+    poll_fd[0].revents = 0;
+
+    ret = poll(poll_fd, 1, timeout);
+    if(ret > 0) {
+        if(poll_fd[0].revents & POLLIN ||
+            poll_fd[0].revents & POLLERR) {
+            ret = 1 << 0;
+        }
+    }
+    return ret;
+}
+
+void mtk_socket_buff_dump(const char* buff, int len) {
+    int i = 0;
+    char tmp[512] = {0};
+    SOCK_LOGD("mtk_socket_buff_dump len=%d", len);
+    for(i = 0; i < len; i++) {
+        if((i % 16 == 0) && (i != 0)) {
+            SOCK_LOGD("  %s", tmp);
+            memset(tmp, 0, sizeof(tmp));
+        }
+        sprintf(tmp + ((i % 16) * 3), "%02x ", buff[i] & 0xff);
+    }
+    if(i > 0) {
+        SOCK_LOGD("  %s", tmp);
+    }
+}
+
+bool mtk_socket_string_is_equal(char* data1, char* data2) {
+    return (strcmp(data1, data2) == 0)? true : false;
+}
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_string_array_is_equal(strings data1, int data1_size, strings data2, int data2_size, int string_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(!mtk_socket_string_is_equal(data1, data2)) {
+            return false;
+        }
+        data1 = (char*)data1 + string_size;
+        data2 = (char*)data2 + string_size;
+    }
+    return true;
+}
+
+void mtk_socket_bool_array_dump(bool input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_bool_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%d]", i, input[i]);
+    }
+}
+
+void mtk_socket_char_array_dump(char input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_char_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%d]", i, input[i] & 0xff);
+    }
+}
+
+void mtk_socket_short_array_dump(short input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_short_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%d]", i, input[i] & 0xffff);
+    }
+}
+
+void mtk_socket_int_array_dump(int input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_int_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%d]", i, input[i]);
+    }
+}
+
+void mtk_socket_int64_t_array_dump(int64_t input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_int64_t_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%lld]", i, (long long)input[i]);
+    }
+}
+
+void mtk_socket_float_array_dump(float input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_float_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%f]", i, input[i]);
+    }
+}
+
+void mtk_socket_double_array_dump(double input[], int size) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_double_array_dump size=%d", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%f]", i, input[i]);
+    }
+}
+
+void mtk_socket_string_array_dump(strings input, int size1, int size2) {
+    int i = 0;
+    SOCK_LOGD("mtk_socket_string_array_dump size1=%d size2=%d", size1, size2);
+    for(i = 0; i < size1; i++) {
+        SOCK_LOGD("  i=[%d] data=[%s]", i, (char*)input);
+        input = (char*)input + size2;
+    }
+}
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line) {
+    bool value = mtk_socket_get_bool(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_bool() failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line) {
+    char value = mtk_socket_get_char(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_char() failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line) {
+    short value = mtk_socket_get_short(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_short() failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line) {
+    int value = mtk_socket_get_int(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_int() failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line) {
+    int64_t value = mtk_socket_get_int64_t(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_int64_t() failed, read=[%lld], expected=[%lld]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line) {
+    float value = mtk_socket_get_float(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_float() failed, read=[%f], expected=[%f]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line) {
+    double value = mtk_socket_get_double(buff, offset);
+    if(value != expected_value) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_double() failed, read=[%f], expected=[%f]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line) {
+    char value[max_size];
+    mtk_socket_get_string(buff, offset, value, sizeof(value));
+    if(strcmp(value, expected_value) != 0) {
+        SOCK_LOGE("%s():%d mtk_socket_expected_string() failed, read=[%s], expected=[%s]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+char *safe_strncpy(char *dest, const char *src, size_t n) {
+    if (dest && n > 0) {
+        // Use strncat for performance because strncpy will always fill n bytes in dest
+        dest[0] = '\0';            // Let dest be an empty string
+        strncat(dest, src, --n);   // n-1 because strncat may fill n+1 bytes
+    }
+    return dest;
+}
+
diff --git a/src/connectivity/gps/lbs_hidl_service/service.cpp b/src/connectivity/gps/lbs_hidl_service/service.cpp
new file mode 100644
index 0000000..0b2daea
--- /dev/null
+++ b/src/connectivity/gps/lbs_hidl_service/service.cpp
@@ -0,0 +1,12 @@
+#define LOG_TAG "lbs_hidl_service"
+
+#include <lbs_hidl_service.h>
+#include <hidl/LegacySupport.h>
+
+int main() {
+    ::vendor::mediatek::hardware::lbs::V1_0::implementation::cpp_main();
+    ::android::hardware::joinRpcThreadpool();
+
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/Android.mk b/src/connectivity/gps/mtk_mnld/Android.mk
new file mode 100644
index 0000000..8aea104
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/Android.mk
@@ -0,0 +1,170 @@
+# 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) 2016. 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.     
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# Copyright 2005 The Android Open Source Project
+
+ifeq ($(MTK_GPS_SUPPORT), true)
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+MY_LOCAL_PATH := $(LOCAL_PATH)
+
+LOCAL_C_INCLUDES += \
+  $(LOCAL_PATH)/utility/inc \
+  $(LOCAL_PATH)/mnl_agps_interface/inc \
+  $(LOCAL_PATH)/mnl_at_cmd_interface/inc \
+  $(LOCAL_PATH)/mnl_flp_interface/inc \
+  $(LOCAL_PATH)/mnl_nlp_interface/inc \
+  $(LOCAL_PATH)/mnl_meta_interface/inc \
+  $(LOCAL_PATH)/mnl_debug_interface/inc \
+  $(LOCAL_PATH)/mnl_geofence_interface/inc \
+  $(LOCAL_PATH)/mnld_entity/inc \
+  $(LOCAL_PATH)/mnl/inc \
+  $(LOCAL_PATH)/curl/inc \
+  $(TOP)/external/libxml2/include \
+  $(TOP)/system/core/libcutils/include_vndk \
+  $(TOP)/system/core/include \
+  $(TOP)/hardware/libhardware/include \
+  $(TOP)/system/core/libcutils/include \
+  $(LOCAL_PATH)/mnl_mpe_interface/inc \
+
+LOCAL_SRC_FILES := \
+	mnld_entity/src/mnl2hal_interface.c \
+	utility/src/data_coder.c \
+	utility/src/mtk_lbs_utility.c \
+	utility/src/mtk_socket_data_coder.c \
+	utility/src/mtk_socket_utils.c \
+	mnl_agps_interface/src/mnl_agps_interface.c \
+	mnl_agps_interface/src/mnl2agps_interface.c \
+	mnl_agps_interface/src/agps2mnl_interface.c \
+	mnl_flp_interface/src/mtk_flp_controller.c \
+	mnl_flp_interface/src/mtk_flp_main.c \
+	mnl_flp_interface/src/mtk_flp_mnl_interface.c \
+	mnl_flp_interface/src/mtk_flp_screen_monitor.c \
+	mnl_flp_interface/src/mnl_flp_test_interface.c \
+	mnl_geofence_interface/src/mtk_geofence_controller.c \
+	mnl_geofence_interface/src/mtk_geofence_main.c \
+	mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c \
+	mnl_meta_interface/src/Meta2MnldInterface.c \
+	mnl_debug_interface/src/Debug2MnldInterface.c \
+	mnl_debug_interface/src/Mnld2DebugInterface.c \
+	mnl_at_cmd_interface/src/mnl_at_interface.c \
+	mnld_entity/src/mnld.c \
+	mnld_entity/src/mnld_uti.c \
+	mnld_entity/src/gps_controller.c \
+	mnld_entity/src/nmea_parser.c \
+	mnld_entity/src/epo.c \
+	mnld_entity/src/qepo.c \
+	mnld_entity/src/mtknav.c \
+	mnld_entity/src/mnl_common.c \
+	mnld_entity/src/op01_log.c \
+	mnld_entity/src/gps_dbg_log.c \
+	mnl/src/pseudo_mnl.c \
+	utility/src/mtk_auto_log.c \
+	mnld_entity/src/mpe.c \
+	mnl_mpe_interface/src/mpe_main.c \
+	mnl_mpe_interface/src/mpe_logger.c \
+
+ifeq ($(MTK_GPS_CHIP), MT3303)
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/mnld_entity/src/flashdownload \
+
+LOCAL_SRC_FILES += \
+	mnld_entity/src/mt3333_controller.c \
+	mnld_entity/src/flashdownload/flashtool.c \
+	mnld_entity/src/flashdownload/brom_base.c \
+	mnld_entity/src/flashdownload/brom_mt3301.c \
+	mnld_entity/src/flashdownload/da_cmd.c \
+	mnld_entity/src/flashdownload/gps_uart.c \
+
+LOCAL_CFLAGS += -DCONFIG_GPS_MT3303
+LOCAL_CFLAGS += -DCONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL
+endif
+
+LOCAL_MODULE := mnld
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
+# LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+#ifeq ($(MTK_TC1_FEATURE), yes)
+#ifeq ($(GPS_CO_CLOCK_DATA_IN_MD), yes)
+LOCAL_CFLAGS += -DMTK_GPS_CO_CLOCK_DATA_IN_MD
+#endif
+#endif
+ifeq ($(TARGET_BUILD_VARIANT), user)
+LOCAL_CFLAGS += -DCONFIG_GPS_USER_LOAD
+endif
+ifeq ($(TARGET_BUILD_VARIANT), userdebug)
+LOCAL_CFLAGS += -DCONFIG_GPS_USER_DBG_LOAD
+endif
+ifeq ($(TARGET_BUILD_VARIANT), eng)
+LOCAL_CFLAGS += -DCONFIG_GPS_ENG_LOAD
+endif
+ifeq ($(MTK_AGPS_APP), yes)
+LOCAL_CFLAGS += -DMTK_AGPS_SUPPORT
+endif
+ifeq ($(MTK_ADR_SUPPORT), true)
+LOCAL_CFLAGS += -DMTK_ADR_SUPPORT
+endif
+LOCAL_CFLAGS += -D__ANDROID_OS__
+
+ifeq ($(PLATFORM_VERSION), 10)
+LOCAL_CFLAGS += -DMTK_GPS_DATA_PATH="\"/data/vendor/gps/\""
+LOCAL_CFLAGS += -DMTK_GPS_FW_PATH="\"/vendor/firmware/\""
+LOCAL_CFLAGS += -D__ANDROID_OS_P__
+LOCAL_CFLAGS += -D__ANDROID_OS_10__
+else ifeq ($(PLATFORM_VERSION), 9)
+LOCAL_CFLAGS += -DMTK_GPS_DATA_PATH="\"/data/vendor/gps/\""
+LOCAL_CFLAGS += -D__ANDROID_OS_P__
+else
+LOCAL_CFLAGS += -DMTK_GPS_DATA_PATH="\"/data/misc/gps/\""
+LOCAL_CFLAGS += -D__ANDROID_OS_O__
+endif
+
+LOCAL_STATIC_LIBRARIES +=  libsupl
+LOCAL_SHARED_LIBRARIES +=  libmnl libgeofence libcurl libcutils libc libm libcrypto libssl libz liblog libhardware libutils libhardware
+LOCAL_HEADER_LIBRARIES +=  libcutils_headers
+LOCAL_EXPORT_HEADER_LIBRARY_HEADERS += libhardware_headers
+# MPE HIDL #
+LOCAL_SHARED_LIBRARIES +=  libDR libutils android.frameworks.sensorservice@1.0 android.hardware.sensors@1.0 libhidlbase libhidltransport libsensorndkbridge
+LOCAL_MODULE_TAGS := optional
+#LOCAL_REQUIRED_MODULES := libmnl.so
+
+include $(BUILD_EXECUTABLE)
+include $(MY_LOCAL_PATH)/mnl/libs/android/Android.mk
+include $(MY_LOCAL_PATH)/curl/libs/Android.mk
+
+endif
+###############################################################################
diff --git a/src/connectivity/gps/mtk_mnld/LICENSE b/src/connectivity/gps/mtk_mnld/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/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/mtk_mnld/Makefile.am b/src/connectivity/gps/mtk_mnld/Makefile.am
new file mode 100644
index 0000000..4569718
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/Makefile.am
@@ -0,0 +1,73 @@
+AUTOMAKE_OPTIONS=foreign subdir-objects
+bin_PROGRAMS = mnld0
+
+mnld0_SOURCES = \
+        mnld_entity/src/mnl2hal_interface.c \
+        utility/src/data_coder.c \
+        utility/src/mtk_lbs_utility.c \
+        utility/src/mtk_socket_data_coder.c \
+        utility/src/mtk_socket_utils.c \
+        mnl_agps_interface/src/mnl_agps_interface.c \
+        mnl_agps_interface/src/mnl2agps_interface.c \
+        mnl_agps_interface/src/agps2mnl_interface.c \
+        mnl_flp_interface/src/mtk_flp_controller.c \
+        mnl_flp_interface/src/mtk_flp_main.c \
+        mnl_flp_interface/src/mtk_flp_mnl_interface.c \
+        mnl_flp_interface/src/mtk_flp_screen_monitor.c \
+        mnl_flp_interface/src/mnl_flp_test_interface.c \
+        mnl_geofence_interface/src/mtk_geofence_controller.c \
+        mnl_geofence_interface/src/mtk_geofence_main.c \
+        mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c \
+        mnl_meta_interface/src/Meta2MnldInterface.c \
+        mnl_debug_interface/src/Debug2MnldInterface.c \
+        mnl_debug_interface/src/Mnld2DebugInterface.c \
+        mnl_at_cmd_interface/src/mnl_at_interface.c \
+        mnld_entity/src/mnld.c \
+        mnld_entity/src/mnld_uti.c \
+        mnld_entity/src/gps_controller.c \
+        mnld_entity/src/nmea_parser.c \
+        mnld_entity/src/epo.c \
+        mnld_entity/src/qepo.c \
+        mnld_entity/src/mtknav.c \
+        mnld_entity/src/mnl_common.c \
+        mnld_entity/src/op01_log.c \
+        mnld_entity/src/gps_dbg_log.c \
+        mnl/src/pseudo_mnl.c \
+        utility/src/mtk_auto_log.c \
+        mnld_entity/src/mpe.c \
+        mnl_mpe_interface/src/mpe_main.c \
+        mnl_mpe_interface/src/mpe_logger.c \
+        mnld_entity/src/mt3333_controller.c \
+        mnld_entity/src/flashdownload/flashtool.c \
+	 mnld_entity/src/flashdownload/brom_base.c \
+	 mnld_entity/src/flashdownload/brom_mt3301.c \
+	 mnld_entity/src/flashdownload/da_cmd.c \
+ 	 mnld_entity/src/flashdownload/gps_uart.c
+
+AM_CFLAGS = \
+        -Iutility/inc \
+        -Imnl_agps_interface/inc \
+        -Imnl_at_cmd_interface/inc \
+        -Imnl_flp_interface/inc \
+        -Imnl_mpe_interface/inc \
+        -Imnl_nlp_interface/inc \
+        -Imnl_meta_interface/inc \
+        -Imnl_debug_interface/inc \
+        -Imnl_geofence_interface/inc \
+        -Imnld_entity/inc \
+        -Imnld_entity/hardware \
+        -Imnld_entity/src/flashdownload \
+        -Imnl/inc \
+        -Icurl/inc \
+        -Imnl_mpe_interface/inc \
+        -D__LINUX_OS__ \
+        -DMTK_GPS_DATA_PATH="\"/usr/share/gps/\""
+
+AM_CFLAGS+=$(DNS_FLAGS)
+
+mnld0_LDADD = mnl/libs/linux/${PACKAGE_ARCH}/libmnl_gnss.so \
+        mnl/libs/linux/${PACKAGE_ARCH}/libhotstill.a \
+        mnl/libs/linux/${PACKAGE_ARCH}/libsupl.a \
+        -lm -lrt -lpthread -lz -lssl -lcrypto -lcurl
+
+include_HEADERS = mnl/inc/mtk_gps_type.h
diff --git a/src/connectivity/gps/mtk_mnld/NOTICE b/src/connectivity/gps/mtk_mnld/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/mtk_mnld/README b/src/connectivity/gps/mtk_mnld/README
new file mode 100644
index 0000000..7394158
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/README
@@ -0,0 +1,16 @@
+WHAT IT DOES?
+=============
+mnld is the implementation that mediatek navigating technology to work well as mediatek navigating library process on native.
+
+HOW IT WAS BUILT?
+==================
+As native process, these are built by android build system.
+
+HOW TO USE IT?
+==============
+mnld is run when system boot up,they receive command from GPS HAL/AGPSD,handle with gps start/close/init/cleanup opertions,
+and send responises to GPS HAL/AGPSD.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/configure.ac b/src/connectivity/gps/mtk_mnld/configure.ac
new file mode 100644
index 0000000..627af4c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/configure.ac
@@ -0,0 +1,9 @@
+AC_INIT([mnld0], [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
+AC_PROG_CXX
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/curl.h b/src/connectivity/gps/mtk_mnld/curl/inc/curl.h
new file mode 100644
index 0000000..b57b3c4
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/curl.h
@@ -0,0 +1,2360 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * If you have libcurl problems, all docs and details are found here:
+ *   http://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+ *   http://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+#include "curlver.h"         /* libcurl version defines   */
+#include "curlbuild.h"       /* libcurl build definitions */
+#include "curlrules.h"       /* libcurl rules enforcement */
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && \
+     !defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+/* Needed for __FreeBSD_version symbol definition */
+#include <osreldate.h>
+#endif
+
+/* The include stuff here below is mainly for time_t! */
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || defined(__LWIP_OPT_H__))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+   included, since they can't co-exist without problems */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#endif
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+   libc5-based Linux systems. Only include it on systems that are known to
+   require it! */
+#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+    defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+    defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+   (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+#include <sys/select.h>
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#include <sys/socket.h>
+#endif
+
+#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#include <sys/time.h>
+#endif
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef void CURL;
+
+/*
+ * libcurl external API function linkage decorations.
+ */
+
+#ifdef CURL_STATICLIB
+#  define CURL_EXTERN
+#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+#  if defined(BUILDING_LIBCURL)
+#    define CURL_EXTERN  __declspec(dllexport)
+#  else
+#    define CURL_EXTERN  __declspec(dllimport)
+#  endif
+#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
+#  define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+#  define CURL_EXTERN
+#endif
+
+#ifndef curl_socket_typedef
+/* socket typedef */
+#if defined(WIN32) && !defined(__LWIP_OPT_H__)
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+struct curl_httppost {
+  struct curl_httppost *next;       /* next entry in the list */
+  char *name;                       /* pointer to allocated name */
+  long namelength;                  /* length of name length */
+  char *contents;                   /* pointer to allocated data contents */
+  long contentslength;              /* length of contents field */
+  char *buffer;                     /* pointer to allocated buffer contents */
+  long bufferlength;                /* length of buffer field */
+  char *contenttype;                /* Content-Type */
+  struct curl_slist* contentheader; /* list of extra headers for this form */
+  struct curl_httppost *more;       /* if one field name has more than one
+                                       file, this link should link to following
+                                       files */
+  long flags;                       /* as defined below */
+#define HTTPPOST_FILENAME (1<<0)    /* specified content is a file name */
+#define HTTPPOST_READFILE (1<<1)    /* specified content is a file name */
+#define HTTPPOST_PTRNAME (1<<2)     /* name is only stored pointer
+                                       do not free in formfree */
+#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
+                                       do not free in formfree */
+#define HTTPPOST_BUFFER (1<<4)      /* upload file from buffer */
+#define HTTPPOST_PTRBUFFER (1<<5)   /* upload file from pointer contents */
+#define HTTPPOST_CALLBACK (1<<6)    /* upload file contents by using the
+                                       regular read callback to get the data
+                                       and pass the given pointer as custom
+                                       pointer */
+
+  char *showfilename;               /* The file name to show. If not set, the
+                                       actual file name will be used (if this
+                                       is a file part) */
+  void *userp;                      /* custom pointer used for
+                                       HTTPPOST_CALLBACK posts */
+};
+
+/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
+   deprecated but was the only choice up until 7.31.0 */
+typedef int (*curl_progress_callback)(void *clientp,
+                                      double dltotal,
+                                      double dlnow,
+                                      double ultotal,
+                                      double ulnow);
+
+/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
+   7.32.0, it avoids floating point and provides more detailed information. */
+typedef int (*curl_xferinfo_callback)(void *clientp,
+                                      curl_off_t dltotal,
+                                      curl_off_t dlnow,
+                                      curl_off_t ultotal,
+                                      curl_off_t ulnow);
+
+#ifndef CURL_MAX_WRITE_SIZE
+  /* Tests have proven that 20K is a very bad buffer size for uploads on
+     Windows, while 16K for some odd reason performed a lot better.
+     We do the ifndef check to allow this value to easier be changed at build
+     time for those who feel adventurous. The practical minimum is about
+     400 bytes since libcurl uses a buffer of this size as a scratch area
+     (unrelated to network send operations). */
+#define CURL_MAX_WRITE_SIZE 16384
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+/* The only reason to have a max limit for this is to avoid the risk of a bad
+   server feeding libcurl with a never-ending header that will cause reallocs
+   infinitely */
+#define CURL_MAX_HTTP_HEADER (100*1024)
+#endif
+
+/* This is a magic return code for the write callback that, when returned,
+   will signal libcurl to pause receiving on the current transfer. */
+#define CURL_WRITEFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_write_callback)(char *buffer,
+                                      size_t size,
+                                      size_t nitems,
+                                      void *outstream);
+
+
+
+/* enumeration of file types */
+typedef enum {
+  CURLFILETYPE_FILE = 0,
+  CURLFILETYPE_DIRECTORY,
+  CURLFILETYPE_SYMLINK,
+  CURLFILETYPE_DEVICE_BLOCK,
+  CURLFILETYPE_DEVICE_CHAR,
+  CURLFILETYPE_NAMEDPIPE,
+  CURLFILETYPE_SOCKET,
+  CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
+
+  CURLFILETYPE_UNKNOWN /* should never occur */
+} curlfiletype;
+
+#define CURLFINFOFLAG_KNOWN_FILENAME    (1<<0)
+#define CURLFINFOFLAG_KNOWN_FILETYPE    (1<<1)
+#define CURLFINFOFLAG_KNOWN_TIME        (1<<2)
+#define CURLFINFOFLAG_KNOWN_PERM        (1<<3)
+#define CURLFINFOFLAG_KNOWN_UID         (1<<4)
+#define CURLFINFOFLAG_KNOWN_GID         (1<<5)
+#define CURLFINFOFLAG_KNOWN_SIZE        (1<<6)
+#define CURLFINFOFLAG_KNOWN_HLINKCOUNT  (1<<7)
+
+/* Content of this structure depends on information which is known and is
+   achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
+   page for callbacks returning this structure -- some fields are mandatory,
+   some others are optional. The FLAG field has special meaning. */
+struct curl_fileinfo {
+  char *filename;
+  curlfiletype filetype;
+  time_t time;
+  unsigned int perm;
+  int uid;
+  int gid;
+  curl_off_t size;
+  long int hardlinks;
+
+  struct {
+    /* If some of these fields is not NULL, it is a pointer to b_data. */
+    char *time;
+    char *perm;
+    char *user;
+    char *group;
+    char *target; /* pointer to the target filename of a symlink */
+  } strings;
+
+  unsigned int flags;
+
+  /* used internally */
+  char * b_data;
+  size_t b_size;
+  size_t b_used;
+};
+
+/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
+#define CURL_CHUNK_BGN_FUNC_OK      0
+#define CURL_CHUNK_BGN_FUNC_FAIL    1 /* tell the lib to end the task */
+#define CURL_CHUNK_BGN_FUNC_SKIP    2 /* skip this chunk over */
+
+/* if splitting of data transfer is enabled, this callback is called before
+   download of an individual chunk started. Note that parameter "remains" works
+   only for FTP wildcard downloading (for now), otherwise is not used */
+typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
+                                        void *ptr,
+                                        int remains);
+
+/* return codes for CURLOPT_CHUNK_END_FUNCTION */
+#define CURL_CHUNK_END_FUNC_OK      0
+#define CURL_CHUNK_END_FUNC_FAIL    1 /* tell the lib to end the task */
+
+/* If splitting of data transfer is enabled this callback is called after
+   download of an individual chunk finished.
+   Note! After this callback was set then it have to be called FOR ALL chunks.
+   Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
+   This is the reason why we don't need "transfer_info" parameter in this
+   callback and we are not interested in "remains" parameter too. */
+typedef long (*curl_chunk_end_callback)(void *ptr);
+
+/* return codes for FNMATCHFUNCTION */
+#define CURL_FNMATCHFUNC_MATCH    0 /* string corresponds to the pattern */
+#define CURL_FNMATCHFUNC_NOMATCH  1 /* pattern doesn't match the string */
+#define CURL_FNMATCHFUNC_FAIL     2 /* an error occurred */
+
+/* callback type for wildcard downloading pattern matching. If the
+   string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
+typedef int (*curl_fnmatch_callback)(void *ptr,
+                                     const char *pattern,
+                                     const char *string);
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK       0
+#define CURL_SEEKFUNC_FAIL     1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+                                    libcurl might try other means instead */
+typedef int (*curl_seek_callback)(void *instream,
+                                  curl_off_t offset,
+                                  int origin); /* 'whence' */
+
+/* This is a return code for the read callback that, when returned, will
+   signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+/* This is a return code for the read callback that, when returned, will
+   signal libcurl to pause sending data on the current transfer. */
+#define CURL_READFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_read_callback)(char *buffer,
+                                      size_t size,
+                                      size_t nitems,
+                                      void *instream);
+
+typedef enum  {
+  CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
+  CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+  CURLSOCKTYPE_LAST    /* never use */
+} curlsocktype;
+
+/* The return code from the sockopt_callback can signal information back
+   to libcurl: */
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+                                CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+typedef int (*curl_sockopt_callback)(void *clientp,
+                                     curl_socket_t curlfd,
+                                     curlsocktype purpose);
+
+struct curl_sockaddr {
+  int family;
+  int socktype;
+  int protocol;
+  unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
+                           turned really ugly and painful on the systems that
+                           lack this type */
+  struct sockaddr addr;
+};
+
+typedef curl_socket_t
+(*curl_opensocket_callback)(void *clientp,
+                            curlsocktype purpose,
+                            struct curl_sockaddr *address);
+
+typedef int
+(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+typedef enum {
+  CURLIOE_OK,            /* I/O operation successful */
+  CURLIOE_UNKNOWNCMD,    /* command was unknown to callback */
+  CURLIOE_FAILRESTART,   /* failed to restart the read */
+  CURLIOE_LAST           /* never use */
+} curlioerr;
+
+typedef enum  {
+  CURLIOCMD_NOP,         /* no operation */
+  CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+  CURLIOCMD_LAST         /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+                                         int cmd,
+                                         void *clientp);
+
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively.  Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+  CURLINFO_TEXT = 0,
+  CURLINFO_HEADER_IN,    /* 1 */
+  CURLINFO_HEADER_OUT,   /* 2 */
+  CURLINFO_DATA_IN,      /* 3 */
+  CURLINFO_DATA_OUT,     /* 4 */
+  CURLINFO_SSL_DATA_IN,  /* 5 */
+  CURLINFO_SSL_DATA_OUT, /* 6 */
+  CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+       (CURL *handle,      /* the handle/transfer this concerns */
+        curl_infotype type, /* what kind of data */
+        char *data,        /* points to the data */
+        size_t size,       /* size of the data pointed to */
+        void *userptr);    /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+   may return other values, stay prepared.
+
+   Always add new return codes last. Never *EVER* remove any. The return
+   codes must remain the same!
+ */
+
+typedef enum {
+  CURLE_OK = 0,
+  CURLE_UNSUPPORTED_PROTOCOL,    /* 1 */
+  CURLE_FAILED_INIT,             /* 2 */
+  CURLE_URL_MALFORMAT,           /* 3 */
+  CURLE_NOT_BUILT_IN,            /* 4 - [was obsoleted in August 2007 for
+                                    7.17.0, reused in April 2011 for 7.21.5] */
+  CURLE_COULDNT_RESOLVE_PROXY,   /* 5 */
+  CURLE_COULDNT_RESOLVE_HOST,    /* 6 */
+  CURLE_COULDNT_CONNECT,         /* 7 */
+  CURLE_FTP_WEIRD_SERVER_REPLY,  /* 8 */
+  CURLE_REMOTE_ACCESS_DENIED,    /* 9 a service was denied by the server
+                                    due to lack of access - when login fails
+                                    this is not returned. */
+  CURLE_FTP_ACCEPT_FAILED,       /* 10 - [was obsoleted in April 2006 for
+                                    7.15.4, reused in Dec 2011 for 7.24.0]*/
+  CURLE_FTP_WEIRD_PASS_REPLY,    /* 11 */
+  CURLE_FTP_ACCEPT_TIMEOUT,      /* 12 - timeout occurred accepting server
+                                    [was obsoleted in August 2007 for 7.17.0,
+                                    reused in Dec 2011 for 7.24.0]*/
+  CURLE_FTP_WEIRD_PASV_REPLY,    /* 13 */
+  CURLE_FTP_WEIRD_227_FORMAT,    /* 14 */
+  CURLE_FTP_CANT_GET_HOST,       /* 15 */
+  CURLE_HTTP2,                   /* 16 - A problem in the http2 framing layer.
+                                    [was obsoleted in August 2007 for 7.17.0,
+                                    reused in July 2014 for 7.38.0] */
+  CURLE_FTP_COULDNT_SET_TYPE,    /* 17 */
+  CURLE_PARTIAL_FILE,            /* 18 */
+  CURLE_FTP_COULDNT_RETR_FILE,   /* 19 */
+  CURLE_OBSOLETE20,              /* 20 - NOT USED */
+  CURLE_QUOTE_ERROR,             /* 21 - quote command failure */
+  CURLE_HTTP_RETURNED_ERROR,     /* 22 */
+  CURLE_WRITE_ERROR,             /* 23 */
+  CURLE_OBSOLETE24,              /* 24 - NOT USED */
+  CURLE_UPLOAD_FAILED,           /* 25 - failed upload "command" */
+  CURLE_READ_ERROR,              /* 26 - couldn't open/read from file */
+  CURLE_OUT_OF_MEMORY,           /* 27 */
+  /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+           instead of a memory allocation error if CURL_DOES_CONVERSIONS
+           is defined
+  */
+  CURLE_OPERATION_TIMEDOUT,      /* 28 - the timeout time was reached */
+  CURLE_OBSOLETE29,              /* 29 - NOT USED */
+  CURLE_FTP_PORT_FAILED,         /* 30 - FTP PORT operation failed */
+  CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */
+  CURLE_OBSOLETE32,              /* 32 - NOT USED */
+  CURLE_RANGE_ERROR,             /* 33 - RANGE "command" didn't work */
+  CURLE_HTTP_POST_ERROR,         /* 34 */
+  CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */
+  CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - couldn't resume download */
+  CURLE_FILE_COULDNT_READ_FILE,  /* 37 */
+  CURLE_LDAP_CANNOT_BIND,        /* 38 */
+  CURLE_LDAP_SEARCH_FAILED,      /* 39 */
+  CURLE_OBSOLETE40,              /* 40 - NOT USED */
+  CURLE_FUNCTION_NOT_FOUND,      /* 41 */
+  CURLE_ABORTED_BY_CALLBACK,     /* 42 */
+  CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
+  CURLE_OBSOLETE44,              /* 44 - NOT USED */
+  CURLE_INTERFACE_FAILED,        /* 45 - CURLOPT_INTERFACE failed */
+  CURLE_OBSOLETE46,              /* 46 - NOT USED */
+  CURLE_TOO_MANY_REDIRECTS ,     /* 47 - catch endless re-direct loops */
+  CURLE_UNKNOWN_OPTION,          /* 48 - User specified an unknown option */
+  CURLE_TELNET_OPTION_SYNTAX ,   /* 49 - Malformed telnet option */
+  CURLE_OBSOLETE50,              /* 50 - NOT USED */
+  CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
+                                     wasn't verified fine */
+  CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
+  CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
+  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
+                                    default */
+  CURLE_SEND_ERROR,              /* 55 - failed sending network data */
+  CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
+  CURLE_OBSOLETE57,              /* 57 - NOT IN USE */
+  CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */
+  CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */
+  CURLE_SSL_CACERT,              /* 60 - problem with the CA cert (path?) */
+  CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized/bad encoding */
+  CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */
+  CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */
+  CURLE_USE_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */
+  CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind
+                                    that failed */
+  CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */
+  CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not
+                                    accepted and we failed to login */
+  CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */
+  CURLE_TFTP_PERM,               /* 69 - permission problem on server */
+  CURLE_REMOTE_DISK_FULL,        /* 70 - out of disk space on server */
+  CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */
+  CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */
+  CURLE_REMOTE_FILE_EXISTS,      /* 73 - File already exists */
+  CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */
+  CURLE_CONV_FAILED,             /* 75 - conversion failed */
+  CURLE_CONV_REQD,               /* 76 - caller must register conversion
+                                    callbacks using curl_easy_setopt options
+                                    CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+                                    CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+                                    CURLOPT_CONV_FROM_UTF8_FUNCTION */
+  CURLE_SSL_CACERT_BADFILE,      /* 77 - could not load CACERT file, missing
+                                    or wrong format */
+  CURLE_REMOTE_FILE_NOT_FOUND,   /* 78 - remote file not found */
+  CURLE_SSH,                     /* 79 - error from the SSH layer, somewhat
+                                    generic so the error message will be of
+                                    interest when this has happened */
+
+  CURLE_SSL_SHUTDOWN_FAILED,     /* 80 - Failed to shut down the SSL
+                                    connection */
+  CURLE_AGAIN,                   /* 81 - socket is not ready for send/recv,
+                                    wait till it's ready and try again(Added
+                                    in 7.18.2) */
+  CURLE_SSL_CRL_BADFILE,         /* 82 - could not load CRL file, missing or
+                                    wrong format(Added in 7.19.0) */
+  CURLE_SSL_ISSUER_ERROR,        /* 83 - Issuer check failed.  (Added in
+                                    7.19.0) */
+  CURLE_FTP_PRET_FAILED,         /* 84 - a PRET command failed */
+  CURLE_RTSP_CSEQ_ERROR,         /* 85 - mismatch of RTSP CSeq numbers */
+  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Ids */
+  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
+  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
+  CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
+                                    session will be queued */
+  CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
+                                     match */
+  CURLE_SSL_INVALIDCERTSTATUS,   /* 91 - invalid certificate status */
+  CURL_LAST /* never use! */
+} CURLcode;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all the obsoletetuff removed!*/
+
+/* Previously obsolete error code re-used in 7.38.0 */
+#define CURLE_OBSOLETE16 CURLE_HTTP2
+
+/* Previously obsolete error codes re-used in 7.24.0 */
+#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
+#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
+
+/*  compatibility with older names */
+#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+
+/* The following were added in 7.21.5, April 2011 */
+#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+/* The following were added in 7.17.1 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.17.0 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+
+/* The following were added earlier */
+
+#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
+
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
+
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+/* This was the error code 50 in 7.7.3 and a few earlier versions, this
+   is no longer used by libcurl but is instead #defined here only to not
+   make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* Provide defines for really old option names */
+#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
+#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
+#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
+
+/* Since long deprecated options with no code in the lib that does anything
+   with them. */
+#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+
+#endif /*!CURL_NO_OLDIES*/
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */
+                                          void *ssl_ctx, /* actually an
+                                                            OpenSSL SSL_CTX */
+                                          void *userptr);
+
+typedef enum {
+  CURLPROXY_HTTP = 0,   /* added in 7.10, new in 7.19.4 default is to use
+                           CONNECT HTTP/1.1 */
+  CURLPROXY_HTTP_1_0 = 1,   /* added in 7.19.4, force to use CONNECT
+                               HTTP/1.0  */
+  CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+                           in 7.10 */
+  CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+  CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+  CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+                                   host name rather than the IP address. added
+                                   in 7.18.0 */
+} curl_proxytype;  /* this enum was added in 7.10 */
+
+/*
+ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
+ *
+ * CURLAUTH_NONE         - No HTTP authentication
+ * CURLAUTH_BASIC        - HTTP Basic authentication (default)
+ * CURLAUTH_DIGEST       - HTTP Digest authentication
+ * CURLAUTH_NEGOTIATE    - HTTP Negotiate (SPNEGO) authentication
+ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
+ * CURLAUTH_NTLM         - HTTP NTLM authentication
+ * CURLAUTH_DIGEST_IE    - HTTP Digest authentication with IE flavour
+ * CURLAUTH_NTLM_WB      - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_ONLY         - Use together with a single other type to force no
+ *                         authentication or just that single type
+ * CURLAUTH_ANY          - All fine types set
+ * CURLAUTH_ANYSAFE      - All fine types except Basic
+ */
+
+#define CURLAUTH_NONE         ((unsigned long)0)
+#define CURLAUTH_BASIC        (((unsigned long)1) << 0)
+#define CURLAUTH_DIGEST       (((unsigned long)1) << 1)
+#define CURLAUTH_NEGOTIATE    (((unsigned long)1) << 2)
+/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
+#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
+#define CURLAUTH_NTLM         (((unsigned long)1) << 3)
+#define CURLAUTH_DIGEST_IE    (((unsigned long)1) << 4)
+#define CURLAUTH_NTLM_WB      (((unsigned long)1) << 5)
+#define CURLAUTH_ONLY         (((unsigned long)1) << 31)
+#define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)
+#define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+#define CURLSSH_AUTH_ANY       ~0     /* all types supported by the server */
+#define CURLSSH_AUTH_NONE      0      /* none allowed, silly but complete */
+#define CURLSSH_AUTH_PUBLICKEY (1 << 0) /* public/private key files */
+#define CURLSSH_AUTH_PASSWORD  (1 << 1) /* password */
+#define CURLSSH_AUTH_HOST      (1 << 2) /* host key files */
+#define CURLSSH_AUTH_KEYBOARD  (1 << 3) /* keyboard interactive */
+#define CURLSSH_AUTH_AGENT     (1 << 4) /* agent (ssh-agent, pageant...) */
+#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
+#define CURLGSSAPI_DELEGATION_NONE        0      /* no delegation (default) */
+#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1 << 0) /* if permitted by policy */
+#define CURLGSSAPI_DELEGATION_FLAG        (1 << 1) /* delegate always */
+
+#define CURL_ERROR_SIZE 256
+
+enum curl_khtype {
+  CURLKHTYPE_UNKNOWN,
+  CURLKHTYPE_RSA1,
+  CURLKHTYPE_RSA,
+  CURLKHTYPE_DSS
+};
+
+struct curl_khkey {
+  const char *key; /* points to a zero-terminated string encoded with base64
+                      if len is zero, otherwise to the "raw" data */
+  size_t len;
+  enum curl_khtype keytype;
+};
+
+/* this is the set of return values expected from the curl_sshkeycallback
+   callback */
+enum curl_khstat {
+  CURLKHSTAT_FINE_ADD_TO_FILE,
+  CURLKHSTAT_FINE,
+  CURLKHSTAT_REJECT, /* reject the connection, return an error */
+  CURLKHSTAT_DEFER,  /* do not accept it, but we can't answer right now so
+                        this causes a CURLE_DEFER error but otherwise the
+                        connection will be left intact etc */
+  CURLKHSTAT_LAST    /* not for use, only a marker for last-in-list */
+};
+
+/* this is the set of status codes pass in to the callback */
+enum curl_khmatch {
+  CURLKHMATCH_OK,       /* match */
+  CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+  CURLKHMATCH_MISSING,  /* no matching host/key found */
+  CURLKHMATCH_LAST      /* not for use, only a marker for last-in-list */
+};
+
+typedef int
+  (*curl_sshkeycallback) (CURL *easy,     /* easy handle */
+                          const struct curl_khkey *knownkey, /* known */
+                          const struct curl_khkey *foundkey, /* found */
+                          enum curl_khmatch, /* libcurl's view on the keys */
+                          void *clientp); /* custom pointer passed from app */
+
+/* parameter for the CURLOPT_USE_SSL option */
+typedef enum {
+  CURLUSESSL_NONE,    /* do not attempt to use SSL */
+  CURLUSESSL_TRY,     /* try using SSL, proceed anyway otherwise */
+  CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+  CURLUSESSL_ALL,     /* SSL for all communication or fail */
+  CURLUSESSL_LAST     /* not an option, never use */
+} curl_usessl;
+
+/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
+
+/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
+   name of improving interoperability with older servers. Some SSL libraries
+   have introduced work-arounds for this flaw but those work-arounds sometimes
+   make the SSL communication fail. To regain functionality with those broken
+   servers, a user can this way allow the vulnerability back. */
+#define CURLSSLOPT_ALLOW_BEAST (1 << 0)
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all the obsolete stuff removed */
+
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2009 */
+
+#define CURLFTPSSL_NONE CURLUSESSL_NONE
+#define CURLFTPSSL_TRY CURLUSESSL_TRY
+#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
+#define CURLFTPSSL_ALL CURLUSESSL_ALL
+#define CURLFTPSSL_LAST CURLUSESSL_LAST
+#define curl_ftpssl curl_usessl
+#endif /*!CURL_NO_OLDIES*/
+
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+  CURLFTPSSL_CCC_NONE,    /* do not send CCC */
+  CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+  CURLFTPSSL_CCC_ACTIVE,  /* Initiate the shutdown */
+  CURLFTPSSL_CCC_LAST     /* not an option, never use */
+} curl_ftpccc;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+  CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+  CURLFTPAUTH_SSL,     /* use "AUTH SSL" */
+  CURLFTPAUTH_TLS,     /* use "AUTH TLS" */
+  CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
+typedef enum {
+  CURLFTP_CREATE_DIR_NONE,  /* do NOT create missing dirs! */
+  CURLFTP_CREATE_DIR,       /* (FTP/SFTP) if CWD fails, try MKD and then CWD
+                               again if MKD succeeded, for SFTP this does
+                               similar magic */
+  CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD again even if MKD failed */
+
+  CURLFTP_CREATE_DIR_LAST   /* not an option, never use */
+} curl_ftpcreatedir;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+  CURLFTPMETHOD_DEFAULT,   /* let libcurl pick */
+  CURLFTPMETHOD_MULTICWD,  /* single CWD operation for each path part */
+  CURLFTPMETHOD_NOCWD,     /* no CWD at all */
+  CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+  CURLFTPMETHOD_LAST       /* not an option, never use */
+} curl_ftpmethod;
+
+/* bitmask defines for CURLOPT_HEADEROPT */
+#define CURLHEADER_UNIFIED  0
+#define CURLHEADER_SEPARATE (1<<0)
+
+/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+#define CURLPROTO_HTTP   (1<<0)
+#define CURLPROTO_HTTPS  (1<<1)
+#define CURLPROTO_FTP    (1<<2)
+#define CURLPROTO_FTPS   (1<<3)
+#define CURLPROTO_SCP    (1<<4)
+#define CURLPROTO_SFTP   (1<<5)
+#define CURLPROTO_TELNET (1<<6)
+#define CURLPROTO_LDAP   (1<<7)
+#define CURLPROTO_LDAPS  (1<<8)
+#define CURLPROTO_DICT   (1<<9)
+#define CURLPROTO_FILE   (1<<10)
+#define CURLPROTO_TFTP   (1<<11)
+#define CURLPROTO_IMAP   (1<<12)
+#define CURLPROTO_IMAPS  (1<<13)
+#define CURLPROTO_POP3   (1<<14)
+#define CURLPROTO_POP3S  (1<<15)
+#define CURLPROTO_SMTP   (1<<16)
+#define CURLPROTO_SMTPS  (1<<17)
+#define CURLPROTO_RTSP   (1<<18)
+#define CURLPROTO_RTMP   (1<<19)
+#define CURLPROTO_RTMPT  (1<<20)
+#define CURLPROTO_RTMPE  (1<<21)
+#define CURLPROTO_RTMPTE (1<<22)
+#define CURLPROTO_RTMPS  (1<<23)
+#define CURLPROTO_RTMPTS (1<<24)
+#define CURLPROTO_GOPHER (1<<25)
+#define CURLPROTO_SMB    (1<<26)
+#define CURLPROTO_SMBS   (1<<27)
+#define CURLPROTO_ALL    (~0) /* enable everything */
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+   but 32 */
+#define CURLOPTTYPE_LONG          0
+#define CURLOPTTYPE_OBJECTPOINT   10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T         30000
+
+/* name is uppercase CURLOPT_<name>,
+   type is one of the defined CURLOPTTYPE_<type>
+   number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(na, t, nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG          CURLOPTTYPE_LONG
+#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T         CURLOPTTYPE_OFF_T
+#define CINIT(name, type, number) CURLOPT_/**/name = type + number
+#endif
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+  /* This is the FILE * or void * the regular output should be written to. */
+  CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+  /* The full URL to get/put */
+  CINIT(URL, OBJECTPOINT, 2),
+
+  /* Port number to connect to, if other than default. */
+  CINIT(PORT, LONG, 3),
+
+  /* Name of proxy to use. */
+  CINIT(PROXY, OBJECTPOINT, 4),
+
+  /* "user:password;options" to use when fetching. */
+  CINIT(USERPWD, OBJECTPOINT, 5),
+
+  /* "user:password" to use with proxy. */
+  CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
+
+  /* Range to get, specified as an ASCII string. */
+  CINIT(RANGE, OBJECTPOINT, 7),
+
+  /* not used */
+
+  /* Specified file stream to upload from (use as input): */
+  CINIT(READDATA, OBJECTPOINT, 9),
+
+  /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+   * bytes big. If this is not used, error messages go to stderr instead: */
+  CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+  /* Function that will be called to store the output (instead of fwrite). The
+   * parameters will use fwrite() syntax, make sure to follow them. */
+  CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+  /* Function that will be called to read the input (instead of fread). The
+   * parameters will use fread() syntax, make sure to follow them. */
+  CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+  /* Time-out the read operation after this amount of seconds */
+  CINIT(TIMEOUT, LONG, 13),
+
+  /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+   * how large the file being sent really is. That allows better error
+   * checking and better verifies that the upload was successful. -1 means
+   * unknown size.
+   *
+   * For large file support, there is also a _LARGE version of the key
+   * which takes an off_t type, allowing platforms with larger off_t
+   * sizes to handle larger files.  See below for INFILESIZE_LARGE.
+   */
+  CINIT(INFILESIZE, LONG, 14),
+
+  /* POST static input fields. */
+  CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+  /* Set the referrer page (needed by some CGIs) */
+  CINIT(REFERER, OBJECTPOINT, 16),
+
+  /* Set the FTP PORT string (interface name, named or numerical IP address)
+     Use i.e '-' to use default address. */
+  CINIT(FTPPORT, OBJECTPOINT, 17),
+
+  /* Set the User-Agent string (examined by some CGIs) */
+  CINIT(USERAGENT, OBJECTPOINT, 18),
+
+  /* If the download receives less than "low speed limit" bytes/second
+   * during "low speed time" seconds, the operations is aborted.
+   * You could i.e if you have a pretty high speed connection, abort if
+   * it is less than 2000 bytes/sec during 20 seconds.
+   */
+
+  /* Set the "low speed limit" */
+  CINIT(LOW_SPEED_LIMIT, LONG, 19),
+
+  /* Set the "low speed time" */
+  CINIT(LOW_SPEED_TIME, LONG, 20),
+
+  /* Set the continuation offset.
+   *
+   * Note there is also a _LARGE version of this key which uses
+   * off_t types, allowing for large file offsets on platforms which
+   * use larger-than-32-bit off_t's.  Look below for RESUME_FROM_LARGE.
+   */
+  CINIT(RESUME_FROM, LONG, 21),
+
+  /* Set cookie in request: */
+  CINIT(COOKIE, OBJECTPOINT, 22),
+
+  /* This points to a linked list of headers, struct curl_slist kind. This
+     list is also used for RTSP (in spite of its name) */
+  CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+  /* This points to a linked list of post entries, struct curl_httppost */
+  CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+  /* name of the file keeping your private SSL-certificate */
+  CINIT(SSLCERT, OBJECTPOINT, 25),
+
+  /* password for the SSL or SSH private key */
+  CINIT(KEYPASSWD, OBJECTPOINT, 26),
+
+  /* send TYPE parameter? */
+  CINIT(CRLF, LONG, 27),
+
+  /* send linked-list of QUOTE commands */
+  CINIT(QUOTE, OBJECTPOINT, 28),
+
+  /* send FILE * or void * to store headers to, if you use a callback it
+     is simply passed to the callback unmodified */
+  CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+  /* point to a file to read the initial cookies from, also enables
+     "cookie awareness" */
+  CINIT(COOKIEFILE, OBJECTPOINT, 31),
+
+  /* What version to specifically try to use.
+     See CURL_SSLVERSION defines below. */
+  CINIT(SSLVERSION, LONG, 32),
+
+  /* What kind of HTTP time condition to use, see defines */
+  CINIT(TIMECONDITION, LONG, 33),
+
+  /* Time to use with the above condition. Specified in number of seconds
+     since 1 Jan 1970 */
+  CINIT(TIMEVALUE, LONG, 34),
+
+  /* 35 = OBSOLETE */
+
+  /* Custom request, for customizing the get command like
+     HTTP: DELETE, TRACE and others
+     FTP: to use a different list command
+     */
+  CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
+
+  /* HTTP request, for odd commands like DELETE, TRACE and others */
+  CINIT(STDERR, OBJECTPOINT, 37),
+
+  /* 38 is not used */
+
+  /* send linked-list of post-transfer QUOTE commands */
+  CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+  CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+  CINIT(VERBOSE, LONG, 41),      /* talk a lot */
+  CINIT(HEADER, LONG, 42),       /* throw the header out too */
+  CINIT(NOPROGRESS, LONG, 43),   /* shut off the progress meter */
+  CINIT(NOBODY, LONG, 44),       /* use HEAD to get http document */
+  CINIT(FAILONERROR, LONG, 45),  /* no output on http error codes >= 400 */
+  CINIT(UPLOAD, LONG, 46),       /* this is an upload */
+  CINIT(POST, LONG, 47),         /* HTTP POST method */
+  CINIT(DIRLISTONLY, LONG, 48),  /* bare names when listing directories */
+
+  CINIT(APPEND, LONG, 50),       /* Append instead of overwrite on upload! */
+
+  /* Specify whether to read the user+password from the .netrc or the URL.
+   * This must be one of the CURL_NETRC_* enums below. */
+  CINIT(NETRC, LONG, 51),
+
+  CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
+
+  CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+  CINIT(PUT, LONG, 54),          /* HTTP PUT */
+
+  /* 55 = OBSOLETE */
+
+  /* DEPRECATED
+   * Function that will be called instead of the internal progress display
+   * function. This function should be defined as the curl_progress_callback
+   * prototype defines. */
+  CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+  /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
+     callbacks */
+  CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+  /* We want the referrer field set automatically when following locations */
+  CINIT(AUTOREFERER, LONG, 58),
+
+  /* Port of the proxy, can be set in the proxy string as well with:
+     "[host]:[port]" */
+  CINIT(PROXYPORT, LONG, 59),
+
+  /* size of the POST input data, if strlen() is not good to use */
+  CINIT(POSTFIELDSIZE, LONG, 60),
+
+  /* tunnel non-http operations through a HTTP proxy */
+  CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+  /* Set the interface string to use as outgoing network interface */
+  CINIT(INTERFACE, OBJECTPOINT, 62),
+
+  /* Set the krb4/5 security level, this also enables krb4/5 awareness.  This
+   * is a string, 'clear', 'safe', 'confidential' or 'private'.  If the string
+   * is set but doesn't match one of these, 'private' will be used.  */
+  CINIT(KRBLEVEL, OBJECTPOINT, 63),
+
+  /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+  CINIT(SSL_VERIFYPEER, LONG, 64),
+
+  /* The CApath or CAfile used to validate the peer certificate
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(CAINFO, OBJECTPOINT, 65),
+
+  /* 66 = OBSOLETE */
+  /* 67 = OBSOLETE */
+
+  /* Maximum number of http redirects to follow */
+  CINIT(MAXREDIRS, LONG, 68),
+
+  /* Pass a long set to 1 to get the date of the requested document (if
+     possible)! Pass a zero to shut it off. */
+  CINIT(FILETIME, LONG, 69),
+
+  /* This points to a linked list of telnet options */
+  CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+  /* Max amount of cached alive connections */
+  CINIT(MAXCONNECTS, LONG, 71),
+
+  CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+  /* 73 = OBSOLETE */
+
+  /* Set to explicitly use a new connection for the upcoming transfer.
+     Do not use this unless you're absolutely sure of this, as it makes the
+     operation slower and is less friendly for the network. */
+  CINIT(FRESH_CONNECT, LONG, 74),
+
+  /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+     when done. Do not use this unless you're absolutely sure of this, as it
+     makes the operation slower and is less friendly for the network. */
+  CINIT(FORBID_REUSE, LONG, 75),
+
+  /* Set to a file name that contains random data for libcurl to use to
+     seed the random engine when doing SSL connects. */
+  CINIT(RANDOM_FILE, OBJECTPOINT, 76),
+
+  /* Set to the Entropy Gathering Daemon socket pathname */
+  CINIT(EGDSOCKET, OBJECTPOINT, 77),
+
+  /* Time-out connect operations after this amount of seconds, if connects are
+     OK within this time, then fine... This only aborts the connect phase. */
+  CINIT(CONNECTTIMEOUT, LONG, 78),
+
+  /* Function that will be called to store headers (instead of fwrite). The
+   * parameters will use fwrite() syntax, make sure to follow them. */
+  CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+  /* Set this to force the HTTP request to get back to GET. Only really usable
+     if POST, PUT or a custom request have been used first.
+   */
+  CINIT(HTTPGET, LONG, 80),
+
+  /* Set if we should verify the Common name from the peer certificate in ssl
+   * handshake, set 1 to check existence, 2 to ensure that it matches the
+   * provided hostname. */
+  CINIT(SSL_VERIFYHOST, LONG, 81),
+
+  /* Specify which file name to write all known cookies in after completed
+     operation. Set file name to "-" (dash) to make it go to stdout. */
+  CINIT(COOKIEJAR, OBJECTPOINT, 82),
+
+  /* Specify which SSL ciphers to use */
+  CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
+
+  /* Specify which HTTP version to use! This must be set to one of the
+     CURL_HTTP_VERSION* enums set below. */
+  CINIT(HTTP_VERSION, LONG, 84),
+
+  /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+     default, that one will always be attempted before the more traditional
+     PASV command. */
+  CINIT(FTP_USE_EPSV, LONG, 85),
+
+  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+  CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
+
+  /* name of the file keeping your private SSL-key */
+  CINIT(SSLKEY, OBJECTPOINT, 87),
+
+  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+  CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
+
+  /* crypto engine for the SSL-sub system */
+  CINIT(SSLENGINE, OBJECTPOINT, 89),
+
+  /* set the crypto engine for the SSL-sub system as default
+     the param has no meaning...
+   */
+  CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+  /* Non-zero value means to use the global dns cache */
+  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+  /* DNS cache timeout */
+  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+  /* send linked-list of pre-transfer QUOTE commands */
+  CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+  /* set the debug function */
+  CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+  /* set the data for the debug function */
+  CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+  /* mark this as start of a cookie session */
+  CINIT(COOKIESESSION, LONG, 96),
+
+  /* The CApath directory used to validate the peer certificate
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(CAPATH, OBJECTPOINT, 97),
+
+  /* Instruct libcurl to use a smaller receive buffer */
+  CINIT(BUFFERSIZE, LONG, 98),
+
+  /* Instruct libcurl to not use any signal/alarm handlers, even when using
+     timeouts. This option is useful for multi-threaded applications.
+     See libcurl-the-guide for more background information. */
+  CINIT(NOSIGNAL, LONG, 99),
+
+  /* Provide a CURLShare for mutexing non-ts data */
+  CINIT(SHARE, OBJECTPOINT, 100),
+
+  /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+     CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+  CINIT(PROXYTYPE, LONG, 101),
+
+  /* Set the Accept-Encoding string. Use this to tell a server you would like
+     the response to be compressed. Before 7.21.6, this was known as
+     CURLOPT_ENCODING */
+  CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102),
+
+  /* Set pointer to private data */
+  CINIT(PRIVATE, OBJECTPOINT, 103),
+
+  /* Set aliases for HTTP 200 in the HTTP Response header */
+  CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+  /* Continue to send authentication (user+password) when following locations,
+     even when hostname changed. This can potentially send off the name
+     and password to whatever host the server decides. */
+  CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+  /* Specifically switch on or off the FTP engine's use of the EPRT command (
+     it also disables the LPRT attempt). By default, those ones will always be
+     attempted before the good old traditional PORT command. */
+  CINIT(FTP_USE_EPRT, LONG, 106),
+
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_USERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(HTTPAUTH, LONG, 107),
+
+  /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
+     in second argument. The function must be matching the
+     curl_ssl_ctx_callback proto. */
+  CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+  /* Set the userdata for the ssl context callback function's third
+     argument */
+  CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+  /* FTP Option that causes missing dirs to be created on the remote server.
+     In 7.19.4 we introduced the convenience enums for this option using the
+     CURLFTP_CREATE_DIR prefix.
+  */
+  CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(PROXYAUTH, LONG, 111),
+
+  /* FTP option that changes the timeout, in seconds, associated with
+     getting a response.  This is different from transfer timeout time and
+     essentially places a demand on the FTP server to acknowledge commands
+     in a timely manner. */
+  CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+  /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+     tell libcurl to resolve names to those IP versions only. This only has
+     affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+  CINIT(IPRESOLVE, LONG, 113),
+
+  /* Set this option to limit the size of a file that will be downloaded from
+     an HTTP or FTP server.
+
+     Note there is also _LARGE version which adds large file support for
+     platforms which have larger off_t sizes.  See MAXFILESIZE_LARGE below. */
+  CINIT(MAXFILESIZE, LONG, 114),
+
+  /* See the comment for INFILESIZE above, but in short, specifies
+   * the size of the file being uploaded.  -1 means unknown.
+   */
+  CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+  /* Sets the continuation offset.  There is also a LONG version of this;
+   * look above for RESUME_FROM.
+   */
+  CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+  /* Sets the maximum size of data that will be downloaded from
+   * an HTTP or FTP server.  See MAXFILESIZE above for the LONG version.
+   */
+  CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+  /* Set this option to the file name of your .netrc file you want libcurl
+     to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+     a poor attempt to find the user's home directory and check for a .netrc
+     file in there. */
+  CINIT(NETRC_FILE, OBJECTPOINT, 118),
+
+  /* Enable SSL/TLS for FTP, pick one of:
+     CURLUSESSL_TRY     - try using SSL, proceed anyway otherwise
+     CURLUSESSL_CONTROL - SSL for the control connection or fail
+     CURLUSESSL_ALL     - SSL for all communication or fail
+  */
+  CINIT(USE_SSL, LONG, 119),
+
+  /* The _LARGE version of the standard POSTFIELDSIZE option */
+  CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+  /* Enable/disable the TCP Nagle algorithm */
+  CINIT(TCP_NODELAY, LONG, 121),
+
+  /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 123 OBSOLETE. Gone in 7.16.0 */
+  /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 127 OBSOLETE. Gone in 7.16.0 */
+  /* 128 OBSOLETE. Gone in 7.16.0 */
+
+  /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
+     can be used to change libcurl's default action which is to first try
+     "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+     response has been received.
+
+     Available parameters are:
+     CURLFTPAUTH_DEFAULT - let libcurl decide
+     CURLFTPAUTH_SSL     - try "AUTH SSL" first, then TLS
+     CURLFTPAUTH_TLS     - try "AUTH TLS" first, then SSL
+  */
+  CINIT(FTPSSLAUTH, LONG, 129),
+
+  CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+  CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+  /* 132 OBSOLETE. Gone in 7.16.0 */
+  /* 133 OBSOLETE. Gone in 7.16.0 */
+
+  /* zero terminated string for pass on to the FTP server when asked for
+     "account" info */
+  CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
+
+  /* feed cookies into cookie engine */
+  CINIT(COOKIELIST, OBJECTPOINT, 135),
+
+  /* ignore Content-Length */
+  CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+  /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+     response. Typically used for FTP-SSL purposes but is not restricted to
+     that. libcurl will then instead use the same IP address it used for the
+     control connection. */
+  CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+  /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+     above. */
+  CINIT(FTP_FILEMETHOD, LONG, 138),
+
+  /* Local port number to bind the socket to */
+  CINIT(LOCALPORT, LONG, 139),
+
+  /* Number of ports to try, including the first one set with LOCALPORT.
+     Thus, setting it to 1 will make no additional attempts but the first.
+  */
+  CINIT(LOCALPORTRANGE, LONG, 140),
+
+  /* no transfer, set up connection and let application use the socket by
+     extracting it with CURLINFO_LASTSOCKET */
+  CINIT(CONNECT_ONLY, LONG, 141),
+
+  /* Function that will be called to convert from the
+     network encoding (instead of using the iconv calls in libcurl) */
+  CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+  /* Function that will be called to convert to the
+     network encoding (instead of using the iconv calls in libcurl) */
+  CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+  /* Function that will be called to convert from UTF8
+     (instead of using the iconv calls in libcurl)
+     Note that this is used only for SSL certificate processing */
+  CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+  /* if the connection proceeds too quickly then need to slow it down */
+  /* limit-rate: maximum number of bytes per second to send or receive */
+  CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+  CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+  /* Pointer to command string to send if USER/PASS fails. */
+  CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
+
+  /* callback function for setting socket options */
+  CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+  CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+  /* set to 0 to disable session ID re-use for this transfer, default is
+     enabled (== 1) */
+  CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+  /* allowed SSH authentication methods */
+  CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+  /* Used by scp/sftp to do public/private key authentication */
+  CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
+  CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
+
+  /* Send CCC (Clear Command Channel) after authentication */
+  CINIT(FTP_SSL_CCC, LONG, 154),
+
+  /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+  CINIT(TIMEOUT_MS, LONG, 155),
+  CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+  /* set to zero to disable the libcurl's decoding and thus pass the raw body
+     data to the application even when it is encoded/compressed */
+  CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
+  CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+
+  /* Permission used when creating new files and directories on the remote
+     server for protocols that support it, SFTP/SCP/FILE */
+  CINIT(NEW_FILE_PERMS, LONG, 159),
+  CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+  /* Set the behaviour of POST when redirecting. Values must be set to one
+     of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+  CINIT(POSTREDIR, LONG, 161),
+
+  /* used by scp/sftp to verify the host's public key */
+  CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
+
+  /* Callback function for opening socket (instead of socket(2)). Optionally,
+     callback is able change the address or refuse to connect returning
+     CURL_SOCKET_BAD.  The callback should have type
+     curl_opensocket_callback */
+  CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+  CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+  /* POST volatile input fields. */
+  CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
+  /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+  CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+  /* Callback function for seeking in the input stream */
+  CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+  CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+  /* CRL file */
+  CINIT(CRLFILE, OBJECTPOINT, 169),
+
+  /* Issuer certificate */
+  CINIT(ISSUERCERT, OBJECTPOINT, 170),
+
+  /* (IPv6) Address scope */
+  CINIT(ADDRESS_SCOPE, LONG, 171),
+
+  /* Collect certificate chain info and allow it to get retrievable with
+     CURLINFO_CERTINFO after the transfer is complete. */
+  CINIT(CERTINFO, LONG, 172),
+
+  /* "name" and "pwd" to use when fetching. */
+  CINIT(USERNAME, OBJECTPOINT, 173),
+  CINIT(PASSWORD, OBJECTPOINT, 174),
+
+    /* "name" and "pwd" to use with Proxy when fetching. */
+  CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
+  CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
+
+  /* Comma separated list of hostnames defining no-proxy zones. These should
+     match both hostnames directly, and hostnames within a domain. For
+     example, local.com will match local.com and www.local.com, but NOT
+     notlocal.com or www.notlocal.com. For compatibility with other
+     implementations of this, .local.com will be considered to be the same as
+     local.com. A single * is the only valid wildcard, and effectively
+     disables the use of proxy. */
+  CINIT(NOPROXY, OBJECTPOINT, 177),
+
+  /* block size for TFTP transfers */
+  CINIT(TFTP_BLKSIZE, LONG, 178),
+
+  /* Socks Service */
+  CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179),
+
+  /* Socks Service */
+  CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+  /* set the bitmask for the protocols that are allowed to be used for the
+     transfer, which thus helps the app which takes URLs from users or other
+     external inputs and want to restrict what protocol(s) to deal
+     with. Defaults to CURLPROTO_ALL. */
+  CINIT(PROTOCOLS, LONG, 181),
+
+  /* set the bitmask for the protocols that libcurl is allowed to follow to,
+     as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+     to be set in both bitmasks to be allowed to get redirected to. Defaults
+     to all protocols except FILE and SCP. */
+  CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+  /* set the SSH knownhost file name to use */
+  CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183),
+
+  /* set the SSH host key callback, must point to a curl_sshkeycallback
+     function */
+  CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+  /* set the SSH host key callback custom pointer */
+  CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
+  /* set the SMTP mail originator */
+  CINIT(MAIL_FROM, OBJECTPOINT, 186),
+
+  /* set the SMTP mail receiver(s) */
+  CINIT(MAIL_RCPT, OBJECTPOINT, 187),
+
+  /* FTP: send PRET before PASV */
+  CINIT(FTP_USE_PRET, LONG, 188),
+
+  /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
+  CINIT(RTSP_REQUEST, LONG, 189),
+
+  /* The RTSP session identifier */
+  CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190),
+
+  /* The RTSP stream URI */
+  CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191),
+
+  /* The Transport: header to use in RTSP requests */
+  CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192),
+
+  /* Manually initialize the client RTSP CSeq for this handle */
+  CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+
+  /* Manually initialize the server RTSP CSeq for this handle */
+  CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+
+  /* The stream to pass to INTERLEAVEFUNCTION. */
+  CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+
+  /* Let the application define a custom write method for RTP data */
+  CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+
+  /* Turn on wildcard matching */
+  CINIT(WILDCARDMATCH, LONG, 197),
+
+  /* Directory matching callback called before downloading of an
+     individual file (chunk) started */
+  CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+
+  /* Directory matching callback called after the file (chunk)
+     was downloaded, or skipped */
+  CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+
+  /* Change match (fnmatch-like) callback for wildcard matching */
+  CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+
+  /* Let the application define custom chunk data pointer */
+  CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+
+  /* FNMATCH_FUNCTION user pointer */
+  CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+
+  /* send linked-list of name:port:address sets */
+  CINIT(RESOLVE, OBJECTPOINT, 203),
+
+  /* Set a username for authenticated TLS */
+  CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204),
+
+  /* Set a password for authenticated TLS */
+  CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205),
+
+  /* Set authentication type for authenticated TLS */
+  CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206),
+
+  /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
+     compressed transfer-encoded responses. Set to 0 to disable the use of TE:
+     in outgoing requests. The current default is 0, but it might change in a
+     future libcurl release.
+
+     libcurl will ask for the compressed methods it knows of, and if that
+     isn't any, it will not ask for transfer-encoding at all even if this
+     option is set to 1.
+
+  */
+  CINIT(TRANSFER_ENCODING, LONG, 207),
+
+  /* Callback function for closing socket (instead of close(2)). The callback
+     should have type curl_closesocket_callback */
+  CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
+  CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+
+  /* allow GSSAPI credential delegation */
+  CINIT(GSSAPI_DELEGATION, LONG, 210),
+
+  /* Set the name servers to use for DNS resolution */
+  CINIT(DNS_SERVERS, OBJECTPOINT, 211),
+
+  /* Time-out accept operations (currently for FTP only) after this amount
+     of miliseconds. */
+  CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+
+  /* Set TCP keepalive */
+  CINIT(TCP_KEEPALIVE, LONG, 213),
+
+  /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
+  CINIT(TCP_KEEPIDLE, LONG, 214),
+  CINIT(TCP_KEEPINTVL, LONG, 215),
+
+  /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
+  CINIT(SSL_OPTIONS, LONG, 216),
+
+  /* Set the SMTP auth originator */
+  CINIT(MAIL_AUTH, OBJECTPOINT, 217),
+
+  /* Enable/disable SASL initial response */
+  CINIT(SASL_IR, LONG, 218),
+
+  /* Function that will be called instead of the internal progress display
+   * function. This function should be defined as the curl_xferinfo_callback
+   * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
+  CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+
+  /* The XOAUTH2 bearer token */
+  CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
+
+  /* Set the interface string to use as outgoing network
+   * interface for DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
+
+  /* Set the local IPv4 address to use for outgoing DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
+
+  /* Set the local IPv4 address to use for outgoing DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
+
+  /* Set authentication options directly */
+  CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
+
+  /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
+  CINIT(SSL_ENABLE_NPN, LONG, 225),
+
+  /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
+  CINIT(SSL_ENABLE_ALPN, LONG, 226),
+
+  /* Time to wait for a response to a HTTP request containing an
+   * Expect: 100-continue header before sending the data anyway. */
+  CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+
+  /* This points to a linked list of headers used for proxy requests only,
+     struct curl_slist kind */
+  CINIT(PROXYHEADER, OBJECTPOINT, 228),
+
+  /* Pass in a bitmask of "header options" */
+  CINIT(HEADEROPT, LONG, 229),
+
+  /* The public key in DER form used to validate the peer public key
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(PINNEDPUBLICKEY, OBJECTPOINT, 230),
+
+  /* Path to Unix domain socket */
+  CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231),
+
+  /* Set if we should verify the certificate status. */
+  CINIT(SSL_VERIFYSTATUS, LONG, 232),
+
+  /* Set if we should enable TLS false start. */
+  CINIT(SSL_FALSESTART, LONG, 233),
+
+  /* Do not squash dot-dot sequences */
+  CINIT(PATH_AS_IS, LONG, 234),
+
+  CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all the obsolete stuff removed */
+
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2011 */
+
+/* This was added in version 7.19.1 */
+#define CURLOPT_POST301 CURLOPT_POSTREDIR
+
+/* These are scheduled to disappear by 2009 */
+
+/* The following were added in 7.17.0 */
+#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_FTPAPPEND CURLOPT_APPEND
+#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
+#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
+
+/* The following were added earlier */
+
+#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+  /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+     name resolves addresses using more than one IP protocol version, this
+     option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+                                     versions that your system allows */
+#define CURL_IPRESOLVE_V4       1 /* resolve to IPv4 addresses */
+#define CURL_IPRESOLVE_V6       2 /* resolve to IPv6 addresses */
+
+  /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+  /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+enum {
+  CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+                             like the library to choose the best possible for us */
+
+  CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */
+  CURL_HTTP_VERSION_1_1,  /* please use HTTP 1.1 in the request */
+  CURL_HTTP_VERSION_2_0,  /* please use HTTP 2.0 in the request */
+
+  CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+/*
+ * Public API enums for RTSP requests
+ */
+enum {
+    CURL_RTSPREQ_NONE, /* first in list */
+    CURL_RTSPREQ_OPTIONS,
+    CURL_RTSPREQ_DESCRIBE,
+    CURL_RTSPREQ_ANNOUNCE,
+    CURL_RTSPREQ_SETUP,
+    CURL_RTSPREQ_PLAY,
+    CURL_RTSPREQ_PAUSE,
+    CURL_RTSPREQ_TEARDOWN,
+    CURL_RTSPREQ_GET_PARAMETER,
+    CURL_RTSPREQ_SET_PARAMETER,
+    CURL_RTSPREQ_RECORD,
+    CURL_RTSPREQ_RECEIVE,
+    CURL_RTSPREQ_LAST /* last in list */
+};
+
+  /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+  CURL_NETRC_IGNORED,     /* The .netrc will never be read.
+                           * This is the default. */
+  CURL_NETRC_OPTIONAL,    /* A user:password in the URL will be preferred
+                           * to one in the .netrc. */
+  CURL_NETRC_REQUIRED,    /* A user:password in the URL will be ignored.
+                           * Unless one is set programmatically, the .netrc
+                           * will be queried. */
+  CURL_NETRC_LAST
+};
+
+enum {
+  CURL_SSLVERSION_DEFAULT,
+  CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+  CURL_SSLVERSION_SSLv2,
+  CURL_SSLVERSION_SSLv3,
+  CURL_SSLVERSION_TLSv1_0,
+  CURL_SSLVERSION_TLSv1_1,
+  CURL_SSLVERSION_TLSv1_2,
+
+  CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+enum CURL_TLSAUTH {
+  CURL_TLSAUTH_NONE,
+  CURL_TLSAUTH_SRP,
+  CURL_TLSAUTH_LAST /* never use, keep last */
+};
+
+/* symbols to use with CURLOPT_POSTREDIR.
+   CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+   can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+   | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+#define CURL_REDIR_GET_ALL  0
+#define CURL_REDIR_POST_301 1
+#define CURL_REDIR_POST_302 2
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+    (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+typedef enum {
+  CURL_TIMECOND_NONE,
+
+  CURL_TIMECOND_IFMODSINCE,
+  CURL_TIMECOND_IFUNMODSINCE,
+  CURL_TIMECOND_LASTMOD,
+
+  CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+   libcurl, see lib/README.curlx for details */
+CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
+CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+  CFINIT(NOTHING),        /********* the first one is unused ************/
+
+  /*  */
+  CFINIT(COPYNAME),
+  CFINIT(PTRNAME),
+  CFINIT(NAMELENGTH),
+  CFINIT(COPYCONTENTS),
+  CFINIT(PTRCONTENTS),
+  CFINIT(CONTENTSLENGTH),
+  CFINIT(FILECONTENT),
+  CFINIT(ARRAY),
+  CFINIT(OBSOLETE),
+  CFINIT(FILE),
+
+  CFINIT(BUFFER),
+  CFINIT(BUFFERPTR),
+  CFINIT(BUFFERLENGTH),
+
+  CFINIT(CONTENTTYPE),
+  CFINIT(CONTENTHEADER),
+  CFINIT(FILENAME),
+  CFINIT(END),
+  CFINIT(OBSOLETE2),
+
+  CFINIT(STREAM),
+
+  CURLFORM_LASTENTRY /* the last unused */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+  CURLformoption option;
+  const char     *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK             on success
+ * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
+ * CURL_FORMADD_NULL           if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY         if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY         if a curl_httppost struct cannot be allocated
+ * CURL_FORMADD_MEMORY         if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY  if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+  CURL_FORMADD_OK, /* first, no error */
+
+  CURL_FORMADD_MEMORY,
+  CURL_FORMADD_OPTION_TWICE,
+  CURL_FORMADD_NULL,
+  CURL_FORMADD_UNKNOWN_OPTION,
+  CURL_FORMADD_INCOMPLETE,
+  CURL_FORMADD_ILLEGAL_ARRAY,
+  CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+  CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanced function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+                                      struct curl_httppost **last_post,
+                                      ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ *   curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ *   success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
+                                        size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+                             curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+                                   const char *string,
+                                   int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+                              int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+                                     const char *string,
+                                     int length,
+                                     int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+                                int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl and before any call of other libcurl functions.
+ *
+ * This function is not thread-safe!
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl.  This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions.  Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc.  User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+                                          curl_malloc_callback m,
+                                          curl_free_callback f,
+                                          curl_realloc_callback r,
+                                          curl_strdup_callback s,
+                                          curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+  char *data;
+  struct curl_slist *next;
+};
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+                                                 const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+/* info about the certificate chain, only for OpenSSL builds. Asked
+   for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+struct curl_certinfo {
+  int num_of_certs;             /* number of certificates with information */
+  struct curl_slist **certinfo; /* for each index in this array, there's a
+                                   linked list with textual information in the
+                                   format "name: value" */
+};
+
+/* enum for the different supported SSL backends */
+typedef enum {
+  CURLSSLBACKEND_NONE = 0,
+  CURLSSLBACKEND_OPENSSL = 1,
+  CURLSSLBACKEND_GNUTLS = 2,
+  CURLSSLBACKEND_NSS = 3,
+  CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
+  CURLSSLBACKEND_GSKIT = 5,
+  CURLSSLBACKEND_POLARSSL = 6,
+  CURLSSLBACKEND_CYASSL = 7,
+  CURLSSLBACKEND_SCHANNEL = 8,
+  CURLSSLBACKEND_DARWINSSL = 9,
+  CURLSSLBACKEND_AXTLS = 10
+} curl_sslbackend;
+
+/* Information about the SSL library used and the respective internal SSL
+   handle, which can be used to obtain further information regarding the
+   connection. Asked for with CURLINFO_TLS_SESSION. */
+struct curl_tlssessioninfo {
+  curl_sslbackend backend;
+  void *internals;
+};
+
+#define CURLINFO_STRING   0x100000
+#define CURLINFO_LONG     0x200000
+#define CURLINFO_DOUBLE   0x300000
+#define CURLINFO_SLIST    0x400000
+#define CURLINFO_MASK     0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+  CURLINFO_NONE, /* first, never use this */
+  CURLINFO_EFFECTIVE_URL    = CURLINFO_STRING + 1,
+  CURLINFO_RESPONSE_CODE    = CURLINFO_LONG   + 2,
+  CURLINFO_TOTAL_TIME       = CURLINFO_DOUBLE + 3,
+  CURLINFO_NAMELOOKUP_TIME  = CURLINFO_DOUBLE + 4,
+  CURLINFO_CONNECT_TIME     = CURLINFO_DOUBLE + 5,
+  CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+  CURLINFO_SIZE_UPLOAD      = CURLINFO_DOUBLE + 7,
+  CURLINFO_SIZE_DOWNLOAD    = CURLINFO_DOUBLE + 8,
+  CURLINFO_SPEED_DOWNLOAD   = CURLINFO_DOUBLE + 9,
+  CURLINFO_SPEED_UPLOAD     = CURLINFO_DOUBLE + 10,
+  CURLINFO_HEADER_SIZE      = CURLINFO_LONG   + 11,
+  CURLINFO_REQUEST_SIZE     = CURLINFO_LONG   + 12,
+  CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG   + 13,
+  CURLINFO_FILETIME         = CURLINFO_LONG   + 14,
+  CURLINFO_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15,
+  CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16,
+  CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+  CURLINFO_CONTENT_TYPE     = CURLINFO_STRING + 18,
+  CURLINFO_REDIRECT_TIME    = CURLINFO_DOUBLE + 19,
+  CURLINFO_REDIRECT_COUNT   = CURLINFO_LONG   + 20,
+  CURLINFO_PRIVATE          = CURLINFO_STRING + 21,
+  CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG   + 22,
+  CURLINFO_HTTPAUTH_AVAIL   = CURLINFO_LONG   + 23,
+  CURLINFO_PROXYAUTH_AVAIL  = CURLINFO_LONG   + 24,
+  CURLINFO_OS_ERRNO         = CURLINFO_LONG   + 25,
+  CURLINFO_NUM_CONNECTS     = CURLINFO_LONG   + 26,
+  CURLINFO_SSL_ENGINES      = CURLINFO_SLIST  + 27,
+  CURLINFO_COOKIELIST       = CURLINFO_SLIST  + 28,
+  CURLINFO_LASTSOCKET       = CURLINFO_LONG   + 29,
+  CURLINFO_FTP_ENTRY_PATH   = CURLINFO_STRING + 30,
+  CURLINFO_REDIRECT_URL     = CURLINFO_STRING + 31,
+  CURLINFO_PRIMARY_IP       = CURLINFO_STRING + 32,
+  CURLINFO_APPCONNECT_TIME  = CURLINFO_DOUBLE + 33,
+  CURLINFO_CERTINFO         = CURLINFO_SLIST  + 34,
+  CURLINFO_CONDITION_UNMET  = CURLINFO_LONG   + 35,
+  CURLINFO_RTSP_SESSION_ID  = CURLINFO_STRING + 36,
+  CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG   + 37,
+  CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG   + 38,
+  CURLINFO_RTSP_CSEQ_RECV   = CURLINFO_LONG   + 39,
+  CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
+  CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
+  CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
+  CURLINFO_TLS_SESSION      = CURLINFO_SLIST  + 43,
+  /* Fill in new entries below here! */
+
+  CURLINFO_LASTONE          = 43
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+   CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+  CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+  CURLCLOSEPOLICY_OLDEST,
+  CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+  CURLCLOSEPOLICY_LEAST_TRAFFIC,
+  CURLCLOSEPOLICY_SLOWEST,
+  CURLCLOSEPOLICY_CALLBACK,
+
+  CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0)
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+  CURL_LOCK_DATA_NONE = 0,
+  /*  CURL_LOCK_DATA_SHARE is used internally to say that
+   *  the locking is just made to change the internal state of the share
+   *  itself.
+   */
+  CURL_LOCK_DATA_SHARE,
+  CURL_LOCK_DATA_COOKIE,
+  CURL_LOCK_DATA_DNS,
+  CURL_LOCK_DATA_SSL_SESSION,
+  CURL_LOCK_DATA_CONNECT,
+  CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+  CURL_LOCK_ACCESS_NONE = 0,   /* unspecified action */
+  CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+  CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+  CURL_LOCK_ACCESS_LAST        /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+                                   curl_lock_data data,
+                                   curl_lock_access locktype,
+                                   void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+                                     curl_lock_data data,
+                                     void *userptr);
+
+typedef void CURLSH;
+
+typedef enum {
+  CURLSHE_OK,  /* all is fine */
+  CURLSHE_BAD_OPTION, /* 1 */
+  CURLSHE_IN_USE,     /* 2 */
+  CURLSHE_INVALID,    /* 3 */
+  CURLSHE_NOMEM,      /* 4 out of memory */
+  CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
+  CURLSHE_LAST        /* never use */
+} CURLSHcode;
+
+typedef enum {
+  CURLSHOPT_NONE,  /* don't use */
+  CURLSHOPT_SHARE,   /* specify a data type to share */
+  CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+  CURLSHOPT_LOCKFUNC,   /* pass in a 'curl_lock_function' pointer */
+  CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+  CURLSHOPT_USERDATA,   /* pass in a user data pointer used in the lock/unlock
+                           callback functions */
+  CURLSHOPT_LAST  /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+  CURLVERSION_FIRST,
+  CURLVERSION_SECOND,
+  CURLVERSION_THIRD,
+  CURLVERSION_FOURTH,
+  CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+   basically all programs ever that want to get version information. It is
+   meant to be a built-in version number for what kind of struct the caller
+   expects. If the struct ever changes, we redefine the NOW to another enum
+   from above. */
+#define CURLVERSION_NOW CURLVERSION_FOURTH
+
+typedef struct {
+  CURLversion age;          /* age of the returned struct */
+  const char *version;      /* LIBCURL_VERSION */
+  unsigned int version_num; /* LIBCURL_VERSION_NUM */
+  const char *host;         /* OS/host/cpu/machine when configured */
+  int features;             /* bitmask, see defines below */
+  const char *ssl_version;  /* human readable string */
+  long ssl_version_num;     /* not used anymore, always 0 */
+  const char *libz_version; /* human readable string */
+  /* protocols is terminated by an entry with a NULL protoname */
+  const char * const *protocols;
+
+  /* The fields below this were added in CURLVERSION_SECOND */
+  const char *ares;
+  int ares_num;
+
+  /* This field was added in CURLVERSION_THIRD */
+  const char *libidn;
+
+  /* These field were added in CURLVERSION_FOURTH */
+
+  /* Same as '_libiconv_version' if built with HAVE_ICONV */
+  int iconv_ver_num;
+
+  const char *libssh_version; /* human readable string */
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6         (1<<0)  /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4    (1<<1)  /* Kerberos V4 auth is supported
+                                             (deprecated) */
+#define CURL_VERSION_SSL          (1<<2)  /* SSL options are present */
+#define CURL_VERSION_LIBZ         (1<<3)  /* libz features are present */
+#define CURL_VERSION_NTLM         (1<<4)  /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5)  /* Negotiate auth is supported
+                                             (deprecated) */
+#define CURL_VERSION_DEBUG        (1<<6)  /* Built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS    (1<<7)  /* Asynchronous DNS resolves */
+#define CURL_VERSION_SPNEGO       (1<<8)  /* SPNEGO auth is supported */
+#define CURL_VERSION_LARGEFILE    (1<<9)  /* Supports files larger than 2GB */
+#define CURL_VERSION_IDN          (1<<10) /* Internationized Domain Names are
+                                             supported */
+#define CURL_VERSION_SSPI         (1<<11) /* Built against Windows SSPI */
+#define CURL_VERSION_CONV         (1<<12) /* Character conversions supported */
+#define CURL_VERSION_CURLDEBUG    (1<<13) /* Debug memory tracking supported */
+#define CURL_VERSION_TLSAUTH_SRP  (1<<14) /* TLS-SRP auth is supported */
+#define CURL_VERSION_NTLM_WB      (1<<15) /* NTLM delegation to winbind helper
+                                             is suported */
+#define CURL_VERSION_HTTP2        (1<<16) /* HTTP2 support built-in */
+#define CURL_VERSION_GSSAPI       (1<<17) /* Built against a GSS-API library */
+#define CURL_VERSION_KERBEROS5    (1<<18) /* Kerberos V5 auth is supported */
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
+
+ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string.  This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string.  This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+/*
+ * NAME curl_easy_pause()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_pause function pauses or unpauses transfers. Select the new
+ * state by setting the bitmask, use the convenience defines below.
+ *
+ */
+CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
+
+#define CURLPAUSE_RECV      (1<<0)
+#define CURLPAUSE_RECV_CONT (0)
+
+#define CURLPAUSE_SEND      (1<<2)
+#define CURLPAUSE_SEND_CONT (0)
+
+#define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND)
+#define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
+
+#ifdef  __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+  stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+
+/* the typechecker doesn't work in C++ (yet) */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+    ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+    !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+#include "typecheck-gcc.h"
+#else
+#if defined(__STDC__) && (__STDC__ >= 1)
+/* This preprocessor magic that replaces a call with the exact same call is
+   only done to make sure application authors pass exactly three arguments
+   to these functions. */
+#define curl_easy_setopt(handle, opt, param) curl_easy_setopt(handle, opt, param)
+#define curl_easy_getinfo(handle, info, arg) curl_easy_getinfo(handle, info, arg)
+#define curl_share_setopt(share, opt, param) curl_share_setopt(share, opt, param)
+#define curl_multi_setopt(handle, opt, param) curl_multi_setopt(handle, opt, param)
+#endif /* __STDC__ >= 1 */
+#endif /* gcc >= 4.3 && !__cplusplus */
+
+#endif /* __CURL_CURL_H */
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/curlbuild.h b/src/connectivity/gps/mtk_mnld/curl/inc/curlbuild.h
new file mode 100644
index 0000000..f09419a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/curlbuild.h
@@ -0,0 +1,585 @@
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/*               NOTES FOR CONFIGURE CAPABLE SYSTEMS                */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * See file include/curl/curlbuild.h.in, run configure, and forget
+ * that this file exists it is only used for non-configure systems.
+ * But you can keep reading if you want ;-)
+ *
+ */
+
+/* ================================================================ */
+/*                 NOTES FOR NON-CONFIGURE SYSTEMS                  */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * Try to keep one section per platform, compiler and architecture,
+ * otherwise, if an existing section is reused for a different one and
+ * later on the original is adjusted, probably the piggybacking one can
+ * be adversely changed.
+ *
+ * In order to differentiate between platforms/compilers/architectures
+ * use only compiler built in predefined preprocessor symbols.
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * For any given platform/compiler curl_off_t must be typedef'ed to a
+ * 64-bit wide signed integral data type. The width of this data type
+ * must remain constant and independent of any possible large file
+ * support settings.
+ *
+ * As an exception to the above, curl_off_t shall be typedef'ed to a
+ * 32-bit wide signed integral data type if there is no 64-bit type.
+ *
+ * As a general rule, curl_off_t shall not be mapped to off_t. This
+ * rule shall only be violated if off_t is the only 64-bit data type
+ * available and the size of off_t is independent of large file support
+ * settings. Keep your build on the safe side avoiding an off_t gating.
+ * If you have a 64-bit off_t then take for sure that another 64-bit
+ * data type exists, dig deeper and you will find it.
+ *
+ * NOTE 3:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.dist or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ * file include/curl/curlbuild.h.dist is renamed to include/curl/curlbuild.h
+ * when the libcurl source code distribution archive file is created.
+ *
+ * File include/curl/curlbuild.h.dist is not included in the distribution
+ * archive. File include/curl/curlbuild.h is not present in the git tree.
+ *
+ * The distributed include/curl/curlbuild.h file is only intended to be used
+ * on systems which can not run the also distributed configure script.
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ * If you check out from git on a non-configure platform, you must run the
+ * appropriate buildconf* script to set up curlbuild.h and other local files.
+ *
+ */
+
+/* ================================================================ */
+/*  DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE  */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+#  error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+#  error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+#  error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+#  error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+#  error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+#  error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+#  error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+#  error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+#  error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+#  error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+   Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/*    EXTERNAL INTERFACE SETTINGS FOR NON-CONFIGURE SYSTEMS ONLY    */
+/* ================================================================ */
+
+#if defined(__DJGPP__) || defined(__GO32__)
+#  if defined(__DJGPP__) && (__DJGPP__ > 1)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  else
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     4
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SALFORDC__)
+#  define CURL_SIZEOF_LONG           4
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_FORMAT_OFF_T          "%ld"
+#  define CURL_SIZEOF_CURL_OFF_T     4
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__BORLANDC__)
+#  if (__BORLANDC__ < 0x520)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     4
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  else
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_FORMAT_OFF_T          "%I64d"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__TURBOC__)
+#  define CURL_SIZEOF_LONG           4
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_FORMAT_OFF_T          "%ld"
+#  define CURL_SIZEOF_CURL_OFF_T     4
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__WATCOMC__)
+#  if defined(__386__)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_FORMAT_OFF_T          "%I64d"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     4
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__POCC__)
+#  if (__POCC__ < 280)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     4
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  elif defined(_MSC_VER)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_FORMAT_OFF_T          "%I64d"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__LCC__)
+#  define CURL_SIZEOF_LONG           4
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_FORMAT_OFF_T          "%ld"
+#  define CURL_SIZEOF_CURL_OFF_T     4
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SYMBIAN32__)
+#  if defined(__EABI__)  /* Treat all ARM compilers equally */
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__CW32__)
+#    pragma longlong on
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__VC32__)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MWERKS__)
+#  define CURL_SIZEOF_LONG           4
+#  define CURL_TYPEOF_CURL_OFF_T     long long
+#  define CURL_FORMAT_CURL_OFF_T     "lld"
+#  define CURL_FORMAT_CURL_OFF_TU    "llu"
+#  define CURL_FORMAT_OFF_T          "%lld"
+#  define CURL_SIZEOF_CURL_OFF_T     8
+#  define CURL_SUFFIX_CURL_OFF_T     LL
+#  define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(_WIN32_WCE)
+#  define CURL_SIZEOF_LONG           4
+#  define CURL_TYPEOF_CURL_OFF_T     __int64
+#  define CURL_FORMAT_CURL_OFF_T     "I64d"
+#  define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURL_FORMAT_OFF_T          "%I64d"
+#  define CURL_SIZEOF_CURL_OFF_T     8
+#  define CURL_SUFFIX_CURL_OFF_T     i64
+#  define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MINGW32__)
+#  define CURL_SIZEOF_LONG           4
+#  define CURL_TYPEOF_CURL_OFF_T     long long
+#  define CURL_FORMAT_CURL_OFF_T     "I64d"
+#  define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURL_FORMAT_OFF_T          "%I64d"
+#  define CURL_SIZEOF_CURL_OFF_T     8
+#  define CURL_SUFFIX_CURL_OFF_T     LL
+#  define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__VMS)
+#  if defined(__VAX)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     4
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  else
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__OS400__)
+#  if defined(__ILEC400__)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURL_SIZEOF_CURL_SOCKLEN_T 4
+#    define CURL_PULL_SYS_TYPES_H      1
+#    define CURL_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(__MVS__)
+#  if defined(__IBMC__) || defined(__IBMCPP__)
+#    if defined(_ILP32)
+#      define CURL_SIZEOF_LONG           4
+#    elif defined(_LP64)
+#      define CURL_SIZEOF_LONG           8
+#    endif
+#    if defined(_LONG_LONG)
+#      define CURL_TYPEOF_CURL_OFF_T     long long
+#      define CURL_FORMAT_CURL_OFF_T     "lld"
+#      define CURL_FORMAT_CURL_OFF_TU    "llu"
+#      define CURL_FORMAT_OFF_T          "%lld"
+#      define CURL_SIZEOF_CURL_OFF_T     8
+#      define CURL_SUFFIX_CURL_OFF_T     LL
+#      define CURL_SUFFIX_CURL_OFF_TU    ULL
+#    elif defined(_LP64)
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_FORMAT_OFF_T          "%ld"
+#      define CURL_SIZEOF_CURL_OFF_T     8
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    else
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_FORMAT_OFF_T          "%ld"
+#      define CURL_SIZEOF_CURL_OFF_T     4
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    endif
+#    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURL_SIZEOF_CURL_SOCKLEN_T 4
+#    define CURL_PULL_SYS_TYPES_H      1
+#    define CURL_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(__370__)
+#  if defined(__IBMC__) || defined(__IBMCPP__)
+#    if defined(_ILP32)
+#      define CURL_SIZEOF_LONG           4
+#    elif defined(_LP64)
+#      define CURL_SIZEOF_LONG           8
+#    endif
+#    if defined(_LONG_LONG)
+#      define CURL_TYPEOF_CURL_OFF_T     long long
+#      define CURL_FORMAT_CURL_OFF_T     "lld"
+#      define CURL_FORMAT_CURL_OFF_TU    "llu"
+#      define CURL_FORMAT_OFF_T          "%lld"
+#      define CURL_SIZEOF_CURL_OFF_T     8
+#      define CURL_SUFFIX_CURL_OFF_T     LL
+#      define CURL_SUFFIX_CURL_OFF_TU    ULL
+#    elif defined(_LP64)
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_FORMAT_OFF_T          "%ld"
+#      define CURL_SIZEOF_CURL_OFF_T     8
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    else
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_FORMAT_OFF_T          "%ld"
+#      define CURL_SIZEOF_CURL_OFF_T     4
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    endif
+#    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURL_SIZEOF_CURL_SOCKLEN_T 4
+#    define CURL_PULL_SYS_TYPES_H      1
+#    define CURL_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(TPF)
+#  define CURL_SIZEOF_LONG           8
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_FORMAT_OFF_T          "%ld"
+#  define CURL_SIZEOF_CURL_OFF_T     8
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+/* ===================================== */
+/*    KEEP MSVC THE PENULTIMATE ENTRY    */
+/* ===================================== */
+
+#elif defined(_MSC_VER)
+#  if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_FORMAT_OFF_T          "%I64d"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     4
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+/* ===================================== */
+/*    KEEP GENERIC GCC THE LAST ENTRY    */
+/* ===================================== */
+
+#elif defined(__GNUC__)
+#  if defined(__ILP32__) || \
+      defined(__i386__) || defined(__ppc__) || defined(__arm__) || defined(__sparc__)
+#    define CURL_SIZEOF_LONG           4
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_FORMAT_OFF_T          "%lld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__LP64__) || \
+        defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__)
+#    define CURL_SIZEOF_LONG           8
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_FORMAT_OFF_T          "%ld"
+#    define CURL_SIZEOF_CURL_OFF_T     8
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_SYS_SOCKET_H     1
+
+#else
+#  error "Unknown non-configure build target!"
+   Error Compilation_aborted_Unknown_non_configure_build_target
+#endif
+
+/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file  */
+/* sys/types.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file  */
+/* sys/socket.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+/* Data type definition of curl_socklen_t. */
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+  typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+#endif
+
+/* Data type definition of curl_off_t. */
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+  typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+#endif
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/curlrules.h b/src/connectivity/gps/mtk_mnld/curl/inc/curlrules.h
new file mode 100644
index 0000000..301ce6e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/curlrules.h
@@ -0,0 +1,262 @@
+#ifndef __CURL_CURLRULES_H
+#define __CURL_CURLRULES_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/*                    COMPILE TIME SANITY CHECKS                    */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * All checks done in this file are intentionally placed in a public
+ * header file which is pulled by curl/curl.h when an application is
+ * being built using an already built libcurl library. Additionally
+ * this file is also included and used when building the library.
+ *
+ * If compilation fails on this file it is certainly sure that the
+ * problem is elsewhere. It could be a problem in the curlbuild.h
+ * header file, or simply that you are using different compilation
+ * settings than those used to build the library.
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * Do not deactivate any check, these are done to make sure that the
+ * library is properly built and used.
+ *
+ * You can find further help on the libcurl development mailing list:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * NOTE 2
+ * ------
+ *
+ * Some of the following compile time checks are based on the fact
+ * that the dimension of a constant array can not be a negative one.
+ * In this way if the compile time verification fails, the compilation
+ * will fail issuing an error. The error description wording is compiler
+ * dependent but it will be quite similar to one of the following:
+ *
+ *   "negative subscript or subscript is too large"
+ *   "array must have at least one element"
+ *   "-1 is an illegal array size"
+ *   "size of array is negative"
+ *
+ * If you are building an application which tries to use an already
+ * built libcurl library and you are getting this kind of errors on
+ * this file, it is a clear indication that there is a mismatch between
+ * how the library was built and how you are trying to use it for your
+ * application. Your already compiled or binary library provider is the
+ * only one who can give you the details you need to properly use it.
+ */
+
+/*
+ * Verify that some macros are actually defined.
+ */
+
+#ifndef CURL_SIZEOF_LONG
+#  error "CURL_SIZEOF_LONG definition is missing!"
+   Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
+#  error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
+   Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
+#  error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
+   Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_OFF_T
+#  error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
+   Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_T
+#  error "CURL_FORMAT_CURL_OFF_T definition is missing!"
+   Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_TU
+#  error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
+   Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
+#endif
+
+#ifndef CURL_FORMAT_OFF_T
+#  error "CURL_FORMAT_OFF_T definition is missing!"
+   Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_OFF_T
+#  error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
+   Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_T
+#  error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
+   Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_TU
+#  error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
+   Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
+#endif
+
+/*
+ * Macros private to this header file.
+ */
+
+#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
+
+#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
+
+/*
+ * Verify that the size previously defined and expected for long
+ * is the same as the one reported by sizeof() at compile time.
+ */
+
+typedef char
+  __curl_rule_01__
+    [CurlchkszEQ(long, CURL_SIZEOF_LONG)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_off_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+  __curl_rule_02__
+    [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
+
+/*
+ * Verify at compile time that the size of curl_off_t as reported
+ * by sizeof() is greater or equal than the one reported for long
+ * for the current compilation.
+ */
+
+typedef char
+  __curl_rule_03__
+    [CurlchkszGE(curl_off_t, long)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_socklen_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+  __curl_rule_04__
+    [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
+
+/*
+ * Verify at compile time that the size of curl_socklen_t as reported
+ * by sizeof() is greater or equal than the one reported for int for
+ * the current compilation.
+ */
+
+typedef char
+  __curl_rule_05__
+    [CurlchkszGE(curl_socklen_t, int)];
+
+/* ================================================================ */
+/*          EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS           */
+/* ================================================================ */
+
+/*
+ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+ * these to be visible and exported by the external libcurl interface API,
+ * while also making them visible to the library internals, simply including
+ * curl_setup.h, without actually needing to include curl.h internally.
+ * If some day this section would grow big enough, all this should be moved
+ * to its own header file.
+ */
+
+/*
+ * Figure out if we can use the ## preprocessor operator, which is supported
+ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+ * or  __cplusplus so we need to carefully check for them too.
+ */
+
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+  defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+  defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+  defined(__ILEC400__)
+  /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+  /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+/*
+ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+ */
+
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
+#  define __CURL_OFF_T_C_HLPR2(x) x
+#  define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
+#  define CURL_OFF_T_C(Val)  __CURL_OFF_T_C_HLPR1(Val) ## \
+                             __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
+#  define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+                             __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
+#else
+#  ifdef CURL_ISOCPP
+#    define __CURL_OFF_T_C_HLPR2(Val, Suffix) Val ## Suffix
+#  else
+#    define __CURL_OFF_T_C_HLPR2(Val, Suffix) Val/**/Suffix
+#  endif
+#  define __CURL_OFF_T_C_HLPR1(Val, Suffix) __CURL_OFF_T_C_HLPR2(Val, Suffix)
+#  define CURL_OFF_T_C(Val)  __CURL_OFF_T_C_HLPR1(Val, CURL_SUFFIX_CURL_OFF_T)
+#  define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val, CURL_SUFFIX_CURL_OFF_TU)
+#endif
+
+/*
+ * Get rid of macros private to this header file.
+ */
+
+#undef CurlchkszEQ
+#undef CurlchkszGE
+
+/*
+ * Get rid of macros not intended to exist beyond this point.
+ */
+
+#undef CURL_PULL_WS2TCPIP_H
+#undef CURL_PULL_SYS_TYPES_H
+#undef CURL_PULL_SYS_SOCKET_H
+#undef CURL_PULL_SYS_POLL_H
+#undef CURL_PULL_STDINT_H
+#undef CURL_PULL_INTTYPES_H
+
+#undef CURL_TYPEOF_CURL_SOCKLEN_T
+#undef CURL_TYPEOF_CURL_OFF_T
+
+#ifdef CURL_NO_OLDIES
+#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
+#endif
+
+#endif /* __CURL_CURLRULES_H */
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/curlver.h b/src/connectivity/gps/mtk_mnld/curl/inc/curlver.h
new file mode 100644
index 0000000..7976c1f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/curlver.h
@@ -0,0 +1,69 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This header file contains nothing but libcurl version info, generated by
+   a script at release-time. This was made its own header file in 7.11.2 */
+
+/* This is the global package copyright */
+#define LIBCURL_COPYRIGHT "1996 - 2015 Daniel Stenberg, <daniel@haxx.se>."
+
+/* This is the version number of the libcurl package from which this header
+   file origins: */
+#define LIBCURL_VERSION "7.42.1"
+
+/* The numeric version number is also available "in parts" by using these
+   defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 42
+#define LIBCURL_VERSION_PATCH 1
+
+/* This is the numeric version of the libcurl version number, meant for easier
+   parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+   always follow this syntax:
+
+         0xXXYYZZ
+
+   Where XX, YY and ZZ are the main version, release and patch numbers in
+   hexadecimal (using 8 bits each). All three numbers are always represented
+   using two digits.  1.2 would appear as "0x010200" while version 9.11.7
+   appears as "0x090b07".
+
+   This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+   and it is always a greater number in a more recent release. It makes
+   comparisons with greater than and less than work.
+*/
+#define LIBCURL_VERSION_NUM 0x072a01
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+ * The format of the date should follow this template:
+ *
+ * "Mon Feb 12 11:35:33 UTC 2007"
+ */
+#define LIBCURL_TIMESTAMP "Wed Apr 29 06:07:13 UTC 2015"
+
+#endif /* __CURL_CURLVER_H */
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/easy.h b/src/connectivity/gps/mtk_mnld/curl/inc/easy.h
new file mode 100644
index 0000000..c1e3e76
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/easy.h
@@ -0,0 +1,102 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function.  The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere).  The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK.  This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistent connections cannot
+ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+
+/*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+ *
+ * It does keep: live connections, the Session ID cache, the DNS cache and the
+ * cookies.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+/*
+ * NAME curl_easy_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
+                                    size_t *n);
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+                                    size_t buflen, size_t *n);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/multi.h b/src/connectivity/gps/mtk_mnld/curl/inc/multi.h
new file mode 100644
index 0000000..42306a9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/multi.h
@@ -0,0 +1,399 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+  This is an "external" header file. Don't give away any internals here!
+
+  GOALS
+
+  o Enable a "pull" interface. The application that uses libcurl decides where
+    and when to ask libcurl to get/send data.
+
+  o Enable multiple simultaneous transfers in the same thread without making it
+    complicated for the application.
+
+  o Enable the application to select() on its own file descriptors and curl's
+    file descriptors simultaneous easily.
+
+*/
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef void CURLM;
+
+typedef enum {
+  CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+                                    curl_multi_socket*() soon */
+  CURLM_OK,
+  CURLM_BAD_HANDLE,      /* the passed-in handle is not a valid CURLM handle */
+  CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+  CURLM_OUT_OF_MEMORY,   /* if you ever get this, you're in deep sh*t */
+  CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */
+  CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */
+  CURLM_UNKNOWN_OPTION,  /* curl_multi_setopt() with unsupported option */
+  CURLM_ADDED_ALREADY,   /* an easy handle already added to a multi handle was
+                            attempted to get added - again */
+  CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+   for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+   curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+typedef enum {
+  CURLMSG_NONE, /* first, not used */
+  CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+                   the CURLcode of the transfer */
+  CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+  CURLMSG msg;       /* what this message means */
+  CURL *easy_handle; /* the handle it concerns */
+  union {
+    void *whatever;    /* message-specific data */
+    CURLcode result;   /* return code for transfer */
+  } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/* Based on poll(2) structure and values.
+ * We don't use pollfd and POLL* constants explicitly
+ * to cover platforms without poll(). */
+#define CURL_WAIT_POLLIN    0x0001
+#define CURL_WAIT_POLLPRI   0x0002
+#define CURL_WAIT_POLLOUT   0x0004
+
+struct curl_waitfd {
+  curl_socket_t fd;
+  short events;
+  short revents; /* not supported yet */
+};
+
+/*
+ * Name:    curl_multi_init()
+ *
+ * Desc:    inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name:    curl_multi_add_handle()
+ *
+ * Desc:    add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+                                            CURL *curl_handle);
+
+ /*
+  * Name:    curl_multi_remove_handle()
+  *
+  * Desc:    removes a curl handle from the multi stack again
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+                                               CURL *curl_handle);
+
+ /*
+  * Name:    curl_multi_fdset()
+  *
+  * Desc:    Ask curl for its fd_set sets. The app can use these to select() or
+  *          poll() on. We want curl_multi_perform() called as soon as one of
+  *          them are ready.
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+                                       fd_set *read_fd_set,
+                                       fd_set *write_fd_set,
+                                       fd_set *exc_fd_set,
+                                       int *max_fd);
+
+/*
+ * Name:     curl_multi_wait()
+ *
+ * Desc:     Poll on all fds within a CURLM set as well as any
+ *           additional fds passed to the function.
+ *
+ * Returns:  CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
+                                      struct curl_waitfd extra_fds[],
+                                      unsigned int extra_nfds,
+                                      int timeout_ms,
+                                      int *ret);
+
+ /*
+  * Name:    curl_multi_perform()
+  *
+  * Desc:    When the app thinks there's data available for curl it calls this
+  *          function to read/write whatever there is right now. This returns
+  *          as soon as the reads and writes are done. This function does not
+  *          require that there actually is data available for reading or that
+  *          data can be written, it can be called just in case. It returns
+  *          the number of handles that still transfer data in the second
+  *          argument's integer-pointer.
+  *
+  * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+  *          returns errors etc regarding the whole multi stack. There might
+  *          still have occurred problems on invidual transfers even when this
+  *          returns OK.
+  */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+                                         int *running_handles);
+
+ /*
+  * Name:    curl_multi_cleanup()
+  *
+  * Desc:    Cleans up and removes a whole multi stack. It does not free or
+  *          touch any individual easy handles in any way. We need to define
+  *          in what state those handles will be if this function is called
+  *          in the middle of a transfer.
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name:    curl_multi_info_read()
+ *
+ * Desc:    Ask the multi handle if there's any messages/informationals from
+ *          the individual transfers. Messages include informationals such as
+ *          error code from the transfer or just the fact that a transfer is
+ *          completed. More details on these should be written down as well.
+ *
+ *          Repeated calls to this function will return a new struct each
+ *          time, until a special "end of msgs" struct is returned as a signal
+ *          that there is no more to get at this point.
+ *
+ *          The data the returned pointer points to will not survive calling
+ *          curl_multi_cleanup().
+ *
+ *          The 'CURLMsg' struct is meant to be very simple and only contain
+ *          very basic informations. If more involved information is wanted,
+ *          we will provide the particular "transfer handle" in that struct
+ *          and that should/could/would be used in subsequent
+ *          curl_easy_getinfo() calls (or similar). The point being that we
+ *          must never expose complex structs to applications, as then we'll
+ *          undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ *          of structs. It also writes the number of messages left in the
+ *          queue (after this read) in the integer the second argument points
+ *          to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+                                          int *msgs_in_queue);
+
+/*
+ * Name:    curl_multi_strerror()
+ *
+ * Desc:    The curl_multi_strerror function may be used to turn a CURLMcode
+ *          value into the equivalent human readable error string.  This is
+ *          useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name:    curl_multi_socket() and
+ *          curl_multi_socket_all()
+ *
+ * Desc:    An alternative version of curl_multi_perform() that allows the
+ *          application to pass in one of the file descriptors that have been
+ *          detected to have "action" on them and let libcurl perform.
+ *          See man page for details.
+ */
+#define CURL_POLL_NONE   0
+#define CURL_POLL_IN     1
+#define CURL_POLL_OUT    2
+#define CURL_POLL_INOUT  3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+#define CURL_CSELECT_IN   0x01
+#define CURL_CSELECT_OUT  0x02
+#define CURL_CSELECT_ERR  0x04
+
+typedef int (*curl_socket_callback)(CURL *easy,      /* easy handle */
+                                    curl_socket_t s, /* socket */
+                                    int what,        /* see above */
+                                    void *userp,     /* private callback
+                                                        pointer */
+                                    void *socketp);  /* private socket
+                                                        pointer */
+/*
+ * Name:    curl_multi_timer_callback
+ *
+ * Desc:    Called by libcurl whenever the library detects a change in the
+ *          maximum number of milliseconds the app is allowed to wait before
+ *          curl_multi_socket() or curl_multi_perform() must be called
+ *          (to allow libcurl's timed events to take place).
+ *
+ * Returns: The callback should return zero.
+ */
+typedef int (*curl_multi_timer_callback)(CURLM *multi,    /* multi handle */
+                                         long timeout_ms, /* see above */
+                                         void *userp);    /* private callback
+                                                             pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+                                        int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+                                               curl_socket_t s,
+                                               int ev_bitmask,
+                                               int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+                                            int *running_handles);
+
+#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
+/* This macro below was added in 7.16.3 to push users who recompile to use
+   the new curl_multi_socket_action() instead of the old curl_multi_socket()
+*/
+#define curl_multi_socket(x, y, z) curl_multi_socket_action(x, y, 0, z)
+#endif
+
+/*
+ * Name:    curl_multi_timeout()
+ *
+ * Desc:    Returns the maximum number of milliseconds the app is allowed to
+ *          wait before curl_multi_socket() or curl_multi_perform() must be
+ *          called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+                                         long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name, type, num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG          CURLOPTTYPE_LONG
+#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T         CURLOPTTYPE_OFF_T
+#define CINIT(name, type, number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+  /* This is the socket callback function pointer */
+  CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+  /* This is the argument passed to the socket callback */
+  CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+    /* set to 1 to enable pipelining for this multi handle */
+  CINIT(PIPELINING, LONG, 3),
+
+   /* This is the timer callback function pointer */
+  CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+  /* This is the argument passed to the timer callback */
+  CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+  /* maximum number of entries in the connection cache */
+  CINIT(MAXCONNECTS, LONG, 6),
+
+  /* maximum number of (pipelining) connections to one host */
+  CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+
+  /* maximum number of requests in a pipeline */
+  CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+
+  /* a connection with a content-length longer than this
+     will not be considered for pipelining */
+  CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+
+  /* a connection with a chunk length longer than this
+     will not be considered for pipelining */
+  CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+
+  /* a list of site names(+port) that are blacklisted from
+     pipelining */
+  CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+
+  /* a list of server types that are blacklisted from
+     pipelining */
+  CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+
+  /* maximum number of open connections in total */
+  CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+
+  CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name:    curl_multi_setopt()
+ *
+ * Desc:    Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+                                        CURLMoption option, ...);
+
+
+/*
+ * Name:    curl_multi_assign()
+ *
+ * Desc:    This function sets an association in the multi handle between the
+ *          given socket and a private pointer of the application. This is
+ *          (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+                                        curl_socket_t sockfd, void *sockp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/curl/inc/typecheck-gcc.h b/src/connectivity/gps/mtk_mnld/curl/inc/typecheck-gcc.h
new file mode 100644
index 0000000..0e3d6c9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/inc/typecheck-gcc.h
@@ -0,0 +1,610 @@
+#ifndef __CURL_TYPECHECK_GCC_H
+#define __CURL_TYPECHECK_GCC_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* wraps curl_easy_setopt() with typechecking */
+
+/* To add a new kind of warning, add an
+ *   if (_curl_is_sometype_option(_curl_opt))
+ *     if (!_curl_is_sometype(value))
+ *       _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
+ * NOTE: We use two nested 'if' statements here instead of the && operator, in
+ *       order to work around gcc bug #32061.  It affects only gcc 4.3.x/4.4.x
+ *       when compiling with -Wlogical-op.
+ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+#define curl_easy_setopt(handle, option, value)                               \
+__extension__({                                                              \
+  __typeof__(option) _curl_opt = option;                                     \
+  if (__builtin_constant_p(_curl_opt)) {                                       \
+    if (_curl_is_long_option(_curl_opt))                                       \
+      if (!_curl_is_long(value))                                               \
+        _curl_easy_setopt_err_long();                                         \
+    if (_curl_is_off_t_option(_curl_opt))                                      \
+      if (!_curl_is_off_t(value))                                              \
+        _curl_easy_setopt_err_curl_off_t();                                   \
+    if (_curl_is_string_option(_curl_opt))                                     \
+      if (!_curl_is_string(value))                                             \
+        _curl_easy_setopt_err_string();                                       \
+    if (_curl_is_write_cb_option(_curl_opt))                                   \
+      if (!_curl_is_write_cb(value))                                           \
+        _curl_easy_setopt_err_write_callback();                               \
+    if ((_curl_opt) == CURLOPT_READFUNCTION)                                   \
+      if (!_curl_is_read_cb(value))                                            \
+        _curl_easy_setopt_err_read_cb();                                      \
+    if ((_curl_opt) == CURLOPT_IOCTLFUNCTION)                                  \
+      if (!_curl_is_ioctl_cb(value))                                           \
+        _curl_easy_setopt_err_ioctl_cb();                                     \
+    if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION)                                \
+      if (!_curl_is_sockopt_cb(value))                                         \
+        _curl_easy_setopt_err_sockopt_cb();                                   \
+    if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION)                             \
+      if (!_curl_is_opensocket_cb(value))                                      \
+        _curl_easy_setopt_err_opensocket_cb();                                \
+    if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION)                               \
+      if (!_curl_is_progress_cb(value))                                        \
+        _curl_easy_setopt_err_progress_cb();                                  \
+    if ((_curl_opt) == CURLOPT_DEBUGFUNCTION)                                  \
+      if (!_curl_is_debug_cb(value))                                           \
+        _curl_easy_setopt_err_debug_cb();                                     \
+    if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION)                               \
+      if (!_curl_is_ssl_ctx_cb(value))                                         \
+        _curl_easy_setopt_err_ssl_ctx_cb();                                   \
+    if (_curl_is_conv_cb_option(_curl_opt))                                    \
+      if (!_curl_is_conv_cb(value))                                            \
+        _curl_easy_setopt_err_conv_cb();                                      \
+    if ((_curl_opt) == CURLOPT_SEEKFUNCTION)                                   \
+      if (!_curl_is_seek_cb(value))                                            \
+        _curl_easy_setopt_err_seek_cb();                                      \
+    if (_curl_is_cb_data_option(_curl_opt))                                    \
+      if (!_curl_is_cb_data(value))                                            \
+        _curl_easy_setopt_err_cb_data();                                      \
+    if ((_curl_opt) == CURLOPT_ERRORBUFFER)                                    \
+      if (!_curl_is_error_buffer(value))                                       \
+        _curl_easy_setopt_err_error_buffer();                                 \
+    if ((_curl_opt) == CURLOPT_STDERR)                                         \
+      if (!_curl_is_FILE(value))                                               \
+        _curl_easy_setopt_err_FILE();                                         \
+    if (_curl_is_postfields_option(_curl_opt))                                 \
+      if (!_curl_is_postfields(value))                                         \
+        _curl_easy_setopt_err_postfields();                                   \
+    if ((_curl_opt) == CURLOPT_HTTPPOST)                                       \
+      if (!_curl_is_arr((value), struct curl_httppost))                        \
+        _curl_easy_setopt_err_curl_httpost();                                 \
+    if (_curl_is_slist_option(_curl_opt))                                      \
+      if (!_curl_is_arr((value), struct curl_slist))                           \
+        _curl_easy_setopt_err_curl_slist();                                   \
+    if ((_curl_opt) == CURLOPT_SHARE)                                          \
+      if (!_curl_is_ptr((value), CURLSH))                                      \
+        _curl_easy_setopt_err_CURLSH();                                       \
+  }                                                                           \
+  curl_easy_setopt(handle, _curl_opt, value);                                 \
+})
+
+/* wraps curl_easy_getinfo() with typechecking */
+/* FIXME: don't allow const pointers */
+#define curl_easy_getinfo(handle, info, arg)                                  \
+__extension__({                                                              \
+  __typeof__(info) _curl_info = info;                                        \
+  if (__builtin_constant_p(_curl_info)) {                                      \
+    if (_curl_is_string_info(_curl_info))                                      \
+      if (!_curl_is_arr((arg), char *))                                        \
+        _curl_easy_getinfo_err_string();                                      \
+    if (_curl_is_long_info(_curl_info))                                        \
+      if (!_curl_is_arr((arg), long))                                          \
+        _curl_easy_getinfo_err_long();                                        \
+    if (_curl_is_double_info(_curl_info))                                      \
+      if (!_curl_is_arr((arg), double))                                        \
+        _curl_easy_getinfo_err_double();                                      \
+    if (_curl_is_slist_info(_curl_info))                                       \
+      if (!_curl_is_arr((arg), struct curl_slist *))                           \
+        _curl_easy_getinfo_err_curl_slist();                                  \
+  }                                                                           \
+  curl_easy_getinfo(handle, _curl_info, arg);                                 \
+})
+
+/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+#define curl_share_setopt(share, opt, param) curl_share_setopt(share, opt, param)
+#define curl_multi_setopt(handle, opt, param) curl_multi_setopt(handle, opt, param)
+
+
+/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+/* To define a new warning, use _CURL_WARNING(identifier, "message") */
+#define _CURL_WARNING(id, message)                                            \
+  static void __attribute__((__warning__(message)))                           \
+  __attribute__((__unused__)) __attribute__((__noinline__))                   \
+  id(void) { __asm__(""); }
+
+_CURL_WARNING(_curl_easy_setopt_err_long,
+  "curl_easy_setopt expects a long argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+  "curl_easy_setopt expects a curl_off_t argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_string,
+              "curl_easy_setopt expects a "
+              "string (char* or char[]) argument for this option"
+  )
+_CURL_WARNING(_curl_easy_setopt_err_write_callback,
+  "curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_read_cb,
+  "curl_easy_setopt expects a curl_read_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+  "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+  "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+              "curl_easy_setopt expects a "
+              "curl_opensocket_callback argument for this option"
+  )
+_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+  "curl_easy_setopt expects a curl_progress_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+  "curl_easy_setopt expects a curl_debug_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+  "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+  "curl_easy_setopt expects a curl_conv_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+  "curl_easy_setopt expects a curl_seek_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_cb_data,
+              "curl_easy_setopt expects a "
+              "private data pointer as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+              "curl_easy_setopt expects a "
+              "char buffer of CURL_ERROR_SIZE as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_FILE,
+  "curl_easy_setopt expects a FILE* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_postfields,
+  "curl_easy_setopt expects a void* or char* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+  "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+  "curl_easy_setopt expects a struct curl_slist* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+  "curl_easy_setopt expects a CURLSH* argument for this option")
+
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+  "curl_easy_getinfo expects a pointer to char * for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+  "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+  "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+  "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
+
+/* To add a new option to one of the groups, just add
+ *   (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+
+/* evaluates to true if option takes a long argument */
+#define _curl_is_long_option(option)                                          \
+  (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+#define _curl_is_off_t_option(option)                                         \
+  ((option) > CURLOPTTYPE_OFF_T)
+
+/* evaluates to true if option takes a char* argument */
+#define _curl_is_string_option(option)                                        \
+  ((option) == CURLOPT_URL ||                                                 \
+   (option) == CURLOPT_PROXY ||                                               \
+   (option) == CURLOPT_INTERFACE ||                                           \
+   (option) == CURLOPT_NETRC_FILE ||                                          \
+   (option) == CURLOPT_USERPWD ||                                             \
+   (option) == CURLOPT_USERNAME ||                                            \
+   (option) == CURLOPT_PASSWORD ||                                            \
+   (option) == CURLOPT_PROXYUSERPWD ||                                        \
+   (option) == CURLOPT_PROXYUSERNAME ||                                       \
+   (option) == CURLOPT_PROXYPASSWORD ||                                       \
+   (option) == CURLOPT_NOPROXY ||                                             \
+   (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
+   (option) == CURLOPT_REFERER ||                                             \
+   (option) == CURLOPT_USERAGENT ||                                           \
+   (option) == CURLOPT_COOKIE ||                                              \
+   (option) == CURLOPT_COOKIEFILE ||                                          \
+   (option) == CURLOPT_COOKIEJAR ||                                           \
+   (option) == CURLOPT_COOKIELIST ||                                          \
+   (option) == CURLOPT_FTPPORT ||                                             \
+   (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER ||                             \
+   (option) == CURLOPT_FTP_ACCOUNT ||                                         \
+   (option) == CURLOPT_RANGE ||                                               \
+   (option) == CURLOPT_CUSTOMREQUEST ||                                       \
+   (option) == CURLOPT_SSLCERT ||                                             \
+   (option) == CURLOPT_SSLCERTTYPE ||                                         \
+   (option) == CURLOPT_SSLKEY ||                                              \
+   (option) == CURLOPT_SSLKEYTYPE ||                                          \
+   (option) == CURLOPT_KEYPASSWD ||                                           \
+   (option) == CURLOPT_SSLENGINE ||                                           \
+   (option) == CURLOPT_CAINFO ||                                              \
+   (option) == CURLOPT_CAPATH ||                                              \
+   (option) == CURLOPT_RANDOM_FILE ||                                         \
+   (option) == CURLOPT_EGDSOCKET ||                                           \
+   (option) == CURLOPT_SSL_CIPHER_LIST ||                                     \
+   (option) == CURLOPT_KRBLEVEL ||                                            \
+   (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 ||                             \
+   (option) == CURLOPT_SSH_PUBLIC_KEYFILE ||                                  \
+   (option) == CURLOPT_SSH_PRIVATE_KEYFILE ||                                 \
+   (option) == CURLOPT_CRLFILE ||                                             \
+   (option) == CURLOPT_ISSUERCERT ||                                          \
+   (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE ||                               \
+   (option) == CURLOPT_SSH_KNOWNHOSTS ||                                      \
+   (option) == CURLOPT_MAIL_FROM ||                                           \
+   (option) == CURLOPT_RTSP_SESSION_ID ||                                     \
+   (option) == CURLOPT_RTSP_STREAM_URI ||                                     \
+   (option) == CURLOPT_RTSP_TRANSPORT ||                                      \
+   (option) == CURLOPT_XOAUTH2_BEARER ||                                      \
+   (option) == CURLOPT_DNS_SERVERS ||                                         \
+   (option) == CURLOPT_DNS_INTERFACE ||                                       \
+   (option) == CURLOPT_DNS_LOCAL_IP4 ||                                       \
+   (option) == CURLOPT_DNS_LOCAL_IP6 ||                                       \
+   (option) == CURLOPT_LOGIN_OPTIONS ||                                       \
+   0)
+
+/* evaluates to true if option takes a curl_write_callback argument */
+#define _curl_is_write_cb_option(option)                                      \
+  ((option) == CURLOPT_HEADERFUNCTION ||                                      \
+   (option) == CURLOPT_WRITEFUNCTION)
+
+/* evaluates to true if option takes a curl_conv_callback argument */
+#define _curl_is_conv_cb_option(option)                                       \
+  ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION ||                            \
+   (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION ||                          \
+   (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+/* evaluates to true if option takes a data argument to pass to a callback */
+#define _curl_is_cb_data_option(option)                                       \
+  ((option) == CURLOPT_WRITEDATA ||                                           \
+   (option) == CURLOPT_READDATA ||                                            \
+   (option) == CURLOPT_IOCTLDATA ||                                           \
+   (option) == CURLOPT_SOCKOPTDATA ||                                         \
+   (option) == CURLOPT_OPENSOCKETDATA ||                                      \
+   (option) == CURLOPT_PROGRESSDATA ||                                        \
+   (option) == CURLOPT_HEADERDATA ||                                         \
+   (option) == CURLOPT_DEBUGDATA ||                                           \
+   (option) == CURLOPT_SSL_CTX_DATA ||                                        \
+   (option) == CURLOPT_SEEKDATA ||                                            \
+   (option) == CURLOPT_PRIVATE ||                                             \
+   (option) == CURLOPT_SSH_KEYDATA ||                                         \
+   (option) == CURLOPT_INTERLEAVEDATA ||                                      \
+   (option) == CURLOPT_CHUNK_DATA ||                                          \
+   (option) == CURLOPT_FNMATCH_DATA ||                                        \
+   0)
+
+/* evaluates to true if option takes a POST data argument (void* or char*) */
+#define _curl_is_postfields_option(option)                                    \
+  ((option) == CURLOPT_POSTFIELDS ||                                          \
+   (option) == CURLOPT_COPYPOSTFIELDS ||                                      \
+   0)
+
+/* evaluates to true if option takes a struct curl_slist * argument */
+#define _curl_is_slist_option(option)                                         \
+  ((option) == CURLOPT_HTTPHEADER ||                                          \
+   (option) == CURLOPT_HTTP200ALIASES ||                                      \
+   (option) == CURLOPT_QUOTE ||                                               \
+   (option) == CURLOPT_POSTQUOTE ||                                           \
+   (option) == CURLOPT_PREQUOTE ||                                            \
+   (option) == CURLOPT_TELNETOPTIONS ||                                       \
+   (option) == CURLOPT_MAIL_RCPT ||                                           \
+   0)
+
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info)                                            \
+  (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info)                                              \
+  (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info)                                            \
+  (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info)                                             \
+  (CURLINFO_SLIST < (info))
+
+
+/* typecheck helpers -- check whether given expression has requested type*/
+
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+/* XXX: should evaluate to true iff expr is a pointer */
+#define _curl_is_any_ptr(expr)                                                \
+  (sizeof(expr) == sizeof(void*))
+
+/* evaluates to true if expr is NULL */
+/* XXX: must not evaluate expr, so this check is not accurate */
+#define _curl_is_NULL(expr)                                                   \
+  (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+/* evaluates to true if expr is type*, const type* or NULL */
+#define _curl_is_ptr(expr, type)                                              \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), type *) ||                  \
+   __builtin_types_compatible_p(__typeof__(expr), const type *))
+
+/* evaluates to true if expr is one of type[], type*, NULL or const type* */
+#define _curl_is_arr(expr, type)                                              \
+  (_curl_is_ptr((expr), type) ||                                              \
+   __builtin_types_compatible_p(__typeof__(expr), type[]))
+
+/* evaluates to true if expr is a string */
+#define _curl_is_string(expr)                                                 \
+  (_curl_is_arr((expr), char) ||                                              \
+   _curl_is_arr((expr), signed char) ||                                       \
+   _curl_is_arr((expr), unsigned char))
+
+/* evaluates to true if expr is a long (no matter the signedness)
+ * XXX: for now, int is also accepted (and therefore short and char, which
+ * are promoted to int when passed to a variadic function) */
+#define _curl_is_long(expr)                                                   \
+  (__builtin_types_compatible_p(__typeof__(expr), long) ||                    \
+   __builtin_types_compatible_p(__typeof__(expr), signed long) ||             \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned long) ||           \
+   __builtin_types_compatible_p(__typeof__(expr), int) ||                     \
+   __builtin_types_compatible_p(__typeof__(expr), signed int) ||              \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned int) ||            \
+   __builtin_types_compatible_p(__typeof__(expr), short) ||                   \
+   __builtin_types_compatible_p(__typeof__(expr), signed short) ||            \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned short) ||          \
+   __builtin_types_compatible_p(__typeof__(expr), char) ||                    \
+   __builtin_types_compatible_p(__typeof__(expr), signed char) ||             \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned char))
+
+/* evaluates to true if expr is of type curl_off_t */
+#define _curl_is_off_t(expr)                                                  \
+  (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+/* XXX: also check size of an char[] array? */
+#define _curl_is_error_buffer(expr)                                           \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), char *) ||                  \
+   __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+/* evaluates to true if expr is of type (const) void* or (const) FILE* */
+#if 0
+#define _curl_is_cb_data(expr)                                                \
+  (_curl_is_ptr((expr), void) ||                                              \
+   _curl_is_ptr((expr), FILE))
+#else /* be less strict */
+#define _curl_is_cb_data(expr)                                                \
+  _curl_is_any_ptr(expr)
+#endif
+
+/* evaluates to true if expr is of type FILE* */
+#define _curl_is_FILE(expr)                                                   \
+  (__builtin_types_compatible_p(__typeof__(expr), FILE *))
+
+/* evaluates to true if expr can be passed as POST data (void* or char*) */
+#define _curl_is_postfields(expr)                                             \
+  (_curl_is_ptr((expr), void) ||                                              \
+   _curl_is_arr((expr), char))
+
+/* FIXME: the whole callback checking is messy...
+ * The idea is to tolerate char vs. void and const vs. not const
+ * pointers in arguments at least
+ */
+/* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+#define _curl_callback_compatible(func, type)                                 \
+  (__builtin_types_compatible_p(__typeof__(func), type) ||                    \
+   __builtin_types_compatible_p(__typeof__(func), type*))
+
+/* evaluates to true if expr is of type curl_read_callback or "similar" */
+#define _curl_is_read_cb(expr)                                          \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) ||       \
+   __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) ||      \
+   _curl_callback_compatible((expr), _curl_read_callback1) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback2) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback3) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback4) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback5) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback6))
+typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
+typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_write_callback or "similar" */
+#define _curl_is_write_cb(expr)                                               \
+  (_curl_is_read_cb(expr) ||                                            \
+   __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) ||      \
+   __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) ||     \
+   _curl_callback_compatible((expr), _curl_write_callback1) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback2) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback3) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback4) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback5) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback6))
+typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
+                                       const void*);
+typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
+typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
+                                       const void*);
+typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+#define _curl_is_ioctl_cb(expr)                                         \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) ||     \
+   _curl_callback_compatible((expr), _curl_ioctl_callback1) ||                \
+   _curl_callback_compatible((expr), _curl_ioctl_callback2) ||                \
+   _curl_callback_compatible((expr), _curl_ioctl_callback3) ||                \
+   _curl_callback_compatible((expr), _curl_ioctl_callback4))
+typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
+typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
+typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
+typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+
+/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+#define _curl_is_sockopt_cb(expr)                                       \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) ||   \
+   _curl_callback_compatible((expr), _curl_sockopt_callback1) ||              \
+   _curl_callback_compatible((expr), _curl_sockopt_callback2))
+typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
+                                      curlsocktype);
+
+/* evaluates to true if expr is of type curl_opensocket_callback or
+   "similar" */
+#define _curl_is_opensocket_cb(expr)                                    \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
+   _curl_callback_compatible((expr), _curl_opensocket_callback1) ||           \
+   _curl_callback_compatible((expr), _curl_opensocket_callback2) ||           \
+   _curl_callback_compatible((expr), _curl_opensocket_callback3) ||           \
+   _curl_callback_compatible((expr), _curl_opensocket_callback4))
+typedef curl_socket_t (_curl_opensocket_callback1)
+  (void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback2)
+  (void *, curlsocktype, const struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback3)
+  (const void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback4)
+  (const void *, curlsocktype, const struct curl_sockaddr *);
+
+/* evaluates to true if expr is of type curl_progress_callback or "similar" */
+#define _curl_is_progress_cb(expr)                                      \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) ||  \
+   _curl_callback_compatible((expr), _curl_progress_callback1) ||             \
+   _curl_callback_compatible((expr), _curl_progress_callback2))
+typedef int (_curl_progress_callback1)(void *,
+    double, double, double, double);
+typedef int (_curl_progress_callback2)(const void *,
+    double, double, double, double);
+
+/* evaluates to true if expr is of type curl_debug_callback or "similar" */
+#define _curl_is_debug_cb(expr)                                         \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) ||     \
+   _curl_callback_compatible((expr), _curl_debug_callback1) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback2) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback3) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback4) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback5) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback6) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback7) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback8))
+typedef int (_curl_debug_callback1) (CURL *,
+    curl_infotype, char *, size_t, void *);
+typedef int (_curl_debug_callback2) (CURL *,
+    curl_infotype, char *, size_t, const void *);
+typedef int (_curl_debug_callback3) (CURL *,
+    curl_infotype, const char *, size_t, void *);
+typedef int (_curl_debug_callback4) (CURL *,
+    curl_infotype, const char *, size_t, const void *);
+typedef int (_curl_debug_callback5) (CURL *,
+    curl_infotype, unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback6) (CURL *,
+    curl_infotype, unsigned char *, size_t, const void *);
+typedef int (_curl_debug_callback7) (CURL *,
+    curl_infotype, const unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback8) (CURL *,
+    curl_infotype, const unsigned char *, size_t, const void *);
+
+/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+/* this is getting even messier... */
+#define _curl_is_ssl_ctx_cb(expr)                                       \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) ||   \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
+#ifdef HEADER_SSL_H
+/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+                                           const void *);
+#else
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+#endif
+
+/* evaluates to true if expr is of type curl_conv_callback or "similar" */
+#define _curl_is_conv_cb(expr)                                          \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) ||      \
+   _curl_callback_compatible((expr), _curl_conv_callback1) ||                 \
+   _curl_callback_compatible((expr), _curl_conv_callback2) ||                 \
+   _curl_callback_compatible((expr), _curl_conv_callback3) ||                 \
+   _curl_callback_compatible((expr), _curl_conv_callback4))
+typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+/* evaluates to true if expr is of type curl_seek_callback or "similar" */
+#define _curl_is_seek_cb(expr)                                          \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) ||      \
+   _curl_callback_compatible((expr), _curl_seek_callback1) ||                 \
+   _curl_callback_compatible((expr), _curl_seek_callback2))
+typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+#endif /* __CURL_TYPECHECK_GCC_H */
diff --git a/src/connectivity/gps/mtk_mnld/curl/libs/Android.mk b/src/connectivity/gps/mtk_mnld/curl/libs/Android.mk
new file mode 100644
index 0000000..deea3fc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/Android.mk
@@ -0,0 +1,16 @@
+ifneq ($(TRUSTONIC_TEE_SUPPORT),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+#LOCAL_MODULE := libcurl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+#LOCAL_MODULE_TAGS := optional
+#LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+#LOCAL_SRC_FILES_arm := libcurl_32.so
+#LOCAL_SRC_FILES_arm64 := libcurl_64.so
+#LOCAL_MODULE_SUFFIX := .so
+#LOCAL_MULTILIB := both
+#include $(BUILD_PREBUILT)
+endif
diff --git a/src/connectivity/gps/mtk_mnld/curl/libs/NOTICE b/src/connectivity/gps/mtk_mnld/curl/libs/NOTICE
new file mode 100644
index 0000000..163b299
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/NOTICE
@@ -0,0 +1,21 @@
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2010, Daniel Stenberg, <daniel@haxx.se>.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright
+notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization of the copyright holder.
diff --git a/src/connectivity/gps/mtk_mnld/curl/libs/README b/src/connectivity/gps/mtk_mnld/curl/libs/README
new file mode 100644
index 0000000..c713169
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libcurl.so is the implementation that access URL for downloading epo data as one shared library.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by android build system.
+
+HOW TO USE IT?
+==============
+Their API will be called to download epo data when GPS open if epo file is expired.
+
+Source
+==============
+All the source code of this library were downloaded from http://curl.haxx.se/
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_32.so b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_32.so
new file mode 100644
index 0000000..8a3449e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_32.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_64.so b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_64.so
new file mode 100644
index 0000000..5669ca5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/curl/libs/libcurl_64.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/etc/gps.conf b/src/connectivity/gps/mtk_mnld/etc/gps.conf
new file mode 100644
index 0000000..33c2fb9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/gps.conf
@@ -0,0 +1,4 @@
+EPO_ENABLE=1
+DW_DAYS=9
+EPO_WIFI_TRIGGER=0
+RAW_DEBUG_MODE=1
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/etc/mnl.prop b/src/connectivity/gps/mtk_mnld/etc/mnl.prop
new file mode 100644
index 0000000..3f6ab89
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/mnl.prop
@@ -0,0 +1,4 @@
+#
+# ADDITIONAL_DEFAULT_PROPERTIES
+#
+debug.dbg2file=1
diff --git a/src/connectivity/gps/mtk_mnld/etc/mpe.conf b/src/connectivity/gps/mtk_mnld/etc/mpe.conf
new file mode 100644
index 0000000..6f15a86
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/mpe.conf
@@ -0,0 +1,4 @@
+mpe_enable=1
+print_rawdata=0
+auto_calib=0
+indoor_enable=1
diff --git a/src/connectivity/gps/mtk_mnld/etc/updateEPOconfig.bat b/src/connectivity/gps/mtk_mnld/etc/updateEPOconfig.bat
new file mode 100644
index 0000000..31d4e76
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/updateEPOconfig.bat
@@ -0,0 +1 @@
+adb push gps.conf /data/misc/gps/gps.conf
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/etc/update_mnl.bat b/src/connectivity/gps/mtk_mnld/etc/update_mnl.bat
new file mode 100644
index 0000000..3d99516
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/etc/update_mnl.bat
@@ -0,0 +1,6 @@
+adb wait-for-device

+adb remount

+

+adb push mnl.prop /data/misc/gps/

+

+PAUSE
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_da.bin b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_da.bin
new file mode 100644
index 0000000..69046ef
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_da.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_fw.bin b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_fw.bin
new file mode 100644
index 0000000..2b8c31f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/flashdownload/bin/3333_fw.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/bin/Android.mk b/src/connectivity/gps/mtk_mnld/mnl/bin/Android.mk
new file mode 100644
index 0000000..be3069c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/bin/Android.mk
@@ -0,0 +1,62 @@
+# 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) 2016. 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.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+LOCAL_PATH := $(call my-dir)
+
+$(warning MTK_COMBO_CHIP=$(MTK_COMBO_CHIP))
+
+ifneq ($(filter CONSYS_6771,$(MTK_COMBO_CHIP)),)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MNL_MT6771_E1.bin
+LOCAL_MODULE := MNL.bin
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware
+$(warning LOCAL_SRC_FILES=$(LOCAL_SRC_FILES))
+include $(BUILD_PREBUILT)
+endif
+
+ifneq ($(filter CONSYS_6775,$(MTK_COMBO_CHIP)),)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MNL_MT6775_E1.bin
+LOCAL_MODULE := MNL.bin
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware
+$(warning LOCAL_SRC_FILES=$(LOCAL_SRC_FILES))
+include $(BUILD_PREBUILT)
+endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6771_E1.bin b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6771_E1.bin
new file mode 100644
index 0000000..9286c0d
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6771_E1.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6775_E1.bin b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6775_E1.bin
new file mode 100644
index 0000000..4736608
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/bin/MNL_MT6775_E1.bin
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_BEE.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_BEE.h
new file mode 100644
index 0000000..a2763aa
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_BEE.h
@@ -0,0 +1,359 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+//*****************************************************************************
+// [File] MTK_BEE.h : Defines the entry point for BEE library
+// [Version] v1.0
+// [Revision Date] 2008-03-31
+// [Author] YC Chien, yc.chien@mediatek.com, 21558
+//          WG Yau, wg.yau@mediatek.com, 26967
+// [Description]
+//*****************************************************************************
+
+
+#ifndef MTK_BEE_H
+#define MTK_BEE_H
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+#include "MTK_Type.h"
+#include "mtk_gps_type.h"
+
+
+//*****************************************************************************
+// MTK_BEE_Init : Initialize BEE kernel data
+//
+// PARAMETER : void
+//
+// RETURN : 1 for success, 0 for error
+//          If return value is 0, you should NOT proceed with any BEE function
+
+MTK_BEE_INT MTK_BEE_Init (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Init : Uninitialize BEE kernel data
+//
+// PARAMETER : void
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Uninit (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Set_File_Path : Set File Path for BEE kernel file
+//
+// PARAMETER : szFilePath [IN] - (1) Input file path for ARC.BIN, BEE.BIN and
+//                                   BEET000A.
+//                               (2) Maximal path length is 256 bytes.
+//                               (3) MUST BE null-terminated string.
+//                               (4) MUST BE called before MTK_BEE_Init().
+//                               (5) MUST BE ended with a directory separator
+//                                   character. (ex: '\\')
+//                               (6) If this function has not been called,
+//                                   then no file path is set.
+// EXAMPLE :
+//    MTK_BEE_Set_File_path("C:\\BEE\\");
+//    MTK_BEE_Init();
+//    ===> Input File path before MTK_BEE_Init() is called.
+//
+// RETURN : 1 for success, 0 for error
+//          If return value is 0, you should NOT proceed with any BEE function
+
+MTK_BEE_INT MTK_BEE_Set_File_Path (char szFilePath[256]);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Table_Health : Get the health status of BEE data file (BEET000A)
+//
+// PARAMETER : void
+//
+// RETURN : 0 -> BEE data file is healthy
+//          1 -> BEE data file is valid for BEE functionality, but an update for this file is suggested
+//          2 -> BEE data file is expired so that BEE functionality has been stopped
+//          3 -> User has updated BEE data file to an older version,
+//               BEE functionality has been stopped, need to update data file
+
+MTK_BEE_INT MTK_BEE_Get_Table_Health (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Proc_Eph : Save broadcast ephemeris into BEE kernel database
+//
+// PARAMETER : u1SvId  [IN] - satellite ID
+//             au4Word [IN] - 24-word ephemeris raw data (word 3-8 of subframe 1,2,3)
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Proc_Eph (unsigned char u1SvId, unsigned int au4Word[24]);
+
+
+//*****************************************************************************
+// MTK_BEE_Have_Enough_Eph : Check how many satellites have enough ephemeris for BEE generation
+//
+// PARAMETER : i2WeekNo    [IN] - week number (count from Jan. 6, 1980)
+//             i4Tow       [IN] - time of week
+//
+// RETURN : Number of satellites with enough ephemeris for BEE generation
+//          Ex : 5 -> 5 satellites have enough ephemeris
+//
+// NOTE : i2WeekNo and i4Tow SHOULD BE set to the correct current time ( > 0),
+//        If i2WeekNo = 0 and i4Tow = 0 this function will not do optimization !!!
+//
+// EXAMPLE :
+//    short i2WeekNo;
+//    int i4Tow;
+//    int i4NumSvToGen = MTK_BEE_Have_Enough_Eph(i2WeekNo, i4Tow);
+//    if ( i4NumSvToGen >= 3 )  ===> Do BEE generation when at least 3 satellites have enough ephemeris
+//    {
+//        MTK_BEE_Gen_Auto(i2WeekNo, i4Tow);
+//    }
+
+MTK_BEE_INT MTK_BEE_Have_Enough_Eph (short i2WeekNo, int i4Tow);
+
+
+//*****************************************************************************
+// MTK_BEE_Gen_All : Generate BEE ephemeris of all satellites
+//
+// PARAMETER : void
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Gen_All (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Gen_Auto : Auto Generate BEE ephemeris of all satellites
+//
+// PARAMETER : i2WeekNo    [IN] - week number (count from Jan. 6, 1980)
+//             i4Tow       [IN] - time of week
+//
+// RETURN : 1 -> BEE data is already FULL generated
+//          0 -> BEE data is not FULL generated
+//
+// NOTE : i2WeekNo and i4Tow MUST BE set to the correct current time ( > 0),
+//        otherwise this function may have wrong generated data !!!
+//        If i2WeekNo = 0 and i4Tow = 0 this function will not do optimization !!!
+
+MTK_BEE_INT MTK_BEE_Gen_Auto (short i2WeekNo, int i4Tow);
+
+
+//*****************************************************************************
+// MTK_BEE_Gen_Data : Generate BEE ephemeris of the specified satellite
+//
+// PARAMETER : u1SvId      [IN] - satellite ID
+//             i2WeekNo    [IN] - week number (count from Jan. 6, 1980)
+//             i4Tow       [IN] - time of week
+//             u1GenLength [IN] - generate length ( MUST > 0 )
+//                                =1 -> Generate 1 Day  Data
+//                                =2 -> Generate 2 Days Data
+//                                =3 -> Generate 3 Days Data
+//                                >3 -> Generate 3 Days Data
+//
+// RETURN : 0 -> No data has been generated / No BEE data
+//          1 -> 1 day  data is already generated
+//          2 -> 2 days data is already generated
+//          3 -> 3 days data is already generated
+//
+// NOTE : If i2WeekNo and i4Tow is set to the current time ( > 0), then this function will delete expired BEE data
+//        (ex. 3 days ago data) based on this current time. Therefore, return value will be 0.
+//        Set i2WeekNo = 0 and i4Tow = 0 to bypass this time checking.
+//
+// EXAMPLE :
+//    unsigned char u1GenState;
+//    unsigned char u1SvId = 1;
+//    (1)
+//    u1GenState = MTK_BEE_Gen_Data(u1SvId, 0, 0, 3);
+//    ===> Generate 3 days BEE data of SV 1, bypass time checking.
+//         If u1GenState = 3, means already has 3 days BEE data, not necessary to generate data within this period,
+//         unless receive new ephemeris.
+//    (2)
+//    u1GenState = MTK_BEE_Gen_Data(u1SvId, 0, 0, 1);
+//    ===> Generate 1 day BEE data of SV 1, bypass time checking.
+//    (3)
+//    u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 1);
+//    ===> Generate 1 day BEE data of SV 1, using time checking.
+//
+//    (4) Methods for 3 days BEE data generation
+//    ------------------------------------------
+//    (a) u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 1);  ==> u1GenState = 1 (has 1 day BEE data)
+//        u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313300, 1);  ==> u1GenState = 2 (has 2 days BEE data)
+//        u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313400, 1);  ==> u1GenState = 3 (has 3 days BEE data)
+//
+//    (b) u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 2);  ==> u1GenState = 2 (has 2 day BEE data)
+//        u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313300, 1);  ==> u1GenState = 3 (has 3 days BEE data)
+//
+//    (c) u1GenState = MTK_BEE_Gen_Data(u1SvId, 1467, 313200, 3);  ==> u1GenState = 3 (has 3 day BEE data)
+
+MTK_BEE_INT MTK_BEE_Gen_Data (unsigned char u1SvId, short i2WeekNo, int i4Tow, unsigned char u1GenLength);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Progress : Get the progress of BEE generation
+//
+// PARAMETER : void
+//
+// RETURN : Progress of current BEE generation, represented in percentage (%)
+//          100    : No action (no generation under going / generation finished)
+//          0 - 99 : Progress
+
+MTK_BEE_INT MTK_BEE_Get_Progress (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Data : Get BEE ephemeris of the specified satellite at the specified time
+//
+// PARAMETER : u1SvId   [IN]  - satellite ID
+//             i2WeekNo [IN]  - week number (count from Jan. 6, 1980)
+//             i4Tow    [IN]  - time of week
+//             BeeData  [OUT] - BEE ephemeris
+//
+// RETURN : 1 for success, 0 for no BEE data
+
+MTK_BEE_INT MTK_BEE_Get_Data (unsigned char u1SvId, short i2WeekNo, int i4Tow, unsigned char BeeData[48]);
+
+
+//*****************************************************************************
+// MTK_BEE_Get_Available_Info : Get information about BEE ephemeris of which satellite
+//
+// PARAMETER : i2WeekNo [IN]  - week number (count from Jan. 6, 1980)
+//             i4Tow    [IN]  - time of week
+//             BeeAvail [OUT] - Array of 32 unsigned char for 32 satellites
+//                              0 -- no BEE available for this satellite
+//                           1-xx -- BEE is available for this satellite ( Valid Hours )
+//
+// RETURN : 1 for success
+
+MTK_BEE_INT MTK_BEE_Get_Available_Info (short i2WeekNo, int i4Tow, unsigned char BeeAvail[32]);
+
+//*****************************************************************************
+// MTK_BEE_Get_GNSS_Available_Info : Get information about BEE ephemeris of which satellite
+//
+// PARAMETER : i2WeekNo [IN]  - week number (count from Jan. 6, 1980)
+//             i4Tow    [IN]  - time of week
+//             BeeAvail [OUT] - Array of 256 unsigned char for 256 satellites
+//                              0 -- no BEE available for this satellite
+//                           1-xx -- BEE is available for this satellite ( Valid Hours )
+//
+// RETURN : 1 for success
+
+MTK_BEE_INT MTK_BEE_Get_GNSS_Available_Info (short i2WeekNo, int i4Tow, unsigned char BeeAvail[256]);
+
+//*****************************************************************************
+// MTK_BEE_Enable_Eph_Update : Enable updating BEE with broadcast ephemeris
+//                             for ALL satellites and save the configuration to file
+//
+// PARAMETER : void
+//
+// RETURN : 1 for success, 0 if fail to save configuration to file
+
+MTK_BEE_INT MTK_BEE_Enable_Eph_Update (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Disable_Eph_Update : Disable updating BEE with broadcast ephemeris
+//                              for ALL satellites and save the configuration to file
+//
+// PARAMETER : void
+//
+// RETURN : 1 for success, 0 if fail to save configuration to file
+
+MTK_BEE_INT MTK_BEE_Disable_Eph_Update (void);
+
+
+//*****************************************************************************
+// MTK_BEE_Set_Eph_Update : Set whether to update BEE with broadcast ephemeris
+//                          for individual satellite and save the configuration to file
+//
+// PARAMETER : UpdateEph [IN] - Array of 32 unsigned char for 32 satellites
+//                              0 -- disable updating broadcast ephemeris for this satellite
+//                              1 -- enable updating broadcast ephemeris for this satellite
+//
+// RETURN : 1 for success, 0 if fail to save configuration to file
+
+MTK_BEE_INT MTK_BEE_Set_Eph_Update (unsigned char UpdateEph[32]);
+
+
+//*****************************************************************************
+// MTK_BEE_Hot_Still_Test : Perform hot still test
+//
+// PARAMETER : u4Test_Mode [IN] -
+//                 bit0 : use old force model parameters
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Hot_Still_Test(unsigned long u4Test_Mode);
+
+
+//*****************************************************************************
+// MTK_BEE_Test : Perform BEE self-test, output data is stored in BEE_TEST.BIN
+//
+// PARAMETER : u1SvId [IN] - PRN of the satellite to be tested
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Test (unsigned char u1SvId);
+
+//*****************************************************************************
+// MTK_BEE_Shutdown : force HotStill run into shutdown mode. (shutdown all jobs after curretn prediction done)
+//
+// PARAMETER : fgEnableShutdown [IN] -
+//                 0 : disable shutdown to resume original state
+//                 1 : enable shutdown
+// RETURN : void
+MTK_BEE_VOID MTK_BEE_Shutdown(unsigned char fgEnableShutdown);
+
+//*****************************************************************************
+// MTK_BEE_Get_Version_Info : Get BEE and HotStill related information
+//
+// PARAMETER : Version        [OUT] - Library version
+//                      Lib_Date      [OUT] - Library release dat information
+//
+// RETURN : void
+
+MTK_BEE_VOID MTK_BEE_Get_Version_Info (double *Version, char *Lib_Date);
+
+//*****************************************************************************
+// MTK_BEE_Get_Calibration_Status : Get HotStill calibration status
+//
+// PARAMETER : void
+//
+// RETURN : 1 for calibration and gen in progess, 0 for calibration not in progress
+
+MTK_BEE_INT MTK_BEE_Get_Calibration_Status(void);
+
+//*****************************************************************************
+// MTK_BEE_Set_Debug_Config : Set HotStill debug configuration
+//
+// PARAMETER : DbgType       [IN] - debug type
+//             DbgLevel      [IN] - debug level
+// RETURN : 1 success, 0 fail
+
+MTK_BEE_INT MTK_BEE_Set_Debug_Config(MTK_DEBUG_TYPE DbgType, MTK_DEBUG_LEVEL DbgLevel);
+
+//*****************************************************************************
+// MTK_BEE_Get_Debug_Config : Get HotStill debug configuration
+//
+// PARAMETER : DbgType       [IN]  - debug type
+//             *DbgLevel     [OUT] - debug level
+//
+// RETURN : 1 success, 0 fail
+MTK_BEE_INT MTK_BEE_Get_Debug_Config(MTK_DEBUG_TYPE DbgType, MTK_DEBUG_LEVEL *DbgLevel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MTK_BEE_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_SDK_Bee.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_SDK_Bee.h
new file mode 100644
index 0000000..51277e4
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_SDK_Bee.h
@@ -0,0 +1,530 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+#ifndef MTK_SDK_BEE_H
+#define MTK_SDK_BEE_H
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+//*****************************************************************************************************
+// MTK_Bee_Feed_Eph  :  Feed the ephemeris to Bee Host
+//
+// Description  :  MTK_Bee_Feed_Eph ( unsigned char Svid , unsigned int au4Word[24] )
+//                 Svid : GPS satellite PRN (1~32)
+//                 au4Word --  24 words ephemeris data
+//
+// Returns: zero(fail), nonzero(pass)
+//
+// Example :
+//    unsigned char SvId = 0;
+//    unsigned int Ephdata[24];
+//    iRes = MTK_Bee_Feed_Eph ( SvId, Ephdata);
+//
+//    =====> Ephdata is ephemeris data and need to transfer to BEE HOST
+//           If iRes > 0 --> Data is valid and can be transfered to BEE HOST
+
+int MTK_Bee_Feed_Eph ( unsigned char Svid , unsigned int au4Word[24] );
+
+//*****************************************************************************************************
+// MTK_Bee_Receive_Bee_Data  :  Receive the Bee data from HOST
+//
+// Description  :  MTK_Bee_Receive_Bee_Data ( char *BeeData )
+//                 BeeData --  BEE data from HOST for aiding.
+//                             BEE data buf mest be greater than 96 bytes.
+//
+// Returns: zero(fail), nonzero(pass)
+//
+// Example :
+//    char Beedatabuf[96];   // must be >= 96 bytes
+//    iRes = MTK_Bee_Receive_Bee_Data ( Beedatabuf );
+//
+//    =====> Beedatabuf is BEE data and need to feed to GPS receiver
+//           If iRes > 0 --> Bee data aiding is valid.
+
+int MTK_Bee_Receive_Bee_Data ( char *BeeData );
+
+//*****************************************************************************************************
+// MTK_Bee_Request_All  :  Send request BEE data command to HOST.
+//
+// Description  :  MTK_Bee_Request_All ( void )
+//                 Send a Nmea command to HOST for request the BEE data.
+//
+// Example :
+//    MTK_Bee_Request_All();
+//
+//    =====> $PMTKRQTBEE*17
+
+void MTK_Bee_Request_All ( void );
+
+//********************************************************************************************************
+// MTK_Bee_Get_Eph_Info  :  Get the information whether satellites has Ephemeris (BRDC / BEE) or not
+//
+//    Note  :  Eph is arrays with 32 unsigned char.
+//             0       ---> This SV has no Ephemeris.
+//             1       ---> This SV has BRDC Ephemeris.
+//             2       ---> This SV has 1st day BEE Ephemeris.
+//             3       ---> This SV has 2nd day BEE Ephemeris.
+//             4       ---> This SV has 3rd day BEE Ephemeris.
+//
+// Example:
+//    unsigned char Eph[32];
+//    MTK_Bee_Get_Eph_Info(Eph);
+//    MTK_UART_OutputData("SDK: Eph = %d", Eph[16]);
+//
+// =====> SDK: Eph = 1  ---> SV17 has BRDC Ephemeris.
+// =====> SDK: Eph = 2  ---> SV17 has 1st day BEE Ephemeris.
+
+void MTK_Bee_Get_Eph_Info (unsigned char Eph[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Get_New_Eph_Info  :  Get the information whether satellites has new Ephemeris or not
+//
+//    Note  :  NewEph is 1 unsigned int with 32 bit.
+//             bit x = 0       ---> No  New Ephemeris, x+1 = GPS satellite PRN.
+//             bit x = 1       ---> Has New Ephemeris, x+1 = GPS satellite PRN.
+// Example:
+//    int i;
+//    unsigned int NewEph,EPhMask;
+//    MTK_Bee_Get_Eph_Info(&NewEph);
+//    MTK_UART_OutputData("SDK: NewEph = %d", NewEph);
+//    if ( NewEph != 0 )
+//    {
+//       EPhMask = 1;
+//       for (i = 0; i < 32; i++)
+//       {
+//          if ( (NewEph & EPhMask) != 0 )
+//          {
+//                MTK_UART_OutputData("SV%d: NewEph = %d", i+1, NewEph);
+//          }
+//          EPhMask = EPhMask << 1;
+//       }
+//    }
+// =====> SDK: NewEph = 1   ---> Has New Ephemeris.
+// =====> SV3: NewEph = 1   ---> SV3 has New Ephemeris.
+// =====> SV17: NewEph = 1  ---> SV17 has New Ephemeris.
+
+void MTK_Bee_Get_New_Eph_Info (unsigned int *NewEph);
+
+//********************************************************************************************************
+// MTK_Bee_Req_Info  :  Get the information whether need to request BEE data or not
+//
+//    Note  :  BeeReq is arrays with 32 unsigned char.
+//             0       ---> This SV no need to request BEE Ephemeris.
+//             1       ---> This SV need to request BEE Ephemeris.
+// Example:
+//    unsigned char BeeReq[32];
+//    MTK_Bee_Req_Info(BeeReq);
+//    MTK_UART_OutputData("SDK: BeeReq = %d", BeeReq[16]);
+//
+// =====> SDK: BeeReq = 1  ---> SV17 need to request BEE Ephemeris.
+// =====> SDK: BeeReq = 0  ---> SV17 no need to request BEE Ephemeris.
+
+void MTK_Bee_Req_Info (unsigned char BeeReq[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Age  :  Get the age information of BEE data
+//
+//    Note  :  BeeAge is arrays with 32 short.
+//             -1      ---> BEE Ephemeris is not valid .
+//             nonzero ---> BEE Ephemeris age.
+// Example:
+//    short BeeAge [32];
+//    MTK_Bee_Age(BeeAge);
+//    MTK_UART_OutputData("SDK: BeeAge = %d", BeeAge[16]);
+//
+// =====> SDK: BeeReq = 300  ---> SV17 BEE Ephemeris has been used 300 sec.
+// =====> SDK: BeeReq = -1   ---> SV17 BEE Ephemeris is not valid.
+
+void MTK_Bee_Age ( short BeeAge[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Send_New_Eph  :  Send new ephemeris to Host
+//
+// Description : MTK_Bee_Send_New_Eph (unsigned int *NewEphSv);
+//               NewEphSv -- 32-bit mask to indicate if satellites have new ephemeirs or not
+//               bit x = 0  ---> No  New Ephemeris, x+1 = GPS satellite PRN
+//               bit x = 1  ---> Has New Ephemeris, x+1 = GPS satellite PRN
+//
+// Return : 0  ---> No new BRDC
+//          1  ---> Have new BRDC, Receiver should start handshaking with Host
+//          2  ---> Have new BRDC and handshaking is OK, Receiver should send BRDC data to Host
+//
+// Example :
+//    void SDK_Main (void)
+//    {
+//       int NewEphStep;
+//       unsigned char SvId;
+//       unsigned int EphData[24];
+//       NewEphStep = MTK_Bee_Send_New_Eph();
+//       if (NewEphStep == 1)
+//       {
+//          ... Send handshaking message to Host ...
+//       }
+//       else if (NewEphStep == 2)
+//       {
+//          if ( MTK_Bee_Get_New_Eph_Data(&SvId, EphData) )
+//          {
+//             ... Send ephemeris data to Host ...
+//          }
+//       }
+//    }
+
+int MTK_Bee_Send_New_Eph (unsigned int *NewEphSv);
+
+//********************************************************************************************************
+// MTK_Bee_Get_New_Eph_Data  :  Get ephemeris data to send
+//
+// Description : MTK_Bee_Get_New_Eph_Data ( unsigned char *SvId, unsigned int EphData[24] )
+//               SvId    -- pointer to Satellite ID
+//               EphData -- 24-word ephemeris data
+//
+// Note : This function automatically determines which ephemeris should be sent at current time
+//
+// Return : 0  ---> No ephemeris data needed to be sent
+//          1  ---> Have ephemeris data to be sent
+//
+// Example :
+//    unsigned char SvId;
+//    unsigned int EphData[24];
+//    iRes = MTK_Bee_Get_New_Eph_Data(&SvId, EphData);
+//    if ( iRes )
+//    {
+//        for ( i = 0; i < 24; i++ )
+//        {
+//            sprintf(( buf + i*7 ), ",%06X", EphData[i]);
+//        }
+//        MTK_NMEA_OutputData("PMTKDTEPH,%02X%s", SvId, buf);
+//    }
+
+int MTK_Bee_Get_New_Eph_Data (unsigned char *SvId, unsigned int EphData[24]);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_New_Eph_Host_Ready  :  Receive message of Host ready to receive new ephemeris
+//
+// Description : MTK_Bee_Receive_New_Eph_Ack ( unsigned char SvId )
+//               SvId -- Satellite ID for ACK
+//
+// Example :
+//    MTK_Bee_Receive_New_Eph_Host_Ready();
+//    MTK_UART_OutputData("READY TO SEND BRDC DATA");
+
+void MTK_Bee_Receive_New_Eph_Host_Ready (void);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_New_Eph_Ack  :  Receive ack for new ephemeris data from Host
+//
+// Description : MTK_Bee_Receive_New_Eph_Ack ( unsigned char SvId )
+//               SvId -- Satellite ID for ACK
+//
+// Return : 0  ---> Invalid ACK, satellite ID does not match the ephemeris sent
+//          1  ---> ACK is valid
+//
+// Example :
+//    unsigned char SvId;
+//    iRes = MTK_Bee_Receive_New_Eph_Ack(SvId);
+//    if ( iRes )
+//    {
+//       MTK_UART_OutputData("BRDC ACK SV %d OK", SvId);
+//    }
+//    else
+//    {
+//       MTK_UART_OutputData("BRDC ACK SV %d FAIL", SvId);
+//    }
+
+int MTK_Bee_Receive_New_Eph_Ack (unsigned char SvId);
+
+//********************************************************************************************************
+// MTK_Bee_Request_Data  :  Get a list of satellites which need BEE data
+//
+// Description : MTK_Bee_Request_Data ( unsigned char BeeReq[32] )
+//               BeeReq -- Array with 32 unsigned char
+//               0  ---> Seed BEE request for this satellite
+//               1  ---> Do not send BEE request for this satellite
+//
+//    Note  :  If MTK_Bee_Disable_BEE() is called to diable BEE,
+//             this function will not request any BEE data.
+//             Only after MTK_Bee_Enable_BEE() is called,
+//             this function will restart to request BEE data.
+//
+// Example :
+//    int NumSv, NumSvOnce, i;
+//    unsigned char BeeReq[32];
+//    char buf[256], tmp[16];
+//    MTK_Bee_Request_Data(BeeReq);
+//    for ( i = 0; i < 32; i++ )
+//    {
+//        if ( BeeReq[i] )
+//        {
+//            NumSv++;
+//            sprintf(tmp, ",%d", i + 1);
+//            strcat(buf, tmp);
+//        }
+//    }
+//    NumSvOnce = 6;
+//    if ( NumSv > 0 )
+//    {
+//        MTK_NMEA_OutputData("PMTKRQTBEE,%d,%d%s", NumSvOnce, NumSv, buf);
+//    }
+
+void MTK_Bee_Request_Data (unsigned char BeeReq[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_Host_Info  :  Receive a list of satellites which Host has their BEE data
+//
+// Description : MTK_Bee_Receive_Host_Info ( int NumSv, unsigned char HostBeeInfo[32] )
+//               NumSv       -- Number of satellites in
+//               HostBeeInfo -- Array with 32 unsigned char
+//               0  ---> Host does not have BEE data for this satellite
+//               1  ---> Host has BEE data for this satellite
+//
+// Return : 0  ---> Fail, input information is not valid
+//          1  ---> OK, input information is valid
+//
+// Example :
+//    int NumSv, Res;
+//    unsigned char HostBeeInfo[32];
+//    Res = MTK_Bee_Receive_Host_Info(NumSv, HostBeeInfo);
+//    if ( Res )
+//    {
+//        MTK_UART_OutputData("HOST BEE INFO OK");
+//    }
+//    else
+//    {
+//        MTK_UART_OutputData("HOST BEE INFO FAIL");
+//    }
+
+int MTK_Bee_Receive_Host_Info (int NumSv, unsigned char HostBeeInfo[32]);
+
+//********************************************************************************************************
+// MTK_Bee_Receive_End_Data  :  Receive end of BEE data transmission message from Host
+//
+// Description : The receiver stops checking which satellite needs BEE data after
+//               MTK_Bee_Receive_Host_Info() is called.
+//               The receiver will restart to check which satellite needs BEE data after
+//               MTK_Bee_Receive_End_Data() is called.
+//
+// Example :
+//    MTK_Bee_Receive_End_Data();
+//    MTK_UART_OutputData("BEE TRANSMISSION FINISH");
+
+void MTK_Bee_Receive_End_Data (void);
+
+//*****************************************************************************************************
+// MTK_Bee_Disable_BEE  :  Disable ALL BEE data
+//
+// Description  :  If no need using BEE data for generate fix, then
+//                 using MTK_Bee_Disable_BEE() to disable BEE data.
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( DISABLE_BEE ), then Disable BEE data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case DISABLE_BEE:
+//              MTK_Bee_Disable_BEE();
+//              break;
+//        ......
+//      }
+
+void MTK_Bee_Disable_BEE ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Enable_BEE  :  Enable ALL BEE data
+//
+// Description  :  If needed using BEE data for generate fix, then
+//                 using MTK_Bee_Enable_BEE() to enable BEE data.
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( ENABLE_BEE ), then Enable BEE data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case ENABLE_BEE:
+//              MTK_Bee_Enable_BEE();
+//              break;
+//        ......
+//      }
+
+void MTK_Bee_Enable_BEE ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Set_BEE  :  Set enable / disable BEE data for individual satellite
+//
+// Description : MTK_Bee_Set_BEE ( unsigned char EnableBEE[32] )
+//               EnableBEE -- Array with 32 unsigned char
+//               0  ---> Disable use of BEE data in the fix for this satellite
+//               1  ---> Enable use of BEE data in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( SET_BEE ), then Set enable / disable BEE data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case SET_BEE:
+//              unsigned char EnableBEE[32];
+//              EnableBEE[5] = 1;
+//              EnableBEE[12] = 0;
+//              EnableBEE[16] = 1;
+//              MTK_Bee_Set_BEE(EnableBEE);
+//              break;
+//        ......
+//      }
+//
+// =====> Enable  use BEE data of PRN 5, 16 in the fix
+//        Disable use BEE data of PRN 12    in the fix
+
+void MTK_Bee_Set_BEE ( unsigned char EnableBEE[32] );
+
+//*****************************************************************************************************
+// MTK_Bee_Disable_BRDC  :  Disable ALL BRDC data
+//
+// Description  :  If no need using BRDC data for generate fix, then
+//                 using MTK_Bee_Disable_BRDC() to disable BRDC data.
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( DISABLE_BRDC ), then Disable BRDC data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case DISABLE_BRDC:
+//              MTK_Bee_Disable_BRDC();
+//              break;
+//        ......
+//      }
+
+void MTK_Bee_Disable_BRDC ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Enable_BRDC  :  Enable ALL BRDC data
+//
+// Description  :  If needed using BRDC data for generate fix, then
+//                 using MTK_Bee_Enable_BRDC() to enable BRDC data.
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( ENABLE_BRDC ), then Enable BRDC data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case ENABLE_BRDC:
+//              MTK_Bee_Enable_BRDC();
+//              break;
+//        ......
+//      }
+
+void MTK_Bee_Enable_BRDC ( void );
+
+//*****************************************************************************************************
+// MTK_Bee_Set_BRDC  :  Set enable / disable BRDC data for individual satellite
+//
+// Description : MTK_Bee_Set_BRDC ( unsigned char EnableBRDC[32] )
+//               EnableBRDC -- Array with 32 unsigned char
+//               0  ---> Disable use of BRDC data in the fix for this satellite
+//               1  ---> Enable use of BRDC data in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( SET_BRDC ), then Set enable / disable BRDC data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case SET_BRDC:
+//              unsigned char EnableBRDC[32];
+//              EnableBRDC[5] = 1;
+//              EnableBRDC[12] = 0;
+//              EnableBRDC[16] = 1;
+//              MTK_Bee_Set_BRDC(EnableBRDC);
+//              break;
+//        ......
+//      }
+//
+// =====> Enable  use BRDC ephemeris of PRN 5, 16 in the fix
+//        Disable use BRDC ephemeris of PRN 12    in the fix
+
+void MTK_Bee_Set_BRDC ( unsigned char EnableBRDC[32] );
+
+
+//*****************************************************************************************************
+// MTK_Bee_Query_BRDC_Status  :  Query BRDC ephemeris status
+//
+// Description : MTK_Bee_Query_BRDC_Status ( unsigned char QueryBRDC[32] )
+//               QueryBRDC -- Array with 32 unsigned char
+//               0  ---> BRDC ephemeris is disable use in the fix for this satellite
+//               1  ---> BRDC ephemeris is enable  use in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( QUERY_BRDC ), then Query BRDC ephemeris
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case QUERY_BRDC:
+//              unsigned char QueryBRDC[32];
+//              MTK_Bee_Query_BRDC_Status(QueryBRDC);
+//              break;
+//        ......
+//      }
+//
+// =====> if QueryBRDC[5] = 1; QueryBRDC[19] = 0; QueryBRDC[25] = 1;
+//        BRDC ephemeris of PRN 5, 25 is enable use in the fix
+//        BRDC ephemeris of PRN 19    is disable use in the fix
+
+void MTK_Bee_Query_BRDC_Status ( unsigned char QueryBRDC[32] );
+
+
+//*****************************************************************************************************
+// MTK_Bee_Query_BEE_Status  :  Query BEE data status
+//
+// Description : MTK_Bee_Query_BRDC_Status ( unsigned char QueryBEE[32] )
+//               QueryBRDC -- Array with 32 unsigned char
+//               0  ---> BEE data is disable use in the fix for this satellite
+//               1  ---> BEE data is enable  use in the fix for this satellite
+//
+// Returns : NONE
+//
+// Example :
+//      Receive some special command( QUERY_BEE ), then Query BEE data
+//      UART_RECEIVE()
+//      {
+//        ......
+//        case QUERY_BEE:
+//              unsigned char QueryBEE[32];
+//              MTK_Bee_Query_BEE_Status(QueryBEE);
+//              break;
+//        ......
+//      }
+//
+// =====> if QueryBEE[5] = 1; QueryBEE[19] = 0; QueryBEE[25] = 1;
+//        BEE data of PRN 5, 25 is enable use in the fix
+//        BEE data of PRN 19    is disable use in the fix
+
+void MTK_Bee_Query_BEE_Status ( unsigned char QueryBEE[32] );
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_SDK_BEE_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Sys.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Sys.h
new file mode 100644
index 0000000..9d4bca0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Sys.h
@@ -0,0 +1,263 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+//*****************************************************************************
+// [File] MTK_Sys.h
+// [Version] v1.0
+// [Revision Date] 2008-03-31
+// [Author] YC Chien, yc.chien@mediatek.com, 21558
+// [Description] Define the prototypes of operating system dependent functions
+//*****************************************************************************
+
+#ifndef MTK_SYS_H
+#define MTK_SYS_H
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+#include "MTK_Type.h"
+
+//#define BEE_HEAP_DEBUG
+
+//*****************************************************************************
+// Semaphore Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_Init_Smphr : Initial semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be initizlized
+//
+// RETURN : void
+
+void MTK_Sys_Init_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Delete_Smphr : Delete semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be deleted
+//
+// RETURN : void
+
+void MTK_Sys_Delete_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Reserve_Smphr : Reserve semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to reserve
+//
+// RETURN : void
+
+void MTK_Sys_Reserve_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Release_Smphr : Release semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to release
+//
+// RETURN : void
+
+void MTK_Sys_Release_Smphr (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Init_Smphr_For_EPO : Initial semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be initizlized
+//
+// RETURN : void
+
+void MTK_Sys_Init_Smphr_For_EPO (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Delete_Smphr_For_EPO : Delete semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to be deleted
+//
+// RETURN : void
+
+void MTK_Sys_Delete_Smphr_For_EPO(MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Reserve_Smphr_For_EPO : Reserve semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to reserve
+//
+// RETURN : void
+
+void MTK_Sys_Reserve_Smphr_For_EPO (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// MTK_Sys_Release_Smphr_For_EPO : Release semaphore
+//
+// PARAMETER : u4SmphrNum [IN] - semaphore number to release
+//
+// RETURN : void
+
+void MTK_Sys_Release_Smphr_For_EPO (MTK_UINT32 u4SmphrNum);
+
+
+//*****************************************************************************
+// Memory Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_Memory_Alloc : Allocate a block of memory
+//
+// PARAMETER : u4Size [IN] - size of memory (bytes) to be allocated
+//
+// RETURN : On success, return the pointer to the allocated memory
+//          If fail, return NULL
+
+void* MTK_Sys_Memory_Alloc (MTK_UINT32 u4Size);
+
+
+//*****************************************************************************
+// MTK_Sys_Memory_Free : Deallocate memory previosly allocated by MTK_Sys_Memory_Alloc()
+//
+// PARAMETER : pMemory [IN] - pointer to memory to be freed
+//
+// RETURN : void
+
+void MTK_Sys_Memory_Free (void *pMemory);
+
+
+//*****************************************************************************
+// File Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_File_Open : Open a file
+//
+// PARAMETER : szFileName [IN] - name of the file to be opened
+//             i4Mode     [IN] - file access mode (read / write / read + write)
+//                               0 -- open file for reading (r)
+//                               1 -- create file for writing,
+//                                    discard previous contents if any (w)
+//                               2 -- open or create file for writing at end of file (a)
+//                               3 -- open file for reading and writing (r+)
+//                               4 -- create file for reading and writing,
+//                                    discard previous contents if any (w+)
+//                               5 -- open or create file for reading and writing at end of file (a+)
+//
+// NOTE : For system which treats binary mode and text mode differently,
+//        such as Windows / DOS, please make sure to open file in BINARY mode
+//
+// RETURN : On success, return the file handle
+//          If fail, return 0
+
+MTK_FILE MTK_Sys_File_Open (const char *szFileName, MTK_INT32 i4Mode);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Close : Close a file
+//
+// PARAMETER : hFile [IN] - handle of file to be closed
+//
+// RETURN : void
+
+void MTK_Sys_File_Close (MTK_FILE hFile);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Read : Read a block of data from file
+//
+// PARAMETER : hFile    [IN]  - handle of file
+//             DstBuf   [OUT] - pointer to data buffer to be read
+//             u4Length [IN]  - number of bytes to read
+//
+// RETURN : Number of bytes read
+
+MTK_UINT32 MTK_Sys_File_Read (MTK_FILE hFile, void *DstBuf, MTK_UINT32 u4Length);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Write : Write a block of data from file
+//
+// PARAMETER : hFile    [IN] - handle of file
+//             SrcBuf   [IN] - pointer to data buffer to be written
+//             u4Length [IN] - number of bytes to write
+//
+// RETURN : Number of bytes written
+
+MTK_UINT32 MTK_Sys_File_Write (MTK_FILE hFile, void *SrcBuf, MTK_UINT32 u4Length);
+
+
+//*****************************************************************************
+// MTK_Sys_File_Seek : Set the position indicator associated with file handle
+//                     to a new position defined by adding offset to a reference
+//                     position specified by origin
+//
+// PARAMETER : hFile    [IN] - handle of file
+//             u4OffSet [IN] - number of bytes to offset from origin
+//             u4Origin [IN] - position from where offset is added
+//                             0 -- seek from beginning of file
+//                             1 -- seek from current position
+//                             2 -- seek from end of file
+//
+// RETURN : On success, return a zero value
+//          Otherwise, return a non-zero value
+
+MTK_INT32 MTK_Sys_File_Seek (MTK_FILE hFile, MTK_UINT32 u4OffSet, MTK_UINT32 u4Origin);
+
+//*****************************************************************************
+// MTK_Sys_Debug_Output : Output debug messages of HotStill library
+//                        Porting layer can help to log on file
+//                        or sent by other interfaces
+//
+// PARAMETER : buffer [IN] - data pointer
+//             length [IN] - size of data
+//
+// RETURN : On success, return a zero value
+//          Otherwise, return a non-zero value
+
+MTK_BEE_INT MTK_Sys_Debug_Output (char* buffer, unsigned int length);
+
+
+//*****************************************************************************
+// Time Functions
+//*****************************************************************************
+
+//*****************************************************************************
+// MTK_Sys_Time : Get the current system time
+//
+// PARAMETER : pUTCTime [OUT] - UTC time
+//
+// RETURN : Success (MTK_TRUE) or Fail (MTK_FAIL)
+
+MTK_BOOL MTK_Sys_Time (MTK_TIME *pUTCTime);
+
+/*****************************************************************************
+ * FUNCTION
+ *  MTK_Sys_Get_EPO_File_Size
+ * DESCRIPTION
+ *  Get the file size
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  File size
+ *****************************************************************************/
+MTK_UINT32 MTK_Sys_Get_EPO_File_Size(MTK_FILE hFile);
+
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_SYS_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Type.h b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Type.h
new file mode 100644
index 0000000..b704863
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/MTK_Type.h
@@ -0,0 +1,101 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+//*****************************************************************************
+// [File] MTK_Type.h
+// [Version] v1.0
+// [Revision Date] 2008-03-31
+// [Author] YC Chien, yc.chien@mediatek.com, 21558
+// [Description]
+//*****************************************************************************
+
+#ifndef MTK_TYPE_H
+#define MTK_TYPE_H
+
+
+typedef unsigned char           MTK_UINT8;
+typedef signed char             MTK_INT8;
+
+typedef unsigned short int      MTK_UINT16;
+typedef signed short int        MTK_INT16;
+
+typedef unsigned int            MTK_UINT32;
+typedef signed int              MTK_INT32;
+
+typedef unsigned long           MTK_UINT64;
+typedef signed long             MTK_INT64;
+
+
+typedef enum
+{
+    MTK_FALSE = 0,
+    MTK_TRUE = 1
+}   MTK_BOOL;
+
+typedef unsigned long MTK_FILE;
+
+typedef enum
+{
+    MTK_FS_READ = 0,     // open file for reading (r)
+    MTK_FS_WRITE,        // create file for writing, discard previous contents if any (w)
+    MTK_FS_APPEND,       // open or create file for writing at end of file (a)
+    MTK_FS_RW,           // open file for reading and writing (r+)
+    MTK_FS_RW_DISCARD,   // create file for reading and writing, discard previous contents if any (w+)
+    MTK_FS_RW_APPEND     // open or create file for reading and writing at end of file (a+)
+}   MTK_FMODE;
+
+typedef enum
+{
+    MTK_FS_SEEK_SET = 0, // seek from beginning of file
+    MTK_FS_SEEK_CUR,     // seek from current position
+    MTK_FS_SEEK_END      // seek from end of file
+}   MTK_FSEEK;
+
+typedef struct _MTK_TIME
+{
+    MTK_UINT16  Year;
+    MTK_UINT16  Month;
+    MTK_UINT16  Day;
+    MTK_UINT16  Hour;
+    MTK_UINT16  Min;
+    MTK_UINT16  Sec;
+    MTK_UINT16  Msec;
+}   MTK_TIME;
+
+typedef enum
+{
+  HSDBGT_INIT = 0,
+  HSDBGT_LIB,
+  HSDBGT_KER,
+  HSDBGT_CAL,
+  HSDBGT_SYS,
+  HSDBGT_COMM,
+  HSDBGT_MSG,
+  HSDBGT_STR,
+  HSDBGT_MEM,
+  HSDBGT_ALL,
+  HSDBGT_END
+} MTK_DEBUG_TYPE;
+
+typedef enum
+{
+  HSDBGL_NONE = 0,
+  HSDBGL_ERR,
+  HSDBGL_WRN,
+  HSDBGL_INFO1,
+  HSDBGL_END
+} MTK_DEBUG_LEVEL;
+
+#define MTK_BEE_VOID void
+#define MTK_BEE_INT int
+
+#endif /* MTK_TYPE_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/SUPL_encryption.h b/src/connectivity/gps/mtk_mnld/mnl/inc/SUPL_encryption.h
new file mode 100644
index 0000000..dc79a90
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/SUPL_encryption.h
@@ -0,0 +1,32 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   SUPL_encryption.h
+ *
+ * Description:
+ * ------------
+ *   Prototype of encryption/decryption function for SUPL PMTK command
+ *
+ ****************************************************************************/
+
+#ifndef SUPL_ENCRYPTION_H
+#define SUPL_ENCRYPTION_H
+
+int SUPL_encrypt(unsigned char *plain, unsigned char *cipher, unsigned int length);
+int SUPL_decrypt(unsigned char *plain, unsigned char *cipher, unsigned int length);
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/agps_agent.h b/src/connectivity/gps/mtk_mnld/mnl/inc/agps_agent.h
new file mode 100644
index 0000000..c3f4edd
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/agps_agent.h
@@ -0,0 +1,331 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   agps_agent.h
+ *
+ * Description:
+ * ------------
+ *   Prototype of MTK AGPS Agent related functions
+ *
+ ****************************************************************************/
+
+#ifndef MTK_AGPS_AGENT_H
+#define MTK_AGPS_AGENT_H
+
+
+#if defined(WIN32) || defined(WINCE)
+#include "windows.h"
+#else
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#endif
+#include "mtk_gps_type.h"
+#include "MTK_Type.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/* Copy required parameters from MNL internal header files.
+   Remember to sync with MNL when any of these are changed. */
+
+#define PMTK_MAX_PKT_LENGTH     256
+#define MGlONID  (24)
+
+// message between mnl and agps agent
+#define MTK_GPS_EVENT_BASE          (0)
+#define MTK_GPS_MSG_BASE            (MTK_GPS_EVENT_BASE+500)
+#define MTK_GPS_MNL_MSG             (MTK_GPS_MSG_BASE+1) //msg to mnl
+#define MTK_GPS_MNL_EPO_MSG         (MTK_GPS_MSG_BASE+2) //msg to agent epo module
+#define MTK_GPS_MNL_BEE_MSG         (MTK_GPS_MSG_BASE+3) //msg to agent bee module
+#define MTK_GPS_MNL_SUPL_MSG        (MTK_GPS_MSG_BASE+4) //msg to agent supl module
+//#define MTK_GPS_MNL_EPO_MSG         (MTK_GPS_MSG_BASE+5) //msg to agent epo module
+#define MTK_GPS_MNL_BEE_IND_MSG         (MTK_GPS_MSG_BASE+6) //msg to agent bee module
+//#define MTK_GPS_MNL_SUPL_MSG        (MTK_GPS_MSG_BASE+7) //msg to agent supl module
+
+#define AGPS_AGENT_DEBUG
+
+//agps state machine
+#define AGENT_ST_IDLE     (0)
+#define AGENT_ST_WORKING  (1)
+
+#define AGENT_WORK_MODE_IDLE          (0)
+#define AGENT_WORK_MODE_EPO           (1)
+#define AGENT_WORK_MODE_BEE           (2)
+#define AGENT_WORK_MODE_SUPL_SI       (3)
+#define AGENT_WORK_MODE_SUPL_NI       (4)
+#define AGENT_WORK_MODE_WIFI_AIDING   (5)
+#define AGENT_WORK_MODE_CELLID_AIDING (6)
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_agent_init
+ * DESCRIPTION
+ *  Initialize AGPS Agent module
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_init(UINT32 u4Param);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_proc
+ * DESCRIPTION
+ *  process the message recv. from agps agent thread
+ * PARAMETERS
+ *  prmsg       [IN]   the message recv. from agps agent thread
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_proc (MTK_GPS_AGPS_AGENT_MSG *prmsg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_epo_init
+ * DESCRIPTION
+ *  Initialize EPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_init(UINT8 *epo_file_name, UINT8 *epo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_epo_uninit
+ * DESCRIPTION
+ *  Un-initialize EPO module
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_uninit();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_init
+ * DESCRIPTION
+ *  Initialize QEPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_init(UINT8 *qepo_file_name, UINT8 *qepo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_uninit
+ * DESCRIPTION
+ *  Un-initialize QEPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_uninit();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_bd_init
+ * DESCRIPTION
+ *  Initialize QEPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_bd_init(UINT8 *qepo_file_name, UINT8 *qepo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_bd_uninit
+ * DESCRIPTION
+ *  Un-initialize QEPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_bd_uninit();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_ga_init
+ * DESCRIPTION
+ *  Initialize QEPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_ga_init(UINT8 *qepo_file_name, UINT8 *qepo_update_file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_ga_uninit
+ * DESCRIPTION
+ *  Un-initialize QEPO module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_ga_uninit();
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_epo_read_gps_time
+ * DESCRIPTION
+ *    Get start time/expire time of the EPO file [gps time]
+ * PARAMETERS
+ *  pFile: EPO file fd
+ *  [out]u4GpsSecs: GPS seconds
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_read_gps_time(UINT32 *u4GpsSecs_start, UINT32 *u4GpsSecs_expire);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_epo_read_utc_time
+ * DESCRIPTION
+ *    Get start time/expire time of the EPO file [utc time]
+ * PARAMETERS
+ *  pFile: EPO file fd
+ *  [out]u4GpsSecs: GPS seconds
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_read_utc_time(time_t *uSecond_start, time_t *uSecond_expire);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_epo_extract_data
+ * DESCRIPTION
+ *    Extract ading data from EPO file
+ * PARAMETERS
+ *  [IN]u4GpsSec: segment time
+ *  [out]epo_data: ading data
+ * RETURNS
+ * success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_extract_data(UINT32 u4GpsSecs, MTK_GPS_PARAM_EPO_DATA_CFG *epo_data);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_epo_file_update
+ * DESCRIPTION
+ *    Update the EPO file after the new Epo file download
+ * PARAMETERS
+ *      None
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_epo_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_file_update
+ * DESCRIPTION
+ *    Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ *      None
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_bd_file_update
+ * DESCRIPTION
+ *    Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ *      None
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_bd_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_ga_file_update
+ * DESCRIPTION
+ *    Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ *      None
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_ga_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_get_rqst_time
+ * DESCRIPTION
+ *    Get the GPS time and system time of the latest QEPO request
+ * PARAMETERS
+ *      wn  [OUT]:The week number of GPS time
+ *      tow [OUT]:The Time Of Week of GPS time
+ *      sys_time    [OUT]:The system time of the latest QEPO request, the unit is second
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_agps_agent_qepo_get_rqst_time(UINT16 *wn, UINT32 *tow, UINT32 *sys_time);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_file_verify
+
+ *****************************************************************************/
+
+INT32
+mtk_agps_agent_qepo_file_verify(MTK_FILE hFile, UINT8 *qepo_type, INT64 *file_size);
+
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps.h
new file mode 100644
index 0000000..244dce2
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps.h
@@ -0,0 +1,2280 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   mtk_gps.h
+ *
+ * Description:
+ * ------------
+ *   Prototype of MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_H
+#define MTK_GPS_H
+
+#include "mtk_gps_type.h"
+#include "mtk_gps_agps.h"
+
+#include "mtk_gps_driver_wrapper.h"
+#ifdef USING_NAMING_MARC
+#include "mtk_gps_macro.h"
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+/* ================= Application layer functions ================= */
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_run
+ * DESCRIPTION
+ *  The main routine for the MTK Nav Library task
+ * PARAMETERS
+ *  application_cb      [IN]
+ *  default_cfg(mtk_init_cfg)       [IN]
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_run(MTK_GPS_CALLBACK application_cb, const MTK_GPS_INIT_CFG* default_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_hotstill_run
+ * DESCRIPTION
+ *  The main routine for the HotStill task
+ * PARAMETERS
+  *  driver_cfg     [IN]  factory default configuration
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_hotstill_run(MTK_GPS_DRIVER_CFG* driver_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_agent_run
+ * DESCRIPTION
+ *  The main routine for the Agent task
+ * PARAMETERS
+  *  driver_cfg     [IN]  factory default configuration
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_agent_run(MTK_GPS_DRIVER_CFG* driver_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_update_gps_data
+ * DESCRIPTION
+ *  Force to write NV-RAM data to storage file
+ * PARAMETERS
+ *
+ * RETURNS
+ *  None
+ *****************************************************************************/
+INT32
+mtk_gps_update_gps_data(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_data_input
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *  buffer      [IN] the content of the gps measuremnt
+ *  length      [IN] the length of the gps measurement
+ *  p_accepted_length [OUT]  indicate how many data was actually accepted into library
+ *                          if this value is not equal to length, then it means library internal
+ *                          fifo is full, please let library task can get cpu usage to digest input data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_data_input(const char* buffer, UINT32 length, UINT32* p_accepted_length);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_rtcm_input
+ * DESCRIPTION
+ *  accept RTCM differential correction data
+ * PARAMETERS
+ *  buffer      [IN]   the content of RTCM data
+ *  length      [IN]   the length of RTCM data(no more than 1KB)
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_rtcm_input(const char* buffer, UINT32 length);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_nmea_input
+ * DESCRIPTION
+ *  accept NMEA(PMTK) sentence raw data
+ * PARAMETERS
+ *  buffer      [IN]   the content of NMEA(PMTK) data
+ *  length      [IN]   the length of NMEA(PMTK) data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_nmea_input(const char* buffer, UINT32 length);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_agps_input
+ * DESCRIPTION
+ *  accept NMEA(PMTK) sentence raw data(only for agent using)
+ * PARAMETERS
+ *  buffer      [IN]   the content of NMEA(PMTK) data
+ *  length      [IN]   the length of NMEA(PMTK) data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_agps_input(const char* buffer, UINT32 length);
+
+
+/* ====================== Utility functions ====================== */
+/*  These functions must be used in application_cb() callback
+    function specified in mtk_gps_run()                            */
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_position
+ * DESCRIPTION
+ *  obtain detailed fix information
+ * PARAMETERS
+ *  pvt_data    [OUT]  pointer to detailed fix information
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_position(MTK_GPS_POSITION* pvt_data);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_sv_info
+ * DESCRIPTION
+ *  obtain detailed information of all satellites for GPS/QZSS
+ * PARAMETERS
+ *  sv_data     [OUT]  pointer to satellites information
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_sv_info(MTK_GPS_SV_INFO* sv_data);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_gleo_sv_info
+ * DESCRIPTION
+ *  obtain detailed information of all satellites for GALIILEO
+ * PARAMETERS
+ *  sv_data     [OUT]  pointer to satellites information
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_gleo_sv_info(MTK_GLEO_SV_INFO* sv_gleo_data);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_glon_sv_info
+ * DESCRIPTION
+ *  obtain detailed information of all satellites for GALIILEO
+ * PARAMETERS
+ *  sv_data     [OUT]  pointer to satellites information
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_glon_sv_info(MTK_GLON_SV_INFO* sv_glon_data);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_bedo_sv_info
+ * DESCRIPTION
+ *  obtain detailed information of all satellites for GALIILEO
+ * PARAMETERS
+ *  sv_data     [OUT]  pointer to satellites information
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_bedo_sv_info(MTK_BEDO_SV_INFO* sv_bedo_data);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_param
+ * DESCRIPTION
+ *  Get the current setting of the GPS receiver
+ * PARAMETERS
+ *  key         [IN]   the configuration you want to know
+ *  value       [OUT]  the current setting
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * EXAMPLE
+ *  //  get the current DGPS mode
+ *  mtk_param_dgps_config param_dgps_config;
+ *  mtk_gps_get_param(MTK_PARAM_DGPS_CONFIG, &param_dgps_config);
+ *  printf("DGPS mode=%d",(int)param_dgps_config.dgps_mode);
+ *****************************************************************************/
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_sv_list
+ * DESCRIPTION
+ *  Return SV list(Elev >= 5)
+ * PARAMETERS
+ *   *UINT32 SV list bit map
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_sv_list(UINT32 *svListBitMap);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_param
+ * DESCRIPTION
+ *  Get the current setting of the GPS receiver
+ * PARAMETERS
+ *  key         [IN]   the configuration you want to know
+ *  value       [OUT]  the current setting
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * EXAMPLE
+ *  //  get the current DGPS mode
+ *  mtk_param_dgps_config param_dgps_config;
+ *  mtk_gps_get_param(MTK_PARAM_DGPS_CONFIG, &param_dgps_config);
+ *  printf("DGPS mode=%d",(int)param_dgps_config.dgps_mode);
+ *****************************************************************************/
+INT32
+mtk_gps_get_param(MTK_GPS_PARAM key, void* value);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_param
+ * DESCRIPTION
+ *  Change the behavior of the GPS receiver
+ * PARAMETERS
+ *  key         [IN]   the configuration needs to be changed
+ *  value       [IN]   the new setting
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_param(MTK_GPS_PARAM key, const void* value);
+INT32
+mtk_gps_get_mnl_info(MTK_GPS_MNL_INFO* lib_info);
+
+//****************************************************************************
+// mtk_gps_set_nmea_format : Set NMEA format
+//
+// Parameters:
+//  Mode = 0 : NMEA show as normal
+//  Mode = 1 : NMEA show
+//                       $GPGGA,,,,,,0,,,,,,,,*66
+//                       $GPVTG,,T,,M,,N,,K,N*2C
+//                       $GPRMC,,V,,,,,,,,,,N*53
+//  Mode > 1 : Reserved
+//
+//
+// Description :
+//    show different GGA/VTF/RMC format when GNSS in no-fix status
+//
+UINT8 mtk_gps_set_nmea_format(UINT8 *NMEA_format);
+
+// *****************************************************************************
+//  mtk_gps_set_navigation_speed_threshold :
+//  The function will keep fix the postion output to the same point if the current
+//  estimated 3D speed is less than SpeedThd or the distance of true position and the fix points
+//  are large than 20 meter.
+//  Parameters :
+//               SpeedThd must be >= 0
+//               The unit of SpeedThd is [meter/second]
+//               if SpeedThd = 0,  The navigation speed threshold function will be disabled.
+//  For exapmle,
+//  The fix points will keep to the same points until estimated speed is large than 0.4m/s
+//
+//  float SpeedThd = 0.4;
+//  MTK_Set_Navigation_Speed_Threshold(SpeedThd);
+//
+
+INT32
+mtk_gps_set_navigation_speed_threshold(float SpeedThd);
+
+// *****************************************************************************
+//  mtk_gps_get_navigation_speed_threshold :
+//  Query the current Static Navigation Speed Threshold
+//  Parameters :  The unit of SpeedThd  is [meter/second]
+//  if SpeedThd = 0, The navigation speed threshold is not functional.
+
+INT32
+mtk_gps_get_navigation_speed_threshold(float *SpeedThd);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_pmtk_data
+ * DESCRIPTION
+ *  send PMTK command to GPS receiver
+ * PARAMETERS
+ *  prPdt       [IN]   pointer to the data structure of the PMTK command
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_pmtk_data(const MTK_GPS_PMTK_DATA_T *prPdt);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_pmtk_response
+ * DESCRIPTION
+ *  obtain detailed information of PMTK response
+ * PARAMETERS
+ *  rs_data     [OUT]  pointer to PMTK response data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_pmtk_response(MTK_GPS_PMTK_RESPONSE_T *prRsp);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_position
+ * DESCRIPTION
+ *  Set the receiver's initial position
+ *  Notes: To make the initial position take effect, please invoke restart
+ *        (hot start/warm start) after this function
+ * PARAMETERS
+ *  LLH         [IN]  LLH[0]: receiver latitude in degrees(positive for North)
+ *                    LLH[1]: receiver longitude in degrees(positive for East)
+ *                    LLH[2]: receiver WGS84 height in meters
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_position(const double LLH[3]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_time
+ * DESCRIPTION
+ *  Set the current GPS time
+ *  Note:       The time will not be set if the receiver has better knowledge
+ *              of the time than the new value.
+ * PARAMETERS
+ *  weekno      [IN]   GPS week number(>1024)
+ *  TOW         [IN]   time of week(in second; 0.0~684800.0)
+ *  timeRMS     [IN]   estimated RMS error of the TOW value(sec^2)
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_time(UINT16 weekno, double tow, float timeRMS);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_ephemeris
+ * DESCRIPTION
+ *  Upload ephemeris
+ * PARAMETERS
+ *  svid        [IN]   GPS satellite PRN(1~32)
+ *  data        [IN]   binary ephemeris words from words 3-10 of subframe 1-3
+ *                     all parity bits(bit 5-0) have been removed
+ *                     data[0]: bit 13-6 of word 3, subframe 1
+ *                     data[1]: bit 21-14 of word 3, subframe 1
+ *                     data[2]: bit 29-22 of word 3, subframe 1
+ *                     data[3]: bit 13-6 of word 4, subframe 1
+ *                     ......
+ *                     data[71]: bit 29-22 of word 10, subframe 3
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_ephemeris(UINT8 svid, const char data[72]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_tcxo_mode
+ * DESCRIPTION
+ *  Set MNL TCXO mode
+ * PARAMETERS
+ *
+
+ *  MTK_TCXO_NORMAL,  // normal mode
+ *  MTK_TCXO_PHONE    // phone mode
+
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_set_tcxo_mode(MTK_GPS_TCXO_MODE tcxo_mode);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_AIC_mode
+ * DESCRIPTION
+ *  Set AIC mode
+ * PARAMETERS
+ *
+ * disalbe = 0
+ * enable = 1
+
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_set_AIC_mode(MTK_GPS_AIC_MODE AIC_Enable);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_almanac
+ * DESCRIPTION
+ *  Upload almanac
+ * PARAMETERS
+ *  svid        [IN]   GPS satellite PRN(1~32)
+ *  weekno      [IN]   the week number of the almanac data record
+ *  data        [IN]   binary almanac words from words 3-10 of either subframe 4
+ *                     pages 2-10 or subframe 5 pages 1-24
+ *                     all parity bits(bit 5-0) have been removed
+ *                     data[0]: bit 13-6 of word 3
+ *                     data[1]: bit 21-14 of word 3
+ *                     data[2]: bit 29-22 of word 3
+ *                     data[3]: bit 13-6 of word 4
+ *                     ......
+ *                     data[23]: bit 29-22 of word 10
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_almanac(UINT8 svid, UINT16 weekno, const char data[24]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_ephemeris
+ * DESCRIPTION
+ *  Download ephemeris
+ * PARAMETERS
+ *  svid        [IN]   GPS satellite PRN(1~32)
+ *  data        [OUT]  binary ephemeris words from words 3-10 of subframe 1-3
+ *                     all parity bits(bit 5-0) have been removed
+ *                     data[0]: bit 13-6 of word 3, subframe 1
+ *                     data[1]: bit 21-14 of word 3, subframe 1
+ *                     data[2]: bit 29-22 of word 3, subframe 1
+ *                     data[3]: bit 13-6 of word 4, subframe 1
+ *                     ......
+ *                     data[71]: bit 29-22 of word 10, subframe 3
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_ephemeris(UINT8 svid, char data[72]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_almanac
+ * DESCRIPTION
+ *  Download almanac
+ * PARAMETERS
+ *  svid        [IN]   GPS satellite PRN(1~32)
+ *  p_weekno    [OUT]  pointer to the week number of the almanac data record
+ *  data        [OUT]  binary almanac words from words 3-10 of either subframe 4
+ *                     pages 2-10 or subframe 5 pages 1-24
+ *                     all parity bits(bit 5-0) have been removed
+ *                     data[0]: bit 13-6 of word 3
+ *                     data[1]: bit 21-14 of word 3
+ *                     data[2]: bit 29-22 of word 3
+ *                     data[3]: bit 13-6 of word 4
+ *                     ......
+ *                     data[23]: bit 29-22 of word 10
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_almanac(UINT8 svid, UINT16* p_weekno, char data[24]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_assist_bitmap
+ * DESCRIPTION
+ *  Set assist(EPH/ALM) bitmap
+ * PARAMETERS
+ *  UINT8 AssistBitMap
+ *     If you want EPH assist data, please set AssistBitMap to 0x08
+ *     If you want ALM assist data, please set AssistBitMap to 0x01
+ *     If you want EPH and ALM assist data, please set AssistBitMap to 0x09
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_assist_bitmap(UINT16 AssistBitMap);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_assist_bitmap
+ * DESCRIPTION
+ *  Get Re-aiding assist(EPH/ALM) bitmap
+ * PARAMETERS
+ *  uint8* pAssistBitMap
+ *     Get current Re-aiding assist bitmap
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_assist_bitmap(UINT16 *pAssistBitMap);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_clear_ephemeris
+ * DESCRIPTION
+ *  clear the ephemeris of the specified PRN
+ * PARAMETERS
+ *  svid        [IN]   GPS satellite PRN(1~32)
+ *****************************************************************************/
+void
+mtk_gps_clear_ephemeris(UINT8 svid);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_clear_almanac
+ * DESCRIPTION
+ *  clear the almanac of the specified PRN
+ * PARAMETERS
+ *  svid        [IN]   GPS satellite PRN(1~32)
+ *****************************************************************************/
+void
+mtk_gps_clear_almanac(UINT8 svid);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_sbas_msg_amount
+ * DESCRIPTION
+ *  Get the number of SBAS message blocks received in this epoch.
+ *  Later on, please use mtk_gps_get_sbas_msg() to get the message
+ *  content one by one.
+ * PARAMETERS
+ *  p_msg_amount  [OUT]   The number of SBAS message blocks received in this epoch
+ * RETURNS
+ *
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_sbas_msg_amount(UINT32* p_msg_amount);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_sbas_msg
+ * DESCRIPTION
+ *  After calling mtk_gps_get_sbas_msg_amount(), we know the
+ *  number of SBAS messages received in this epoch.
+ *  mtk_gps_get_sbas_msg() gives a way to access each message
+ *  data
+ * PARAMETERS
+ *  index        [IN]   which message you want to read
+ *  pSVID        [OUT]  the PRN of the SBAS satellite
+ *  pMsgType     [OUT]  the SBAS message type
+ *  pParityError [OUT]  nonzero(parity error); zero(parity check pass)
+ *  data         [OUT]  The 212-bit message data excluding the preamble,
+ *                      message type field, and the parity check.
+ *                      Regarding to endian, the data[0] is the beginning the
+ *                      message, such as IODP field. The data[26] is the end of
+ *                      message, and the bit 3..0 are padding zero.
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ * EXAMPLE
+ *   // dump the SBAS message to UART output
+ *   int  i, count;
+ *   unsigned char PRN, MsgType, ParityError;
+ *   char data[27];
+ *
+ *   mtk_gps_get_sbas_msg_amount(&count);
+ *   for(i = 0; i < count; i++)
+ *   {
+ *      mtk_gps_get_sbas_msg(i, &PRN, &MsgType, &ParityError, data);
+ *   }
+ *****************************************************************************/
+INT32
+mtk_gps_get_sbas_msg(INT32 index, unsigned char* pSVID,
+     unsigned char* pMsgType, unsigned char* pParityError, char data[27]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_cn0_test
+ * DESCRIPTION
+ *  Get Channel CNR and in CN0 test mode
+ * PARAMETERS
+ *  ChnSNR       [OUT]  Channel SNR
+ *  PRN[0]: GPS PRN 1
+ *  PRN[1]: GPS PRN 2
+ *  PRN[2]: GLO PRN 8
+ *  PRN[3]: BDS PRN 6
+ *  PRN[4]: BDS PRN 7
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *  if you do not enter test mode first or Channel tracking not ready,
+ *  return MTK_GPS_ERROR
+ *****************************************************************************/
+
+INT32
+mtk_gps_get_cn0_test(INT32 SVID[5],INT32 SV_type[5],INT32 ChnSNR[5]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_cn0_test_CW
+ * DESCRIPTION
+ *  Get Channel CNR and Doppler in CN0 test mode
+ * PARAMETERS
+ *  ChnSNR       [OUT]  Channel SNR
+ *  PRN[0]: GPS PRN 1
+ *  PRN[1]: GPS PRN 2
+ *  PRN[2]: GLO PRN 8
+ *  PRN[3]: BDS PRN 6
+ *  PRN[4]: BDS PRN 7
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *  if you do not enter test mode first or Channel tracking not ready,
+ *  return MTK_GPS_ERROR
+ *****************************************************************************/
+
+INT32
+mtk_gps_get_cn0_test_CW(INT32 PRN[5],INT32 SV_type[5],INT32 ChnSNR[5],INT32 Doppler[5]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_chn_status
+ * DESCRIPTION
+ *  Get Channel SNR and Clock Drift Status in Channel Test Mode
+ * PARAMETERS
+ *  ChnSNR       [OUT]  Channel SNR
+ *  ClkDrift     [OUT]  Clock Drift
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *  if you do not enter test mode first or Channel tracking not ready,
+ *  return MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_gps_get_chn_test(float ChnSNR[16], float *ClkDrift);
+
+
+
+/****************************************************************************
+* FUNCTION
+*mtk_gps_D2_Set_Enable
+*DESCRIPTION
+* Bediou D2 data Enable/Disable functions
+*PARAMETERS
+* UsedD2Corr =1, Enable D2 correction data.
+* UsedD2Corr =0, Disable D2 correction data.
+*RETURNS
+* None
+ *****************************************************************************/
+
+void mtk_gps_D2_Set_Enable(unsigned char bUsedD2Corr);
+
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_glonass_chn_status
+ * DESCRIPTION
+ *  Get Channel SNR and Clock Drift Status in Channel Test Mode
+ * PARAMETERS
+ *  ChnSNR       [OUT]  Channel SNR
+ *  ClkDrift     [OUT]  Clock Drift
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *  if you do not enter test mode first or Channel tracking not ready,
+ *  return MTK_GPS_ERROR
+ *****************************************************************************/
+INT32
+mtk_gps_get_glonass_chn_test(float ChnSNR[3]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_jammer_test
+ * DESCRIPTION
+ *  Obtain the CW jammer estimation result
+ * PARAMETERS
+ *  Freq         [OUT]  jammer frequency offset in KHz
+ *  JNR          [OUT]  JNR of the associated jammer
+ *  jammer_peaks [OUT]  The number(0~195) of jammer peaks if ready
+ *                      0 means no jammer detected
+ *                      Negative if not ready
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_jammer_test(INT32 *jammer_peaks, short Freq[195], UINT16 JNR[195]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_jammer_test
+ * DESCRIPTION
+ *  Enter or leave Jammer Test Mode
+ * PARAMETERS
+ *  action [IN]   1 = enter Jammer test(old); 2 = enter Jammer test(new); 0 = leave Jammer test
+ *  SVid [IN] please assign any value between 1~32
+ *  range [IN] no use in new jammer scan, any value is ok.
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+*****************************************************************************/
+INT32
+mtk_gps_set_jammer_test(INT32 action, UINT16 mode, UINT16 arg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_gnss_jammer_test
+ * DESCRIPTION
+ *   Enter or leave Jammer Test Mode
+ * PARAMETERS
+ *  action       [IN]   1 = enter Jammer test; 0 = leave Jammer test, not ready
+ *  mode         [IN]   0 = GPS; 1 = GLONASS ;2 = Beidou
+ *  arg          [IN]   unused
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_gnss_jammer_test(INT32 action, UINT16 mode, UINT16 arg);
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_phase_test
+ * DESCRIPTION
+ *  Obtain the last phase error calibration result
+ * PARAMETERS
+ *  result       [OUT]  0~64(success)
+ *                      Negative(failure or not ready)
+ *                      The return value is 64*{|I|/sqrt(I*I + Q*Q)}
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_phase_test(INT32 *result);
+
+
+// *************************************************************************************
+//  mtk_gps_get_sat_accurate_snr  :  Get the accurate SNR of all satellites
+//
+//     Note  :  SNR is an array with 32 float.
+//  Example:
+//     float SNR[32];
+//     mtk_gps_get_sat_accurate_snr(SNR);
+//     // Get SNR of SV 17
+//     MTK_UART_OutputData("SV17: SNR = %lf", SNR[16]);
+//
+//  =====> SV17: SNR = 38.1
+
+void mtk_gps_get_sat_accurate_snr(float SNR[32]);
+
+
+// *************************************************************************************
+//  mtk_gps_get_glon_sat_accurate_snr  :  Get the accurate SNR of all GLONASS satellites
+//
+//     Note  :  SNR is an array with [24] float.
+//  Example:
+//     float SNR[24];
+//     mtk_gps_get_glon_sat_accurate_snr(SNR);
+//     // Get SNR of SV 1
+//     MTK_UART_OutputData("GLON,SV1: SNR = %lf", SNR[0]);
+//
+//  =====>GLON,SV1: SNR = 38.1
+
+void mtk_gps_get_glon_sat_accurate_snr(float ASNR[24]);
+
+
+// *************************************************************************************
+//  mtk_gps_get_bd_sat_accurate_snr  :  Get the accurate SNR of all Beidou satellites
+//
+//     Note  :  SNR is an array with 30 float.
+//  Example:
+//     float SNR[30];
+//     mtk_gps_get_bd_sat_accurate_snr(SNR);
+//     // Get SNR of SV 17
+//     MTK_UART_OutputData("BD,SV17: SNR = %lf", SNR[16]);
+//
+//  =====>BD,SV17: SNR = 38.1
+
+void mtk_gps_get_bd_sat_accurate_snr(float SNR[30]);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_per_test
+ * DESCRIPTION
+ *   Enable PER test
+ * PARAMETERS
+ *  Threshold       [IN]   power of 2(1,2,4,8,...)
+ *  SVid               [IN]   SVid for PER test that can be tracked in sky
+ *  TargetCount   [IN]   Test time in 20ms unit
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_per_test(INT16 Threshold, UINT16 SVid, UINT16 TargetCount);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_chip_capability
+ * DESCRIPTION
+ *  send chip capability to mnld (ex: 6797: GPS + Beidou + Glonass)
+ * PARAMETERS
+ *  pradt       [out]
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+void
+mtk_gps_get_chip_capability (UINT8* SV_TYPE);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gnss_get_gps_time_infor
+ * DESCRIPTION
+ *  send GPS TOW,WK and leap second when send PMTK761/763
+ * PARAMETERS
+ *  pradt       [IN]   pointer to the data structure of the A-GPS command or data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gnss_get_gps_time_infor (unsigned int *p_dfTOW, short *p_i2WeekNo, double *p_UTC_Cor);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_agps_data
+ * DESCRIPTION
+ *  send A-GPS assistance data or command to GPS receiver
+ * PARAMETERS
+ *  pradt       [IN]   pointer to the data structure of the A-GPS command or data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_agps_data(const MTK_GPS_AGPS_CMD_DATA_T *prAdt);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_agps_response
+ * DESCRIPTION
+ *  obtain detailed information of A-GPS reponse
+ * PARAMETERS
+ *  prRsp     [OUT]  pointer to A-GPS response data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_response(MTK_GPS_AGPS_RESPONSE_T *prRsp);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_agps_lppe_3Dstatus_response
+ * DESCRIPTION
+ *  obtain detailed information of A-GPS reponse
+ * PARAMETERS
+ *  prRsp     [OUT]  pointer to A-GPS response data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_lppe_3Dstatus_response(gnss_ha_3Dposition_struct *hight_3Dposition,gnss_ha_3Dvelocity_struct *hight_3Dvelocity);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_agps_lppe_meas_response
+ * DESCRIPTION
+ *  obtain detailed information of A-GPS reponse
+ * PARAMETERS
+ *  prRsp     [OUT]  pointer to A-GPS response data
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_lppe_meas_response(gnss_ha_Measure_struct *ha_Measure);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_agps_req_mod
+ * DESCRIPTION
+ *  obtain req module of A-GPS response
+ * PARAMETERS
+ *  ReqMod     [OUT]  pointer to request module
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_get_agps_req_mod(MTK_GPS_MODULE *pReqMod);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_time_change_notify
+ * DESCRIPTION
+ *  Notify MNL to handle RTC time change
+ * PARAMETERS
+ *  INT32RtcDiff      [IN]  System RTC time changed: old rtc time - new rtc time
+ * RETURNS
+ *
+ *****************************************************************************/
+void
+mtk_gps_time_change_notify(INT32 INT32RtcDiff);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_rtc_offset
+ * DESCRIPTION
+ *  Notify MNL to handle RTC time change
+ * PARAMETERS
+ *  r8RtcOffset      [OUT]  System RTC time changed
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_rtc_offset(double *r8RtcOffset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_time_update_notify
+ * DESCRIPTION
+ *  Notify MNL to handle RTC time change
+ * PARAMETERS
+ *  fgSyncGpsTime      [IN]  System time sync to GPS time
+ *  i4RtcDiff      [IN]  Difference of system RTC time changed
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_time_update_notify(UINT8 fgSyncGpsTime, INT32 i4RtcDiff);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_debug_config
+ * DESCRIPTION
+ *  config the debug log type and level
+ * PARAMETERS
+ *  DbgType         [IN]  Debug message category
+ *  DbgLevel        [IN]  Debug message output level
+ *
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_sys_debug_config(MTK_GPS_DBG_TYPE DbgType, MTK_GPS_DBG_LEVEL DbgLevel);
+
+
+/* =================== Porting layer functions =================== */
+/*            The function body needs to be implemented            */
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_gps_mnl_callback
+ * DESCRIPTION
+ *  MNL CallBack function
+ * PARAMETERS
+ *  mtk_gps_notification_type
+ * RETURNS
+ *   success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+
+INT32
+mtk_gps_sys_gps_mnl_callback(MTK_GPS_NOTIFICATION_TYPE msg);
+
+/*****************************************************************************
+ * FUNCTION
+*  mtk_gps_sys_time_tick_get
+* DESCRIPTION
+*  get the current system tick of target platform(msec)
+* PARAMETERS
+*  none
+* RETURNS
+*  system time tick
+*****************************************************************************/
+UINT32
+mtk_gps_sys_time_tick_get(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_time_tick_get_max
+ * DESCRIPTION
+ *  get the maximum system tick of target platform(msec)
+ * PARAMETERS
+ *  none
+ * RETURNS
+ *  system time tick
+ *****************************************************************************/
+UINT32
+mtk_gps_sys_time_tick_get_max(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_time_read
+ * DESCRIPTION
+ *  Read system time
+ * PARAMETERS
+ *  utctime     [IN/OUT] get the host system time
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *  failed(MTK_GPS_ERROR)
+ *  system time changed since last call(MTK_GPS_ERROR_TIME_CHANGED)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_time_read(MTK_GPS_TIME* utctime);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_task_sleep
+ * DESCRIPTION
+ *  Task sleep function
+ * PARAMETERS
+ *  milliseconds [IN]
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_sys_task_sleep(UINT32 milliseconds);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_storage_open
+ * DESCRIPTION
+ *  Open a non-volatile file
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_storage_open(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_storage_close
+ * DESCRIPTION
+ *  Close a non-volatile file
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_sys_storage_close(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_storage_delete
+ * DESCRIPTION
+ *  Delete a non-volatile file
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_sys_storage_delete(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_storage_read
+ * DESCRIPTION
+ *  Read a non-volatite file
+ *  - blocking read until reaching 'length' or EOF
+ * PARAMETERS
+ *  buffer      [OUT]
+ *  offset      [IN]
+ *  length      [IN]
+ *  p_nRead     [OUT]
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_storage_read(void* buffer, UINT32 offset, UINT32 length,
+                      UINT32* p_nRead);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_storage_write
+ * DESCRIPTION
+ *  Write a non-volatite file
+ * PARAMETERS
+ *  buffer      [IN]
+ *  offset      [IN]
+ *  length      [IN]
+ *  p_nWritten  [OUT]
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_storage_write(const void* buffer, UINT32 offset, UINT32 length,
+                       UINT32* p_nWritten);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_mem_alloc
+ * DESCRIPTION
+ *  Allocate a block of memory
+ * PARAMETERS
+ *  size        [IN]   the length of the whole memory to be allocated
+ * RETURNS
+ *  On success, return the pointer to the allocated memory
+ *  NULL(0) if failed
+ *****************************************************************************/
+void*
+mtk_gps_sys_mem_alloc(UINT32 size);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_mem_free
+ * DESCRIPTION
+ *  Release unused memory
+ * PARAMETERS
+ *  pmem         [IN]
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_sys_mem_free(void* pmem);
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_gps_sys_event_delete
+* DESCRIPTION
+*  event delete for Android
+* PARAMETERS
+*  event_idx         [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_delete(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_gps_sys_event_create
+* DESCRIPTION
+*  event create for Android
+* PARAMETERS
+*  event_idx         [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_create(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_gps_sys_event_set
+* DESCRIPTION
+*  event set for Android
+* PARAMETERS
+*  event_idx         [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_set(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_gps_sys_event_wait
+* DESCRIPTION
+*  event wait for android
+*
+* PARAMETERS
+*  event_idx         [IN] MTK_GPS_EVENT_ENUM
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_event_wait(MTK_GPS_EVENT_ENUM event_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_uart_init
+ * DESCRIPTION
+ *  Initiialize UART
+ * PARAMETERS
+ *  portname      [IN]
+ *  baudrate      [IN]
+ *  txbufsize      [IN]
+ *  rxbufsize      [IN]
+ * RETURNS
+ *  Result of Handler
+ *****************************************************************************/
+INT32
+mtk_gps_sys_uart_init(char* portname, UINT32 baudrate, UINT32 txbufsize,
+                      UINT32 rxbufsize);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_uart_read
+ * DESCRIPTION
+ *  Initiialize UART
+ * PARAMETERS
+ *  UARTHandle      [IN]
+ *  buffer      [IN]
+ *  bufsize      [IN]
+ *  length      [IN]
+ * RETURNS
+ *  Result of Handler
+ *****************************************************************************/
+INT32
+mtk_gps_sys_uart_read(INT32 UARTHandle, char* buffer, UINT32 bufsize,
+                   INT32* length);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_uart_write
+ * DESCRIPTION
+ *  Initiialize UART
+ * PARAMETERS
+ *  UARTHandle      [IN]
+ *  buffer      [IN]
+ *  bufsize      [IN]
+ *  length      [IN]
+ * RETURNS
+ *  Result of Handler
+ *****************************************************************************/
+INT32 mtk_gps_sys_uart_write(INT32 UARTHandle, const char* buffer, UINT32 bufsize,
+       INT32* wrotenlength);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_uart_uninit
+ * DESCRIPTION
+ *  Initiialize UART
+ * PARAMETERS
+ *  UARTHandle      [IN]
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_sys_uart_uninit(INT32 UARTHandle);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_if_set_spd
+ * DESCRIPTION
+ *  Set baud rate at host side from GPS lib
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  baudrate         [IN] UART baudrate
+ *  hw_fc            [IN] UART hardware flow control
+ *                        0: without hardware flow contorl(defualt)
+ *                        1: with hardware flow contorl
+ * RETURNS
+ *  success(0)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_if_set_spd(UINT32 baudrate, UINT8 hw_fc);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_data_output
+ * DESCRIPTION
+ *  Transmit data to the GPS chip
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  msg         [IN]
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_data_output(char* buffer, UINT32 length);
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_gps_sys_nmea_output
+* DESCRIPTION
+*  Transmit NMEA data out to task
+*  (The function body needs to be implemented)
+* PARAMETERS
+*  buffer         [IN] data pointer
+*  length         [IN] size of data
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_nmea_output(char* buffer, UINT32 length);
+
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_sys_nmea_output_to_app
+* DESCRIPTION
+*  Transmit NMEA data out to APP layer
+*  (The function body needs to be implemented)
+* PARAMETERS
+*  buffer         [IN] data pointer
+*  length         [IN] size of data
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_nmea_output_to_app(const char * buffer, UINT32 length);
+
+INT32
+mtk_gps_sys_nmea_output_to_app_print(const char *fmt, ...);
+
+#if 1
+/*****************************************************************************
+* FUNCTION
+*  mtk_sys_nmea_output_to_mnld
+* DESCRIPTION
+*  Transmit NMEA data out to MNLD
+*  (The function body needs to be implemented)
+* PARAMETERS
+*  buffer         [IN] data pointer
+*  length         [IN] size of data
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length);
+#endif
+
+/*****************************************************************************
+* FUNCTION
+*  mnl_sys_alps_gps_dbg2file_mnld
+* DESCRIPTION
+*  Transfer GPS debug log to MNLD to write to file
+*  (The function body needs to be implemented)
+* PARAMETERS
+*  buffer         [IN] data pointer
+*  length         [IN] size of data
+* RETURNS
+*  success(MTK_GPS_SUCCESS)
+*****************************************************************************/
+INT32
+mnl_sys_alps_gps_dbg2file_mnld(const char * buffer, UINT32 length);
+
+//  Otehr platform
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_start_result_handler
+ * DESCRIPTION
+ *  Handler routine for the result of restart command
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  result         [IN]  the result of restart
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_start_result_handler(MTK_GPS_START_RESULT result);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_spi_poll
+ * DESCRIPTION
+ *  Polling data input routine for SPI during dsp boot up stage.
+ *  If use UART interface, this function can do nothing at all.
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_spi_poll(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_set_spi_mode
+ * DESCRIPTION
+ *  Set SPI interrupt/polling and support burst or not.
+ *  If use UART interface, this function can do nothing at all.
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  enable_int         [IN]  1 for enter interrupt mode , 0 for entering polling mode
+ *  enable_burst       [IN]  1 for enable burst transfer, 0 for disable burst transfer
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_set_spi_mode(UINT8 enable_int, UINT8 enable_burst);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_dsp_boot_begin_handler
+ * DESCRIPTION
+ *  Handler routine for porting layer implementation right before GPS DSP boot up
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  none
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_dsp_boot_begin_handler(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_dsp_boot_end_handler
+ * DESCRIPTION
+ *  Handler routine for porting layer implementation right after GPS DSP boot up
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  none
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_dsp_boot_end_handler(void);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_frame_sync_meas
+ * DESCRIPTION
+ * PARAMETERS
+ *  pFrameTime [OUT] frame time of the issued frame pulse(seconds)
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+
+INT32 mtk_gps_sys_frame_sync_meas(double *pdfFrameTime);
+
+INT32 mtk_gps_sys_frame_sync_enable_sleep_mode(unsigned char mode);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_frame_sync_meas_resp
+ * DESCRIPTION
+ *  accept a frame sync measurement response
+ * PARAMETERS
+ *  eResult     [IN] success to issue a frame sync meas request
+ *  dfFrameTime [IN] frame time of the issued frame pulse(seconds)
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_frame_sync_meas_resp(MTK_GPS_FS_RESULT eResult, double dfFrameTime);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_frame_sync_meas_req_by_network
+ * DESCRIPTION
+ *  issue a frame sync measurement request
+ * PARAMETERS
+ *  none
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *  fail(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_frame_sync_meas_req_by_network(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_frame_sync_meas_req
+ * DESCRIPTION
+ *  issue a frame sync measurement request
+ * PARAMETERS
+ *  mode       [out] frame sync request indication for aiding or maintain
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *  fail(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_frame_sync_meas_req(MTK_GPS_FS_WORK_MODE mode);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_initialize_mutex
+ * DESCRIPTION
+ *  Inialize mutex array
+ * PARAMETERS
+ *  void
+  * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_initialize_mutex(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_create_mutex
+ * DESCRIPTION
+ *  Create a mutex object
+ * PARAMETERS
+ *  mutex_num        [IN]  mutex index used by MTK Nav Library
+  * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_create_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_take_mutex
+ * DESCRIPTION
+ *  Request ownership of a mutex and if it's not available now, then block the thread execution
+ * PARAMETERS
+ *  mutex_num        [IN]  mutex index used by MTK Nav Library
+ * RETURNS
+ *  void
+ *****************************************************************************/
+
+void
+mtk_gps_sys_take_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_give_mutex
+ * DESCRIPTION
+ *  Release a mutex ownership
+ * PARAMETERS
+ *  mutex_num        [IN]  mutex index used by MTK Nav Library
+ * RETURNS
+ *  void
+ *****************************************************************************/
+
+void
+mtk_gps_sys_give_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_destroy_mutex
+ * DESCRIPTION
+ *  Destroy a mutex object
+ * PARAMETERS
+ *  mutex_num        [IN]  mutex index used by MTK Nav Library
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_destroy_mutex(MTK_GPS_MUTEX_ENUM mutex_idx);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_pmtk_cmd_cb
+ * DESCRIPTION
+ *  Notify porting layer that MNL has received one PMTK command.
+ * PARAMETERS
+ *  UINT16CmdNum        [IN]  The received PMTK command number.
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_sys_pmtk_cmd_cb(UINT16 UINT16CmdNum);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_sys_spi_poll
+ * DESCRIPTION
+ *  Polling data input routine for SPI during dsp boot up stage.
+ *  If use UART interface, this function can do nothing at all.
+ *  (The function body needs to be implemented)
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS)
+ *****************************************************************************/
+INT32 mtk_gps_sys_spi_poll(void);
+
+ /*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_uart_poll
+ * DESCRIPTION
+ *  GPS RX polling function
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  success(0)
+ *****************************************************************************/
+INT32 mtk_gps_sys_uart_poll(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_rtc_info
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *  dfrtcD        [OUT]  RTC clock drift(unit : ppm).
+ *  dfage         [OUT]  RTC drift age : current gps time - gps time of latest rtc drift calculated.(unit : sec)
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_rtc_info(double *dfrtcD, double *dfage);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_delete_nv_data
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *  u4Bitmap    [INPUT]
+ *
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32 mtk_gps_delete_nv_data(UINT32 assist_data_bit_map);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_tsx_xvt
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *  u4Bitmap    [INPUT]
+ *
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32
+mtk_gps_tsx_xvt(UINT8 enable);
+
+/*****************************************************************************
+ * mtk_gps_set_wifi_location_aiding :
+ *   set Wifi location information to MNL
+ * Parameters :
+ *  latitude :Wifi latitude      unit: [degree]
+ *  longitude:Wifi longitude     unit: [degree]
+ *  posvar   :position accuracy  unit: [m]
+ * Return Value: 0: fail; 1: pass
+ *****************************************************************************/
+INT32 mtk_gps_set_wifi_location_aiding(MTK_GPS_REF_LOCATION *RefLocation,
+      double latitude, double longitude, double accuracy);
+
+/*****************************************************************************
+ * mtk_gps_inject_ntp_time :
+ *   inject ntp time into MNL
+ * Parameters :
+ *  time : ntp time      unit: [degree]
+ *  timeRef: the system time tick when sync NTP time to network    unit: mini-second
+ *  Uncertainty: ntp time uncertainty error: [mini]
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32 mtk_gps_inject_ntp_time(MTK_GPS_NTP_T* ntp);
+
+/*****************************************************************************
+ * mtk_gps_inject_nlp_location :
+ *   inject nlp location into MNL
+ * Parameters :
+ *  latitude : nlp latitude
+ *  longitude:  nlp longitude
+ *  accuracy: nlp location uncertainty : [m]
+ * success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32 mtk_gps_inject_nlp_location(MTK_GPS_NLP_T* nlp);
+
+
+/*****************************************************************************
+ * mtk_gps_measurement :
+ *   get gps measurement
+ * Parameters :
+ * flag:                  A set of flags indicating the validity of the fields in this data structure
+ * PRN:                 Pseudo-random number in the range of [1, 32]
+ * TimeOffsetInNs: Time offset at which the measurement was taken in nanoseconds.
+                            The reference receiver's time is specified by GpsData::clock::time_ns and should be
+                            interpreted in the same way as indicated by GpsClock::type.
+                            The sign of time_offset_ns is given by the following equation:
+                            measurement time = GpsClock::time_ns + time_offset_ns
+                            It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * state:                Per satellite sync state. It represents the current sync state for the associated satellite.
+                             Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ * ReGpsTowInNs:  Received GPS Time-of-Week at the measurement time, in nanoseconds.
+                            The value is relative to the beginning of the current GPS week.
+                            Given the sync state of GPS receiver, per each satellite, valid range for this field can be:
+                                 Searching           : [ 0       ]   : GPS_MEASUREMENT_STATE_UNKNOWN
+                                 Ranging code lock   : [ 0   1ms ]   : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+                                 Bit sync            : [ 0  20ms ]   : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+                                 Subframe sync       : [ 0   6ms ]   : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+                                 TOW decoded         : [ 0 1week ]   : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+ * ReGpsTowUnInNs: 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds
+ * Cn0InDbHz:                Carrier-to-noise density in dB-Hz, in the range [0, 63].
+                                     It contains the measured C/N0 value for the signal at the antenna input.
+ * PRRateInMeterPreSec: Pseudorange rate at the timestamp in m/s.
+                                     The value also includes the effects of the receiver clock frequency and satellite clock
+                                     frequency errors.
+                                     The value includes the 'pseudorange rate uncertainty' in it.
+                                     A positive value indicates that the pseudorange is getting larger.
+ * PRRateUnInMeterPreSec: 1-Sigma uncertainty of the pseudurange rate in m/s.
+                                         The uncertainty is represented as an absolute(single sided) value.
+ * AcDRState10:         Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+                               (indicating loss of lock).
+ * AcDRInMeters:       Accumulated delta range since the last channel reset in meters.
+ * AcDRUnInMeters:   1-Sigma uncertainty of the accumulated delta range in meters.
+ * PRInMeters:           Best derived Pseudorange by the chip-set, in meters.
+                                The value contains the 'pseudorange uncertainty' in it.
+ * PRUnInMeters:       1-Sigma uncertainty of the pseudorange in meters.
+                               The value contains the 'pseudorange' and 'clock' uncertainty in it.
+                               The uncertainty is represented as an absolute(single sided) value.
+ * CPInChips:           A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+                              This value contains the time(in Chip units) since the last C/A code cycle(GPS Msec epoch).
+                              The reference frequency is given by the field 'carrier_frequency_hz'.
+                              The value contains the 'code-phase uncertainty' in it.
+ * CPUnInChips:       1-Sigma uncertainty of the code-phase, in a fraction of chips.
+                              The uncertainty is represented as an absolute(single sided) value.
+ * CFInhZ:               Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+                              If the field is not set, the carrier frequency is assumed to be L1.
+ * CarrierCycle:       The number of full carrier cycles between the satellite and the receiver.
+                              The reference frequency is given by the field 'carrier_frequency_hz'.
+ * CarrierPhase:      The RF phase detected by the receiver, in the range [0.0, 1.0].
+                              This is usually the fractional part of the complete carrier phase measurement.
+                              The reference frequency is given by the field 'carrier_frequency_hz'.
+                              The value contains the 'carrier-phase uncertainty' in it.
+ * CarrierPhaseUn:   1-Sigma uncertainty of the carrier-phase.
+ * LossOfLock:               An enumeration that indicates the 'loss of lock' state of the event.
+ * BitNumber:                The number of GPS bits transmitted since Sat-Sun midnight(GPS week).
+ * TimeFromLastBitInMs: The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+ * DopperShiftInHz:        Doppler shift in Hz.
+                                    A positive value indicates that the SV is moving toward the receiver.
+                                    The reference frequency is given by the field 'carrier_frequency_hz'.
+                                    The value contains the 'doppler shift uncertainty' in it.
+ * DopperShiftUnInHz:    1-Sigma uncertainty of the doppler shift in Hz.
+ * MultipathIndicater:     An enumeration that indicates the 'multipath' state of the event.
+ * SnrInDb:                  Signal-to-noise ratio in dB.
+ * ElInDeg:                   Elevation in degrees, the valid range is [-90, 90].
+                                   The value contains the 'elevation uncertainty' in it.
+ * ElUnInDeg:               1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+                                   The uncertainty is represented as the absolute(single sided) value.
+ * AzInDeg:                  Azimuth in degrees, in the range [0, 360).
+                                  The value contains the 'azimuth uncertainty' in it.
+ * AzUnInDeg:             1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+                                 The uncertainty is represented as an absolute(single sided) value.
+ * UsedInFix:              Whether the GPS represented by the measurement was used for computing the most recent fix.
+ *****************************************************************************/
+void
+mtk_gps_get_measurement(MTK_GPS_MEASUREMENT GpsMeasurement[32], INT8 Ch_Proc_Ord_PRN[32]);
+
+/*****************************************************************************
+ * mtk_gps_clock :
+ *   get clock parameter
+ * Parameters :
+ * flag:            A set of flags indicating the validity of the fields in this data structure.
+ * leapsecond: Leap second data.
+                      The sign of the value is defined by the following equation:
+                      utc_time_ns = time_ns +(full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+ * type:           Indicates the type of time reported by the 'time_ns' field.
+ * TimeInNs:    The GPS receiver internal clock value. This can be either the local hardware clock value
+                     (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+                     (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+
+                      For local hardware clock, this value is expected to be monotonically increasing during
+                      the reporting session. The real GPS time can be derived by compensating the 'full bias'
+                     (when it is available) from this value.
+
+                      For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+                      receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+
+                      Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+                      The value contains the 'time uncertainty' in it.
+ * TimeUncertaintyInNs: 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+                                    The uncertainty is represented as an absolute(single sided) value.
+                                    This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+ * FullBiasInNs:              The difference between hardware clock('time' field) inside GPS receiver and the true GPS
+                                    time since 0000Z, January 6, 1980, in nanoseconds.
+                                    This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+                                    has solved the clock for GPS time.
+                                    The caller is responsible for using the 'bias uncertainty' field for quality check.
+
+                                    The sign of the value is defined by the following equation:
+                                    true time(GPS time) = time_ns +(full_bias_ns + bias_ns)
+
+                                    This value contains the 'bias uncertainty' in it.
+ * BiasInNs:                  Sub-nanosecond bias.
+                                    The value contains the 'bias uncertainty' in it.
+ * BiasUncertaintyInNs:   1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+                                    The uncertainty is represented as an absolute(single sided) value.
+ * DriftInNsPerSec:        The clock's drift in nanoseconds(per second).
+                                    A positive value means that the frequency is higher than the nominal frequency.
+
+                                    The value contains the 'drift uncertainty' in it.
+ * DriftUncertaintyInNsPerSec:  1-Sigma uncertainty associated with the clock's drift in nanoseconds(per second).
+                                              The uncertainty is represented as an absolute(single sided) value.
+ *
+ * Return Value: 0: fail; 1: pass
+ *****************************************************************************/
+INT32
+mtk_gps_get_clock(MTK_GPS_CLOCK *GpsClock);
+
+/*****************************************************************************
+ * mtk_gps_navigation_event :
+ *   get navigation event
+ * Parameters :
+ * type:                The type of message contained in the structure.
+ * prn:                  Pseudo-random number in the range of [1, 32]
+ * meaasgeID:      Message identifier.
+                           It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+                           subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+                           Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+ * submeaasgeID: Sub-message identifier.
+                            If required by the message 'type', this value contains a sub-index within the current
+                            message(or frame) that is being transmitted.
+                            i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+ * data[]:              The data of the reported GPS message.
+                            The bytes(or words) specified using big endian format(MSB first).
+
+                            For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word(30 bits) should be
+                            fitted into the last 30 bits in a 4-byte word(skip B31 and B32), with MSB first.
+ *
+ * Return Value: 0: fail; 1: pass
+ *****************************************************************************/
+INT32
+mtk_gps_get_navigation_event(MTK_GPS_NAVIGATION_EVENT *NavEvent, UINT8 SVID);
+
+
+void
+mtk_gnss_get_measurement(Gnssmeasurement GpQzMeasurement[40], Gnssmeasurement GloMeasurement[24],
+Gnssmeasurement BDMeasurement[37], Gnssmeasurement GalMeasurement[36],Gnssmeasurement SBASMeasurement[42],
+INT8 GpQz_Ch_Proc_Ord_PRN[40],INT8 Glo_Ch_Proc_Ord_PRN[24],INT8 BD_Ch_Proc_Ord_PRN[37],
+INT8 Gal_Ch_Proc_Ord_PRN[36],INT8 SBAS_Ch_Proc_Ord_PRN[42]);
+
+INT32
+mtk_gnss_get_clock(Gnssclock *GnssClock);
+
+
+INT32
+mtk_gnss_get_navigation_event (GnssNavigationmessage *NavEvent, UINT8 SVID, UINT8 SV_type);
+
+// *****************************************************************************
+//  mtk_gps_set_mpe_event :(MNL to MPE)
+//  set mpe event
+//  Parameters :
+// *****************************************************************************
+UINT16
+mtk_gps_set_mpe_info(UINT8 *msg);
+
+// *****************************************************************************
+//  mtk_gps_mnl_mpe_callback_reg :(MNLD to MNL)
+//  MNLD register callback function in libmnl
+//  Parameters :
+//   name    [IN]  callback function address in MNLD
+//  Return
+//    success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+// *****************************************************************************
+int
+mtk_gps_mnl_mpe_callback_reg(MPECallBack *name);
+
+// *****************************************************************************
+//  mtk_gps_mnl_mpe_run_callback :(MNL to MNLD)
+//  Run MNLD function registered in libmnl
+//  Parameters :
+//  Return
+//    success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+// *****************************************************************************
+int
+mtk_gps_mnl_mpe_run_callback(void);
+
+/*****************************************************************************
+ * mtk_gps_get_sensor_info :
+ *   get sensor LLH,head,head acc,vout information(MPE to MNL)
+ * Parameters :
+ *****************************************************************************/
+void
+mtk_gps_get_sensor_info(INT8 *msg, int len);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_debug_type
+ * DESCRIPTION
+ *  Set the GPS debug type in running time
+ * PARAMETERS
+ *  debug_type         [IN]   the debug type needs to be changed
+ *
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_debug_type(const UINT8 debug_type);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_debug_type
+ * DESCRIPTION
+ *  Get the GPS debug type in running time
+ * PARAMETERS
+ *  debug_type         [out]   current debug type
+ *
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_debug_type(UINT8* debug_type);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_debug_file
+ * DESCRIPTION
+ *  Set the GPS debug file name(include the path name) in running time
+ * PARAMETERS
+ *  file_name         [IN]   the debug file name needs to be changed
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_set_debug_file(char* file_name);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_rtc_info
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *  PRN           [OUT]  PRN Number  (1~32 are valid).
+ *  ParityError   [OUT]  Parity Error flag (ex :3FF = 10 words are wrong)
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_word_parity(UINT32 *TTick,UINT8 PRN[26], UINT16 ParityError[26]);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_get_jamming_indicator
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *  JammingIndicator           [OUT]  Jamming Indicator
+ *                                    1 : No jammer, healthy status
+ *                                    2 : Warning status
+ *                                    3 : Critical status
+ *****************************************************************************/
+void mtk_get_jamming_indicator(unsigned char *JammingIndicator);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_set_gnss_low_power_mode
+ * DESCRIPTION
+ *  Set GNSS Low Power mode
+ * PARAMETERS
+ *  GNSSLowPowerMode           [IN]  Enable GNSS Low Power or not
+ *                                    0 : Disable GNSS Low Power
+ *                                    1 : Enable GNSS Low Power
+ *****************************************************************************/
+void mtk_set_gnss_low_power_mode(unsigned char GNSSLowPowerMode);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_get_gnss_low_power_mode
+ * DESCRIPTION
+ *  Get GNSS Low Power mode
+ * PARAMETERS
+ *  GNSSLowPowerMode           [OUT]  GNSS Low Power enabled or not
+ *                                    0 : GNSS Low Power disabled
+ *                                    1 : GNSS Low Power enabled
+ *****************************************************************************/
+void mtk_get_gnss_low_power_mode(unsigned char *GNSSLowPowerMode);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_set_ext_lna_control_test
+ * DESCRIPTION
+ *  Test the external LNA. The external LNA would be turn off when calling this function.
+ *****************************************************************************/
+void mtk_set_ext_lna_control_test(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_set_pps_config
+ * DESCRIPTION
+ *  Set PPS Config
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+
+INT32 mtk_gps_set_pps_config (MTK_GPS_PPS_CFG *pps_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_pps_config
+ * DESCRIPTION
+ *  Get PPS Config
+ *****************************************************************************/
+
+INT32 mtk_gps_get_pps_config (MTK_GPS_PPS_CFG *pps_cfg);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_get_position_accuracy
+ * DESCRIPTION
+ *  get position
+ * PARAMETERS
+ *  double *Lat,double *Lon,int *accuracy)
+ *     Get return result
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure(MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_get_position_accuracy(double *Lat, double *Lon, int *accuracy);
+
+void
+mtk_gps_mnl_get_sensor_info(UINT8 *msg, int len);
+
+void
+mtk_gps_mnl_set_sensor_info(UINT8 *msg, int len);
+
+int
+mtk_gps_mnl_trigger_mpe(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_qepo_file_update
+ * DESCRIPTION
+ *    Update the qEPO file after the new qEpo file download
+ * PARAMETERS
+ *      None
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32 mtk_agps_agent_qepo_file_update();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_agent_mtknav_file_update
+ * DESCRIPTION
+ *    Update the MTKNAV file after the new MTKNAV file download
+ * PARAMETERS
+ *      None
+ * RETURNS
+ *  success: MTK_GPS_SUCCESS  fail: MTK_GPS_ERROR
+ *****************************************************************************/
+INT32 mtk_agps_agent_mtknav_file_update();
+
+#if 1  // mnl offload interface start
+/*****************************************************************************
+ * \bref    for mnl offload
+ *          enable  offload:
+ *              1. mtk_gps_ofl_set_cfg(MNL_OFL_CFG_ENALBE_OFFLOAD)
+ *              2. mnl_sys_alps_gps_run
+ *          disable offload, only one step:
+ *              1. mnl_sys_alps_gps_run
+ */
+// ============================================================================
+//  Offload: MNLD => libmnl.so
+// ============================================================================
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_set_option
+ * DESCRIPTION
+ *  Configure mnl offload parameters.
+ *  Now whether to enable mnl offload is controlled by this function
+ * PARAMETERS
+ *  user_bitmask     [IN]  bitmask like MNL_OFL_CFG_XXX
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+#define MNL_OFL_OPTION_ENALBE_OFFLOAD   0x1
+
+INT32 mtk_gps_ofl_set_option(UINT32 cfg_bitmask);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_set_user
+ * DESCRIPTION
+ *  Set the owners who use MNL, then how to init CONNSYS-MNL can be initilised.
+ * PARAMETERS
+ *  user_bitmask     [IN]  bitmask which stands for different users like GPS_USR_XXX.
+ *                      The bitmask must contaion all the users of GPS so mnld msut
+ *                      must keep a copy of this bitmask.
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+#define GPS_USER_UNKNOWN        0x0
+#define GPS_USER_APP            0x1
+#define GPS_USER_AGPS           0x2
+#define GPS_USER_META           0x4   //  meta or factory mode
+#define GPS_USER_RESTART        0x8
+#define GPS_USER_FLP            0x10
+#define GPS_USER_OFL_TEST       0x20  //  for offload test
+#define GPS_USER_AT_CMD         0x40  //  for offload test
+#define GPS_USER_APM            0x80
+#define GPS_USER_GEOFENCE       0x100
+
+INT32 mtk_gps_ofl_set_user(UINT32 user_bitmask);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_rst_stpgps_begin_ntf
+ * DESCRIPTION
+ *  Notify libmnl.so that MNLD is to reopen /dev/stpgps.
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_rst_stpgps_begin_ntf();
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_rst_stpgps_begin_ntf
+ * DESCRIPTION
+ *  Notify libmnl.so that MNLD has reopened /dev/stpgps and tell libmnl.so the new fd.
+ * PARAMETERS
+ *  dsp_fd      [IN] the new fd of /dev/stpgps after reopened.
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_rst_stpgps_end_ntf(int dsp_fd);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_send_flp_data
+ * DESCRIPTION
+ *  Reroute data from HOST FLP to CONNSYS FLP.
+ * PARAMETERS
+ *  buf     [IN] buffer to send
+ *  len     [IN] length of the data
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_send_flp_data(UINT8 *buf, UINT32 len);
+
+#if 0
+/* These 2 API can be replaced by:
+mtk_gps_ofl_set_user(gps_user |  GPS_USER_FLP);
+mtk_gps_ofl_set_user(gps_user & ~GPS_USER_FLP);
+*/
+INT32 mtk_gps_ofl_flp_init();
+INT32 mtk_gps_ofl_flp_deinit();
+#endif
+
+//  ============================================================================
+//  Offload: libmnl.so => MNLD
+//  ============================================================================
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_sys_rst_stpgps_req
+ * DESCRIPTION
+ *  Request MNLD to reopen /dev/stpgps.
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+ 
+INT32 sys_gps_mnl_data2mnld_callback(const char *data, unsigned int length);
+/*****************************************************************************
+ * FUNCTION
+ *  sys_gps_mnl_data2mnld_callback
+ * DESCRIPTION
+ *  Submit data from mnl to mnld.
+ * PARAMETERS
+ *  buf     [IN] buffer to send
+ *  len     [IN] length of the data
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+
+INT32 mtk_gps_ofl_sys_rst_stpgps_req(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_sys_submit_flp_data
+ * DESCRIPTION
+ *  Submit data from CONNSYS FLP to HOST FLP.
+ * PARAMETERS
+ *  buf     [IN] buffer to send
+ *  len     [IN] length of the data
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_sys_submit_flp_data(UINT8 *buf, UINT32 len);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_ofl_sys_mnl_offload_callback
+ * DESCRIPTION
+ *  Callback for libmnl.so to notify MNLD for something.
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_ofl_sys_mnl_offload_callback(
+    MTK_GPS_OFL_CB_TYPE type, UINT16 length, UINT8 *data);
+#endif  //  mnl offload interface end
+
+
+#if 1  // for FLP AP mode function only
+/*****************************************************************************
+ * FUNCTION
+ *   mtk_gps_flp_get_location
+ *
+ * DESCRIPTION
+ *   Porting layer or MNL daemon can call this API to fill location data to
+ *     "buf", then it can be reported to FLP daemon.
+ *
+ *   The "buf" will be filled with "MtkGpsLocation". Due to MNLD use
+ *     "buf" rather then "MtkGpsLocation" as parameter, any change on
+ *     "MtkGpsLocation" structure only need to be synchronized between
+ *     FLP daemon and libmnl, then maintian effort can be eased.
+ *
+ *   Please note that:
+ *   1. It's better if "buf" is 4-byte alligned. On some platform, non-alligned
+ *     address for structure filling may cause issue.
+ *   2. The "buf_len" should be greater than or equal to
+ *     sizeof("MtkGpsLocation"), otherwise function will return
+ *     "MTK_GPS_ERROR" and no data will be filled into "buf".
+ *   3. If function return MTK_GPS_SUCCESS, "buf" will be filled and the filled
+ *     length can be get from "*p_get_len".
+ *   4. If function return MTK_GPS_ERROR, "*p_get_len" indicates the wanted "buf_len"
+ *
+ * PARAMETERS
+ *  buf         [OUT] buffer to be filled
+ *  buf_len     [IN]  length of the buffer
+ *  p_get_len   [OUT] the actual length of data be filled to buffer.
+ *                    it should be
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32 mtk_gps_flp_get_location(void *buf, UINT32 buf_len, UINT32 *p_get_len);
+#endif // for FLP AP mode function only
+
+
+//*************************************************************************************
+// mtk_gps_get_gnss_operation_mode  :  Set GNSS operation mode
+//
+//    Note  :  fgGLONStatus = [0] Disable GLONASS [1] Enable GLONASS
+//             fgGALIStatus = [0] Disable GALIELO [1] Enable GALIELO
+//             fgBEDOStatus = [0] Disable BEIDOU  [1] Enable BEIDOU
+// Example:
+// unsigned char fgGLONStatus = 0;
+// unsigned char fgGALIStatus = 0;
+// unsigned char fgBEDOStatus = 0;
+// mtk_gps_get_gnss_operation_mode(&fgGLONStatus,&fgGALIStatus,&fgBEDOStatus);
+
+void mtk_gps_get_gnss_operation_mode(unsigned char *fgGLONStatus, unsigned char *fgGALIStatus, unsigned char *fgBEDOStatus);
+
+//*************************************************************************************
+// mtk_gps_set_gnss_operation_mode  :  Set GNSS operation mode
+//
+//    Note  :  fgGLONStatus = [0] Disable GLONASS [1] Enable GLONASS
+//             fgGALIStatus = [0] Disable GALIELO [1] Enable GALIELO
+//             fgBEDOStatus = [0] Disable BEIDOU  [1] Enable BEIDOU
+// Notice :
+//    GLONASS + GALILEO and Beidou are mutal exclusion.
+//    If you enable GLONASS, GALILEO and Beidou at the same time, Beidou will be disabled automatically.
+//
+// Notice : The GALILEO mode switch is not support in this release.
+//
+// Example:
+// mtk_gps_set_gnss_operation_mode(1,0,0) : Enable GLONASS
+// mtk_gps_set_gnss_operation_mode(0,0,0) : Disable GLOANSS, GALIELO , BEIDOU
+// mtk_gps_set_gnss_operation_mode(0,0,1) : Enable BEIDOU
+// mtk_gps_set_gnss_operation_mode(1,1,1) : Enable GLONASS. Beidou will be disabled automatically.
+
+void mtk_gps_set_gnss_operation_mode(unsigned char fgGLONStatus, unsigned char fgGALIStatus, unsigned char fgBEDOStatus);
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_agps.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_agps.h
new file mode 100644
index 0000000..a4cd3a8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_agps.h
@@ -0,0 +1,1146 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+#ifndef MTK_GPS_AGPS_H
+#define MTK_GPS_AGPS_H
+
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+#include "mtk_gps_type.h"
+
+#define MGPSID (32)
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ) )
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack(4)
+#endif
+
+
+typedef struct
+{
+  UINT8 u1Arg1;
+  UINT8 u1Arg2;
+  UINT8 u1Arg3; //VERSION
+  UINT8 u1Arg4; //C2K Flag
+} MTK_GPS_AGPS_CMD_MODE_T;
+
+typedef struct
+{
+#ifdef AGPS_SUPPORT_QOPMS
+  float u1Delay;  // Response time in unit of sec.
+                  // change  from interge sec to mini-sec. so the Required response time will be more accurate
+                  // for example
+                  //old : $PMTK293,16,0,0,51*<Check Sum>
+                  //new: $PMTK293,15.296,0,0,51*<Check Sum>
+#else
+  UINT8 u1Delay;  // Response time in unit of sec.
+#endif
+  UINT32 u4HAcc;  // Horizontal accuracy in unit of meter.
+  UINT16 u2VAcc;  // Vertical accuracy in unit of meter.
+  UINT16 u2PRAcc; // Pseudorange accuracy in unit of meter.
+  float  f4DelayEarlyFix; //[TS 36.355 R12] new item->responseTimeEarlyFix-r12
+  UINT32 u4PeriodicMode;// For Moving Scenario, default 0:normal mod, 1:moving scenario, >1, reserved.
+  UINT8 u1HAccConf;//(MSB only)Horizontal confidence [0~100]. 0 consider as "no information" and consider it as 90%.
+  UINT8 u1VAccConf;//(MSB only)Confidence associated with the altitude[0~100].0 consider as "no information" and consider it as 90%.
+  UINT8 u1PRAccConf;//(MSA only)MA accuracy confidence associated with the pseudorange error [0~100].0 consider as "no information" and consider it as 90%.
+} MTK_GPS_AGPS_CMD_QOP_T;
+
+typedef struct
+{
+  UINT8 u1SvId;
+  UINT32 au4Word[24];
+} MTK_GPS_ASSIST_EPH_T;
+
+typedef struct
+{
+  UINT32 u1SvId;
+  UINT32 au1Byte[55];
+  UINT32 u1Lf;
+} MTK_ASSIST_GLON_EPH_T;
+
+
+typedef struct
+{
+  UINT8 u1SvId;
+  UINT16 u2WeekNo;
+  UINT32 au4Word[8];
+} MTK_GPS_ASSIST_ALM_T;
+
+typedef struct
+{
+  UINT16 u2WeekNo;
+  double dfTow;        // sec
+  double dfTowRms;     // ms
+  double dfFS_Tow;     // sec, not used
+  double dfFS_TowRms;  // ms, not used
+  MTK_GPS_BOOL fgTimeComp;   /* TRUE: indicate ref time compensation from modem , FALSE: no ref time composate   */
+  double   dfTimeDelay;      /* the value of ref time compensation */
+  UINT8  gpsWeekCycleNumber; //INTEGER(0..7) -- GPS Acquisition Assistance Rel-10 Extension
+} MTK_GPS_ASSIST_TIM_T;
+
+typedef struct
+{
+  UINT16 u2WeekNo;
+  double dfTow;        // sec
+  double dfTowRms;     // ms
+  double dfFTime;      // sec, Frame Time correspond to GPS TOW
+  double dfFTimeRms;   // ms, Frame Time RMS accuracy
+} MTK_GPS_ASSIST_FTA_T, MTK_GPS_AGPS_DT_FTIME_T;    // Fine Time Assistance
+
+typedef struct
+{
+  double dfLat;        // Receiver Latitude in degrees
+  double dfLon;        // Receiver Longitude in degrees
+  double dfAlt;        // Receiver Altitude in meters
+  float fAcc_Maj;     // semi-major RMS accuracy [m]
+  float fAcc_Min;     // semi-minor RMS accuracy [m]
+  UINT8 u1Maj_Bear;   // Bearing of semi-major axis in degrees
+  float fAcc_Vert;    // Vertical RMS accuracy [m]
+  UINT8 u1Confidence; // Position Confidence: range from 0 ~ 100 [%]
+} MTK_GPS_ASSIST_LOC_T;
+
+typedef struct
+{
+   double dUtc_hms;  // UTC: hhmmss.sss
+   double dUtc_ymd;  //  UTC: yyyymmdd
+   UINT8 u1FixType;  // the type of measurements performed by the MS [0: 2D or 1: 3D]
+   double dfLat;     // latitude (degree)
+   double dfLon;     // longitude (degree)
+   INT16 i2Alt;      // altitude (m)
+   float fUnc_SMaj;  // semi-major axis of error ellipse (m)
+   float fUnc_SMin;  // semi-minor axis of error ellipse (m)
+   UINT16 u2Maj_brg; // bearing of the semi-major axis (degrees) [0 - 179]
+   float fUnc_Vert;  // Altitude uncertainty
+   UINT8 u1Conf;     // The confidence by which the position is known to be within the shape description, expressed as a percentage. [0 ~ 100] (%)
+   UINT16 u2HSpeed;  // Horizontal speed (km/hr)
+   UINT16 u2Bearing; // Direction (degree) of the horizontal speed [0 ~ 359]
+} MTK_GPS_AGPS_CMD_MA_LOC_T;
+typedef struct
+{
+  double dfClkDrift;   // GPS Clock Frequency Error [nsec/sec]
+  INT32 i4ClkRMSAcc;  // Frequency Measurement RSM Accuracy [nsec/sec]
+  INT32 i4ClkAge;     // Age (sec) of the clock drift value since last estimated
+} MTK_GPS_ASSIST_CLK_T;
+
+typedef struct
+{
+  INT8 i1a0;         // Klobuchar - alpha 0  (seconds)           / (2^-30)
+  INT8 i1a1;         // Klobuchar - alpha 1  (sec/semi-circle)   / (2^-27/PI)
+  INT8 i1a2;         // Klobuchar - alpha 2  (sec/semi-circle^2) / (2^-24/PI^2)
+  INT8 i1a3;         // Klobuchar - alpha 3  (sec/semi-circle^3) / (2^-24/PI^3)
+  INT8 i1b0;         // Klobuchar - beta 0   (seconds)           / (2^11)
+  INT8 i1b1;         // Klobuchar - beta 1   (sec/semi-circle)   / (2^14/PI)
+  INT8 i1b2;         // Klobuchar - beta 2   (sec/semi-circle^2) / (2^16/PI^2)
+  INT8 i1b3;         // Klobuchar - beta 3   (sec/semi-circle^3) / (2^16/PI^3)
+} MTK_GPS_ASSIST_KLB_T;
+
+typedef struct
+{
+  INT32 i4A1;         // UTC parameter A1 (seconds/second)/(2^-50)
+  INT32 i4A0;         // UTC parameter A0 (seconds)/(2^-30)
+  UINT8 u1Tot;        // UTC reference time of week (seconds)/(2^12)
+  UINT8 u1WNt;        // UTC reference week number (weeks)
+  INT8 i1dtLS;       // UTC time difference due to leap seconds before event (seconds)
+  UINT8 u1WNLSF;      // UTC week number when next leap second event occurs (weeks)
+  UINT8 u1DN;         // UTC day of week when next leap second event occurs (days)
+  INT8 i1dtLSF;      // UTC time difference due to leap seconds after event (seconds)
+} MTK_GPS_ASSIST_UCP_T;
+
+typedef struct
+{
+  INT8 i1NumBad;        // Number of Bad Satellites listed
+  UINT8 au1SvId[MTK_GPS_SV_MAX_PRN]; // A list of bad SV id
+} MTK_GPS_ASSIST_BSV_T;
+
+
+typedef struct
+{
+  UINT8 u1SV;          // SV PRN number (1 ~ 32) (0 means no data available)
+  INT32 i4GPSTOW;      // TOW of last Acquisition Assistance data, Units 0.08 sec
+  INT16 i2Dopp;        // Doppler value. Units 2.5 Hz
+  INT8 i1DoppRate;    // Doppler rate of change. Units (1/42) Hz/s
+  UINT8 u1DoppSR;      // Doppler search range. index. [0 ~ 4]
+  UINT16 u2Code_Ph;     // C/A Code Phase chips [range 0..1022]
+                    //    relative to the previous msec edge
+  INT8 i1Code_Ph_Int; // Integer C/A Code msec into the GPS Data Bit
+                    //    [range 0..19 msec]  (-1 if not known)
+  INT8 i1GPS_Bit_Num; // GPS Data Bit Number, modulo 80 msec  [range 0..3]
+                    //    (-1 if not known)
+  UINT8 u1CodeSR;      // Code search range. index. [0 ~ 15]
+  UINT8 u1Azim;        // Azimuth. Units 11.25 degrees
+  UINT8 u1Elev;        // Elevation. Units 11.25 degrees
+} MTK_GPS_ASSIST_ACQ_T;
+
+
+#define RTCM_MAX_N_SAT 11
+typedef struct
+{
+  UINT8 u1SatID;  // [1 - 32]
+  UINT8 u1IODE;   // [0 - 255]
+  UINT8 u1UDRE;   // [0 - 3]
+  INT16 i2PRC;    // [-655.04 - 655.04], Units 0.32m
+  INT8 i1RRC;    // [-4.064 - 4.064], Units 0.032m
+} MTK_GPS_RTCM_SV_CORR_T;
+
+typedef struct
+{
+  UINT32 u4Tow;     // the baseline time for the corrections are valid [0 - 604799]
+  UINT8 u1Status;  // the status of the differential corrections [0 - 7]
+  UINT8 u1NumSv;   // the number of satellites for which differential corrections are available [1 - 11]
+  MTK_GPS_RTCM_SV_CORR_T arSVC[RTCM_MAX_N_SAT];
+} MTK_GPS_ASSIST_DGP_T;
+
+#define TOW_MAX_N_SAT 11
+typedef struct
+{
+    UINT8 u1SatID;   // [1 - 32]
+    UINT16 u2TLM;    // [0 - 16383]
+    UINT8 u1Anti_s;  // [0 - 1]
+    UINT8 u1Alert;   // [0 - 1]
+    UINT8 u1Reserved;  // [0 - 3]
+} MTK_GPS_TOW_SV_T;
+
+typedef struct
+{
+  UINT16 u2WN;      // GPS week number (weeks)
+  UINT32 u4Tow;     // GPS time of week  of the TLM message applied [0 - 604799]
+  UINT8 u1NumSv;   // the number of satellites for which TOW assist are available [1 - 11]
+  MTK_GPS_TOW_SV_T atSV[TOW_MAX_N_SAT];
+} MTK_GPS_ASSIST_TOW_T;
+
+typedef struct
+{
+  MTK_GPS_BOOL fgAcceptAlm;    // Satellite Almanac
+  MTK_GPS_BOOL fgAcceptUcp;    // UTC Model
+  MTK_GPS_BOOL fgAcceptKlb;    // Ionospheric Model
+  MTK_GPS_BOOL fgAcceptEph;    // Navigation Model
+  MTK_GPS_BOOL fgAcceptDgps;   // DGPS Corrections
+  MTK_GPS_BOOL fgAcceptLoc;    // Reference Location
+  MTK_GPS_BOOL fgAcceptTim;    // Reference Time
+  MTK_GPS_BOOL fgAcceptAcq;    // Acquisition Assistance
+  MTK_GPS_BOOL fgAcceptBsv;    // Real-Time Integrity
+} MTK_GPS_AGPS_CMD_ACCEPT_MAP_T;
+
+typedef struct
+{
+   UINT32 u4Frame;   // BTS Reference Frame number during which the location estimate was measured [0 - 65535]
+   UINT16 u2WeekNo;  // the GPS week number for which the location estimate is valid
+   UINT32 u4TowMS;   // the GPS TOW (ms) for which the location estimate is valid [0 - 604799999]
+   UINT8 u1FixType;  // the type of measurements performed by the MS [0: 2D or 1: 3D]
+   double dfLat;         // latitude (degree)
+   double dfLon;         // longitude (degree)
+   INT16 i2Alt;      // altitude (m)
+   float fUnc_SMaj;      // semi-major axis of error ellipse (m)
+   float fUnc_SMin;      // semi-minor axis of error ellipse (m)
+   UINT16 u2Maj_brg; // bearing of the semi-major axis (degrees) [0 - 179]
+   float fUnc_Vert;      // Altitude uncertainty
+   UINT8 u1Conf;     // The confidence by which the position is known to be within the shape description, expressed as a percentage. [0 ~ 100] (%)
+   UINT16 u2HSpeed;  // Horizontal speed (km/hr)
+   UINT16 u2Bearing; // Direction (degree) of the horizontal speed [0 ~ 359]
+} MTK_GPS_AGPS_DT_LOC_EST_T;
+
+
+typedef struct               // Satellite Pseudorange Measurement Data
+{
+   UINT8 u1PRN_num;      // Satellite PRN number [1 - 32]
+   UINT8 u1SNR;          // Satellite Signal to Noise Ratio [dBHz} (range 0-63)
+   INT16 i2Dopp;         // Measured Doppler frequency [0.2 Hz] (range +/-6553.6)
+   UINT16 u2Code_whole;   // Satellite Code phase measurement - whole chips
+                    //   [C/A chips] (range 0..1022)
+   UINT16 u2Code_fract;   // Satellite Code phase measurement - fractional chips
+                    //   [2^-10 C/A chips] (range 0..1023)
+   UINT8 u1Mul_Path_Ind; // Multipath indicator (range 0..3)
+                    //   (see TIA/EIA/IS-801 Table 3.2.4.2-7)
+   UINT8 u1Range_RMS_Exp;// Pseudorange RMS error: Exponent (range 0..7)
+                    //   (see TIA/EIA/IS-801 Table 3.2.4.2-8)
+   UINT8 u1Range_RMS_Man;// Pseudorange RMS error: Mantissa (range 0..7)
+                    //   (see TIA/EIA/IS-801 Table 3.2.4.2-8)
+
+} MTK_GPS_AGPS_PRM_SV_DATA_T;        // Satellite Pseudorange Measurement Data
+
+#define AGPS_RRLP_MAX_PRM 14
+typedef struct
+{
+   UINT32 u4Frame;         // [0 - 65535]
+   UINT8 u1NumValidMeas;  // Number of valid measurements available (0..NUM_CH)
+   UINT32 u4GpsTow;        // Time of validity [ms] modulus 14400000
+   MTK_GPS_AGPS_PRM_SV_DATA_T SV_Data[AGPS_RRLP_MAX_PRM];  // Satellite Pseudorange Measurement Data
+} MTK_GPS_AGPS_DT_GPS_MEAS_T;     // RRLP Pseudorange Data
+
+typedef struct
+{
+    UINT8 u1Type;
+} MTK_GPS_AGPS_DT_FTIME_ERR_T;
+
+typedef struct
+{
+    UINT16 u2AckCmd;
+    UINT8 u1Flag;
+} MTK_GPS_AGPS_DT_ACK_T;
+
+typedef struct
+{
+    UINT8 u1Type;
+} MTK_GPS_AGPS_DT_LOC_ERR_T;
+
+typedef struct
+{
+    UINT16 u2BitMap;
+                        //  bit0 0x0001  // almanac
+                        //  bit1 0x0002  // UTC model
+                        //  bit2 0x0004  // ionospheric model
+                        //  bit3 0x0008  // navigation data
+                        //  bit4 0x0010  // DGPS corrections
+                        //  bit5 0x0020  // reference location
+                        //  bit6 0x0040  // reference time
+                        //  bit7 0x0080  // acquisition assistance
+                        //  bit8 0x0100  // Real-Time integrity
+} MTK_GPS_AGPS_DT_REQ_ASSIST_T;
+typedef struct
+{
+
+    UINT8 u1FixType;
+    UINT8 u1FixQuality;
+    UINT8 u1SelectType;
+    double dfWRTSeaLevel;
+    float dfPDOP;
+    float dfHDOP;
+    float dfVDOP;
+
+    UINT8 u1SatNumInUse;
+    UINT8 SVInUsePRNs[MTK_GPS_SV_MAX_NUM];
+
+    UINT8 u1SatNumInView;
+    UINT8 u1SVInViewPRNs[MTK_GPS_SV_MAX_NUM];
+    INT8  u1SVInViewEle[MTK_GPS_SV_MAX_NUM];
+    UINT16 u1SVInViewAzi[MTK_GPS_SV_MAX_NUM];
+    float u1SVInViewSNR[MTK_GPS_SV_MAX_NUM];
+
+} MTK_GPS_AGPS_DT_LOC_EXTRA_T;
+#if defined(AGPS_SUPPORT_GNSS)
+//start for AGPS_SUPPORT_GNSS
+/* for AGPS with GNSS supported GNSS assist bitmap   */
+
+/* The BITMAP is define for PMTK760 coding operation of MODEM/AGPSD/MNL , but NOT the same as GNSS ID(3GPP protocol). */
+#define BITMAP_GPS     0
+#define BITMAP_GLONASS 1
+#define BITMAP_GALILEO 2
+#define BITMAP_BEIDOU  3
+
+
+#define BITINDEX_TMOD    0
+#define BITINDEX_DGNSS   1
+#define BITINDEX_EPH     2
+#define BITINDEX_RTI     3
+#define BITINDEX_DBA     4
+#define BITINDEX_AA      5
+#define BITINDEX_ALM     6
+#define BITINDEX_UTC     7
+#define BITINDEX_AUX     8
+
+#define BITMAP_TMOD    0x0001
+#define BITMAP_DGNSS   0x0002
+#define BITMAP_EPH     0x0004
+#define BITMAP_RTI     0x0008
+#define BITMAP_DBA     0x0010
+#define BITMAP_AA      0x0020
+#define BITMAP_ALM     0x0040
+#define BITMAP_UTC     0x0080
+#define BITMAP_AUX     0x0100
+
+typedef struct
+{
+   //UINT16 u2BitMap;
+   MTK_GPS_BOOL fgReqTime; //commonAssistDataReq: GNSS reference time request flag
+   MTK_GPS_BOOL fgReqLoc;  //commonAssistDataReq: GNSS reference location request flag
+   MTK_GPS_BOOL fgReqIon;  //commonAssistDataReq: GNSS reference Inospheris request flag
+   MTK_GPS_BOOL fgReqEop;  //commonAssistDataReq: GNSS reference EarthOrentationParameters request flag
+   UINT16       u2BitMap[GNSS_ID_MAX_NUM];  //GenerateAssistDataReq:  u2BitMap
+                        //  bit0 0x0001  // Time mode Request
+                        //  bit1 0x0002  // Differential Corrections Request
+                        //  bit2 0x0004  // Navigation Model(Ephemeris) Request
+                        //  bit3 0x0008  // Real-Time Integrity Request
+                        //  bit4 0x0010  // Data Bit Assistance Request
+                        //  bit5 0x0020  // Acquisition Assist Request
+                        //  bit6 0x0040  // Almanac Request
+                        //  bit7 0x0080  // UTC Model Request
+                        //  bit8 0x0100  // Auxiliary Information Request
+} MTK_AGNSS_DT_REQ_ASSIST_T;
+
+typedef struct
+{
+
+   UINT8  u1GnssTimeID;    /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+   INT16 i2DayNo;         /* [0-32767] gnssDayNumber do not report DayNo to server */
+   UINT32 u4Todms;        /* [0-3599999] in seconds */
+   UINT16 u2GnssIDsInUse;   //in-use GNSSID bitmap :
+                           //bit 0:gps
+                           //bit 1:sbas
+                           //bit 2:qzss
+                           //bit 3:galileo
+                           //bit 4:glonass
+                           //bit 5~15:reserved
+
+   UINT8 u1FixType;  // the type of measurements performed by the MS [0: 2D or 1: 3D]
+   double dfLat;         // latitude (degree)
+   double dfLon;         // longitude (degree)
+   INT16 i2Alt;      // altitude (m)
+   float fUnc_SMaj;      // semi-major axis of error ellipse (m)
+   float fUnc_SMin;      // semi-minor axis of error ellipse (m)
+   UINT16 u2Maj_brg; // bearing of the semi-major axis (degrees) [0 - 179]
+   float fUnc_Vert;      // Altitude uncertainty
+   UINT8 u1Conf;     // The confidence by which the position is known to be within the shape description, expressed as a percentage. [0 ~ 100] (%)
+   UINT16 u2HSpeed;  // Horizontal speed (km/hr)
+   UINT16 u2Bearing; // Direction (degree) of the horizontal speed [0 ~ 359]
+
+   UINT16 u4Frame;
+   UINT16 u2GnssIDsUsed;
+
+} MTK_AGNSS_DT_LOC_EST_T;
+
+typedef struct
+{
+
+   UINT16 u1PRN_num;               //
+   MTK_GNSS_ID_ENUM eGnssID;       //in-use GNSSID  :
+                           //bit 0:gps
+                           //bit 1:sbas
+                           //bit 2:qzss
+                           //bit 3:galileo
+                           //bit 4:glonass
+                           //bit 5~15:reserved
+   UINT8 u2SignalID;       //in-use signal ID  :
+                           //now for GPS only support GNSS_SGN_ID_VALUE_GPS_L1C_A
+                           //now for GLONASS only support GNSS_SGN_ID_VALUE_GLONASS_G1
+                           //now for QZSS only support GNSS_SGN_ID_VALUE_QZSS_L1C_A
+
+   UINT8  u1SNR;         //[0..63] SNR
+   INT16  i2Dopp;        // [-32768..32767]
+   UINT32 u4CodePh;      //[0..2097151] ms 21-bits with 2^-21 resolution
+   UINT8  u1CodePhInt;   //[0~127] ms
+   UINT8  u1Mul_Path_Ind;  //[0~3] refer to RRLP table A.9
+
+   UINT8  u1CarryQualInd; //[0~3]
+   UINT32 u1Adr;          //[0..33554431] 25-bits with 2^-10 resolution
+   UINT8  u1Range_RMS_Man ;         //Pseudorange RMS Error mantissa
+   UINT8  u1Range_RMS_Exp;         //Pseudorange RMS Error Exponent
+
+   UINT8  u1SigBitmap;
+}MTK_GPS_AGNSS_PRM_SV_DATA_T;
+#define AGNSS_RRLP_MAX_PRM 24
+typedef struct
+{
+  UINT8 u1NumValidGPSSig;
+  UINT8 u1GPSSigIDs;
+  UINT8 u1NumValidGLOSig;
+  UINT8 u1GLOSigIDs;
+}MTK_AGNSS_SIGNALIDS_T;
+
+typedef struct
+{
+
+   UINT8  u1GnssTimeID;    /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+   INT16  i2DayNo;
+   UINT32 u4Todms;        /* [0-3599999] in ms */
+   UINT16 u2TodFrag;      /* [0-3999] with resolution of 250ns optional */
+   UINT32 u4TodUnc ;         /* [0-127] with resolution of 250ns optional */
+   UINT8  u1NumValidMeas;
+   UINT8  u1NumValidGnss;
+   UINT16 u2GnssIDsInUse;     //in-use GNSSID bitmap
+   MTK_AGNSS_SIGNALIDS_T  u1SignalIDsInUse;   //in-use GNSSID bitmap :
+   UINT8  u1CodePhAmb;     // [0~127 ]the codephase ambiguity in interge ms default set to 0¡£ optional
+   MTK_GPS_AGNSS_PRM_SV_DATA_T SV_Data[AGNSS_RRLP_MAX_PRM];  // Satellite Pseudorange Measurement Data
+
+} MTK_AGNSS_DT_MEAS_T;     // RRLP Pseudorange Data MTK_AGNSS_DT_REQ_ASSIST_T
+//MTK_GPS_AGPS_DT_GPS_MEAS_T
+
+
+/*=== GNSS Common Assistance Data ===*/
+typedef struct
+{
+    UINT8    u1GnssTimeID;    /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+    /**
+     * This field specifies the sequential number of days from the origin of the GNSS System Time as follows:
+     * GPS, QZSS, SBAS  Days from January 6th 1980 00:00:00 UTC(USNO)
+     * Galileo ¡V             TBD;
+     * GLONASS ¡V         Days from January 1st 1996
+     */
+    UINT16   u2DN;           /* [0-32767] gnssDayNumber  */
+    double   dfTod;          /* [0-86399.999] in seconds */
+    double   dfTodRms;       /* K = [0..127], uncertainty r (microseconds) = C*(((1+x)^K)-1), C=0.5, x=0.14 */
+    MTK_GPS_BOOL u1NotifyLeap;   /* [0~1] flag to notify leap second only present when gnss=GLONASS */
+    MTK_GPS_BOOL fgTimeComp;   /* TRUE: indicate ref time compensation from modem , FALSE: no ref time composate   */
+    double   dfTimeDelay;      /* the ref time compensation */
+    UINT8    ganssDayCycleNumber;//INTEGER(0..7) -- GPS Acquisition Assistance Rel-10 Extension
+} MTK_GNSS_ASSIST_TIM_T;
+
+typedef MTK_GPS_ASSIST_LOC_T MTK_GNSS_ASSIST_LOC_T;
+
+/* start for gnss ionospheric model */
+
+//gnss Klobuchar model
+typedef struct
+{
+    UINT8 u1DataID;              /*bit[0..1] : "11"generated by QZSS. aplicable within the area of QZSS */
+                                 /*               "00"generated by GPS,GLONASS.  aplicable worldwild   */
+    MTK_GPS_ASSIST_KLB_T rdata;  /*these field is simillar to GPS Klobuchar struct */
+
+}MTK_GNSS_ASSIST_KLB_T;
+
+//gnss NeQuick model
+typedef struct
+{
+    UINT16  u2Ai0;  /* [0..4095] */
+    UINT16  u2Ai1;  /* [0..4095] */
+    UINT16  u2Ai2;  /* [0..4095] */
+    /* optional field */
+    /**
+      * iono storm flag represent five region: [value 0: no disturbance, value 1: disturbance]
+      *  region 1: for the northern region (60¢X<MODIP<90¢X)
+      *  region 2: for the northern middle region (30¢X<MODIP<60¢X)
+      *  region 3: for the equatorial region (-30¢X<MODIP<30¢X)
+      *  region 4: for the southern middle region (-60¢X<MODIP<-30¢X)
+      *  region 5: for the southern region (-90¢X<MODIP<-60¢X)
+      */
+    UINT8   u2StValidBit;  /*Stormflag valid bitmap to indicate if fgStormFlag is aviliable or not */
+                              /*bit0 -> indicate fgStormFlag[0]  aviliable or not*/
+                              /*bit1 -> indicate fgStormFlag[1]  aviliable or not*/
+                              /*bit2 -> indicate fgStormFlag[2]  aviliable or not*/
+                              /*bit3 -> indicate fgStormFlag[3]  aviliable or not*/
+                              /*bit4 -> indicate fgStormFlag[4]  aviliable or not*/
+    MTK_GPS_BOOL fgStormFlag[5];
+
+}MTK_GNSS_ASSIST_NQK_T;
+
+typedef struct
+{
+    UINT8 u1InoModel;            /*[0~7] 0: INO Klobuchar Model -used for GPS,GLONASS,QZSS */
+                                 /*         1: NeQuick Model          - used for Galileo */
+  union
+  {
+    MTK_GNSS_ASSIST_KLB_T rAKlb;  /*Klobuchar Model  */
+    MTK_GNSS_ASSIST_NQK_T rANqk;  /*NeQuick    Model  */
+ }data;
+
+}MTK_GNSS_ASSIST_ION_T;
+
+/* end for gnss ionospheric model */
+
+
+/* start for gnss earth orientation parameters */
+typedef struct
+{
+    UINT16  u2Teop;         /* [0..65535], EOP data reference time in seconds, scale factor 2^4 seconds */
+    INT32   i4PmX;          /* [-1048576..1048575], X-axis polar motion value at reference time in arc-seconds, scale factor 2^(-20) arc-seconds */
+    INT16   i2PmXdot;       /* [-16384..16383], X-axis polar motion drift at reference time in arc-seconds/day, scale factor 2^(-21) arc-seconds/day */
+    INT32   i4PmY;          /* [-1048576..1048575], Y-axis polar motion value at reference time in arc-seconds, scale factor 2^(-20) arc-seconds */
+    INT16   i2PmYdot;       /* [-16384..16383] Y-axis polar motion drift at reference time in arc-seconds/day, scale factor 2^(-21) arc-seconds/day */
+    INT32   i4DeltaUT1;     /* [-1073741824..1073741823], UT1-UTC diff at reference time in seconds, scale factor 2^(-24) seconds */
+    INT32   i4DeltaUT1dot;  /* [-262144..262143], the rate of UT1-UTC diff at reference time in seconds/day, scale factor 2^(-25) seconds/day */
+} MTK_GNSS_ASSIST_EOP_T;
+/* end for gnss earth orientation parameters */
+
+
+
+
+/*=== GNSS Generic Assistance Data ===*/
+
+/* start for gnss time model */
+/**
+ * in LPP, location server could provide up to 15 GNSS-GNSS system time offset
+ * in RRC/RRLP, location server could provide up to 7 GNSS-GNSS system time offset
+ * i.e. generic assist data is for GPS, time model could provide GPS-GLONASS time offset
+ */
+typedef struct
+{
+    /* note that RRC/RRLP tA0, tA1 range is larger than LPP, although scale factor is the same */
+    MTK_GNSS_ID_ENUM eGnssID;
+    UINT16        u2TmodTOW;  /* [0..65535], the reference time of week TOW , scale factor 2^4 seconds */
+    INT32         i4Ta0;         /* [-67108864..67108863] for LPP, [-2147483648 .. 2147483647] for RRC/RRLP, the bias coefficient, scale factor 2^(-35) seconds */
+    INT16         i2Ta1;         /* [-4096..4095] for LPP, [-8388608 .. 8388607] for RRC/RRLP, the drift coefficient, scale factor 2^(-51) seconds/second */
+    INT8          i1Ta2;         /* [-64..63], the drift rate correction coefficient, scale factor 2^(-68) seconds/second^2 */
+    MTK_GNSS_TO_ID_ENUM   eGnssToId; /* GPS, Galileo, QZSS, GLOANSS */
+    /* optional field */
+    UINT16        u2WeekNo;    /* [0..8191], the reference week */
+    INT8          i1DeltaT;    /* [-128..127], the integer number of seconds of GNSS-GNSS time offset */
+} MTK_GNSS_ASSIST_TMOD_T;
+
+
+typedef MTK_GPS_ASSIST_EPH_T MTK_ASSIST_GPS_EPH_T;
+//aGLONASS EPH
+typedef struct
+{
+  UINT8 u1SvId;  // GLONASS SV PRN number 1~24
+  UINT32 au4Word[12];
+} MTK_GLO_ASSIST_EPH_T;
+
+typedef struct
+{
+  UINT8 u1SvId;  // BD SV PRN number 1~30
+  UINT32 au4Word[15];
+} MTK_BDS_ASSIST_EPH_T;
+
+typedef struct
+{
+    MTK_GNSS_ID_ENUM  eGnssID;
+
+    union
+    {
+       MTK_GPS_ASSIST_EPH_T  rAGpsEph;  /* for GPS eph  */
+       MTK_GLO_ASSIST_EPH_T  rAGloEph;  /* for GLO eph  */
+       MTK_BDS_ASSIST_EPH_T   rABDEph;   /* for BD eph  */
+      // MTK_QZS_ASSIST_EPH_T  rAQzsEph;     /* for GLONASS */
+      // MTK_GAL_ASSIST_EPH_T  rAGalEph;     /* for Gallileo */
+    } data;
+} MTK_GNSS_ASSIST_EPH_T;
+
+//aGLONASS ALM
+typedef struct
+{
+  UINT8 u1SvId;//GLONASS SV PRN:1~24
+  UINT16 u2DayNum;
+  UINT32 au4Word[6];
+} MTK_GLO_ASSIST_ALM_T;
+
+//ABD ALM
+typedef struct
+{
+  UINT8 u1SvId;
+  UINT16 u2DayNum;
+  UINT32 au4Word[8];
+} MTK_BDS_ASSIST_ALM_T;
+
+typedef struct
+{
+    MTK_GNSS_ID_ENUM  eGnssID;
+
+    union
+    {
+       MTK_GPS_ASSIST_ALM_T  rAGpsAlm;  /* for GPS alm  */
+       MTK_GLO_ASSIST_ALM_T  rAGloAlm;  /* for GLONASS alm  */
+       MTK_BDS_ASSIST_ALM_T  rABDAlm;   /* for BDS alm  */
+      // MTK_QZS_ASSIST_ALM_T  rAQzsEph;     /* for GLONASS */
+      // MTK_GAL_ASSIST_ALM_T  rAGalEph;     /* for Gallileo */
+    } data;
+} MTK_GNSS_ASSIST_ALM_T;
+
+/* start for gnss real time integrity */
+
+typedef struct
+{
+   UINT16  u1SVID;
+   UINT8  u1BSignalIDs;  /* identidy the bad signal or signals of a satellite, bit string representation, map to GNSS_SGN_ID_BITMAP_* */
+} MTK_GNSS_ASSIST_BSIG_T;
+
+typedef struct
+{
+    MTK_GNSS_ID_ENUM        eGnssID;
+    UINT8                   u1BsvNum;
+    MTK_GNSS_ASSIST_BSIG_T  rBsv[MGPSID];
+} MTK_GNSS_ASSIST_BSV_T;
+/* end for gnss real time integrity */
+
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+    MTK_GNSS_ID_ENUM  eGnssID;
+    UINT16  u2SvId;         //,GPS:1~32 GLO:65~96
+    UINT8   u1SigID;        /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+    UINT8   u1Conf;         /* [0..100]  only for LPP */
+    double  dfTod;          /* [0-86399.999] in seconds */
+    INT16   i2Dopp0;        /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+    UINT8   i1Dopp1;        /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+    UINT8   u1DoppSR;       /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+    UINT16  u2CodePh;    /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+    UINT8   u1CodePhInt; /* [0..127], integer codephase, scale factor 1ms */
+    UINT8   u1CodePhSR;  /* [0..31], map to value-to-searchwindow table (ms) */
+    UINT16  u2Azim;         /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+    UINT8   u1Elev;         /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+    /* optional field */
+    MTK_GPS_BOOL fgCodePh1023;    /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+    /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+    MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+    UINT8   u1CodeSR;
+
+} MTK_GNSS_ASSIST_ACQ_T;
+/* end for gnss acquisition assistance */
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+   double GPSTOW;
+   double dfGNSSTOD;
+   MTK_GPS_BOOL AzElIncl;
+   MTK_GPS_BOOL UseEph;
+   unsigned char NumSV;
+   UINT16  SV[24];         //,GPS:1~32 GLO:65~96
+   UINT8   u1SigID[24];        /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+   UINT8   u1Conf[24];         /* [0..100]  only for LPP */
+   double  dfTod[24];          /* [0-86399.999] in seconds */
+   INT16   Dopp[24];        /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+   UINT8   DoppRate[24];        /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+   UINT8   DoppSR[24];       /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+   UINT16  Code_Ph[24];    /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+   UINT8   Code_Ph_Int[24]; /* [0..127], integer codephase, scale factor 1ms */
+   UINT8   CodePhSR[24];  /* [0..31], map to value-to-searchwindow table (ms) */
+   UINT8   CodeSR[24];
+   UINT16  Azim[24];         /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+   UINT8   Elev[24];         /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+   /* optional field */
+   MTK_GPS_BOOL fgCodePh1023[24];    /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+   /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+   MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum[24]; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+
+} s_NA_GLO_AcqAss;
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+    double dfGNSSTOD;
+    MTK_GPS_BOOL AzElIncl;
+    MTK_GPS_BOOL UseEph;
+    unsigned char NumSV;
+    UINT16  SV[24];         //,GPS:1~32 GLO:65~96
+    UINT8   u1SigID[24];        /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+    UINT8   u1Conf[24];         /* [0..100]  only for LPP */
+    double  dfTod[24];          /* [0-86399.999] in seconds */
+    INT16   Dopp[24];        /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+    UINT8   DoppRate[24];        /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+    UINT8   DoppSR[24];       /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+    UINT16  Code_Ph[24];    /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+    UINT8   Code_Ph_Int[24]; /* [0..127], integer codephase, scale factor 1ms */
+    UINT8   CodePhSR[24];  /* [0..31], map to value-to-searchwindow table (ms) */
+    UINT8   CodeSR[24];
+    UINT16  Azim[24];         /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+    UINT8   Elev[24];         /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+    /* optional field */
+    MTK_GPS_BOOL fgCodePh1023[24];    /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+    /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+    MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum[24]; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+} MTK_GNSS_ASSIST_ACQ_RAW_DATA_T;
+/* end for gnss acquisition assistance */
+
+/* start for gnss acquisition assistance */
+typedef struct
+{
+    UINT16  Code_Ph[24];    /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+    UINT8   Code_Ph_Int[24]; /* [0..127], integer codephase, scale factor 1ms */
+    UINT8 Acq_GPS_Secs;
+    MTK_GPS_BOOL AzElIncl;
+    MTK_GPS_BOOL UseEph;
+    double dfGNSSTOD;
+    UINT8   CodeSR[24];
+    unsigned char NumSV;
+    UINT16  SV[24];         //,GPS:1~32 GLO:65~96
+    UINT8   u1SigID;        /* GNSS type, map to GNSS_SGN_ID_VALUE_* */
+    UINT8   u1Conf;         /* [0..100]  only for LPP */
+    double  dfTod;          /* [0-86399.999] in seconds */
+    INT16   Dopp[24];        /* [-2048..2047], Doppler (0th order term) value for velocity, scale factor 0.5 m/s in th range from -1024 m/s to +1023.5 m/s */
+    UINT8   DoppRate[24];        /* [0..63], i1DoppRate, Doppler (1th order term) value for acceleration, scale factor 1/210 m/s^2 in the range from -0.2 m/s^2 to +0.1 m/s^2 */
+    UINT8   DoppSR[24];       /* [0..4], defined values: 2.5 m/s, 5 m/s, 10 m/s, 20 m/s, 40 m/s encoded as integer range 0-4 by 2^(-n)*40 m/s, n=0-4 */
+    UINT16  CodePh[24];    /* [0..1022], scale factor 2^(-10) ms in the range from 0 to (1-2^(-10)) ms */
+    UINT8   CodePhInt[24]; /* [0..127], integer codephase, scale factor 1ms */
+    UINT8   CodePhSR[24];  /* [0..31], map to value-to-searchwindow table (ms) */
+    UINT16  Azim[24];         /* [0..511], azimuth angle a, x-degrees of satellite x<=a<x+0.703125, scale factor 0.703125 degrees */
+    UINT8   Elev[24];         /* [0..127], elevation angle e, y-degrees of satellite y>=e<y+0.703125, scale factr 0.703125 degrees */
+    /* optional field */
+    MTK_GPS_BOOL fgCodePh1023;    /* only use if codePhase is 1022, codePhase value is 1023*2^(-10) = (1-2^(-10)) ms */
+    /* if support dopplerUncertaintyExtR10, should ignore dopplerUncertainty field */
+    MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM u1DopExtEnum; /* enumerated value map to 60 m/s, 80 m/s, 100 m/s, 120 ms, and No Information */
+} MTK_GNSS_ASSIST_ACQ_DATA_T;
+/* end for gnss acquisition assistance */
+
+typedef struct
+{
+   UINT32 Code_whole;
+   UINT32 Code_fract;
+
+   UINT16 PRN_num;               //
+   INT8 i1ChannelID;
+   MTK_GNSS_ID_ENUM eGnssID;       //in-use GNSSID  :
+                           //bit 0:gps
+                           //bit 1:sbas
+                           //bit 2:qzss
+                           //bit 3:galileo
+                           //bit 4:glonass
+                           //bit 5~15:reserved
+   UINT8 u2SignalID;       //in-use signal ID  :
+                           //now for GPS only support GNSS_SGN_ID_VALUE_GPS_L1C_A
+                           //now for GLONASS only support GNSS_SGN_ID_VALUE_GLONASS_G1
+                           //now for QZSS only support GNSS_SGN_ID_VALUE_QZSS_L1C_A
+
+   UINT8  SNR;         //[0..63] SNR
+   INT16  Dopp;        // [-32768..32767]
+   UINT32 u4CodePh;      //[0..2097151] ms 21-bits with 2^-21 resolution
+   UINT8  u1CodePhInt;   //[0~127] ms
+   UINT8  Mul_Path_Ind;  //[0~3] refer to RRLP table A.9
+
+   UINT8  u1CarryQualInd; //[0~3]
+   UINT32 u1Adr;          //[0..33554431] 25-bits with 2^-10 resolution
+   UINT8  Range_RMS_Man ;         //Pseudorange RMS Error mantissa
+   UINT8  Range_RMS_Exp;         //Pseudorange RMS Error Exponent
+}MTK_IS801_SV_DATA_T;
+
+typedef struct
+{
+   UINT8 Time_Ref;     //I4
+   UINT8 TimeRefSrc;   //I4
+   UINT8 NumValidMeas; //U4
+   UINT32 Time_Tow;
+   UINT8  u1GnssTimeID;    /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+   INT16  i2DayNo;        /* [0-] in day */
+   UINT32 u4Todms;        /* [0-3599999] in ms */
+   UINT16 u2TodFrag;      /* [0-3999] with resolution of 250ns optional */
+   UINT32 u4TodUnc ;         /* [0-127] with resolution of 250ns optional */
+   UINT8  u1NumValidMeas;
+   UINT8  u1NumValidGnss;
+   UINT16 u2GnssIDsInUse;     //in-use GNSSID bitmap
+   MTK_AGNSS_SIGNALIDS_T  u1SignalIDsInUse;   //in-use GNSSID bitmap :
+   UINT8  u1CodePhAmb;     // [0~127 ]the codephase ambiguity in interge ms default set to 0¡£ optional
+   MTK_IS801_SV_DATA_T SV_Data[AGNSS_RRLP_MAX_PRM];  // Satellite Pseudorange Measurement Data
+
+}s_API_IS801_GNSS_PRMeas;
+
+/* start for gnss utc model */
+/* for GPS UTC model */
+/*
+typedef struct
+{
+    INT32  i4UtcA1;         //[-8388608..8388607], scale factor 2^(-50) seconds/second
+    INT32  i4UtcA0;         // [-2147483648..2147483647], scale factor 2^(-30) seconds
+    UINT8  u1UtcTot;        // [0..255], scale factor 2^12 seconds
+    UINT8  u1UtcWNt;        // [0..255], scale factor 1 week
+    INT8   i1UtcDeltaTls;   //[-128..127], scale factor 1 second
+    UINT8  u1UtcWNlsf;      // [0..255], scale factor 1 week
+    INT8   i1UtcDN;         // [-128..127], scale factor 1 day
+    INT8   i1UtcDeltaTlsf;  // [-128..127], scale factor 1 second
+} MTK_GPS_ASSIST_UCP_T;
+*/
+
+/* for QZSS UTC model */
+typedef struct
+{
+    INT16   i2UtcA0;         /* [-32768..32767], bias coefficient of GNSS time scale relative to UTC time scale, scale factor 2^(-35) seconds */
+    INT16   i2UtcA1;         /* [-4096..4095], drift coefficient of GNSS time scale relative to UTC time scale, scale factor 2^(-51) seconds/second */
+    INT8    i1UtcA2;         /* [-64..63], drift rate correction coefficient of GNSS time sacel relative to UTC time scale, scale factor 2^(-68) seconds/second^2 */
+    INT8    i1UtcDeltaTls;   /* [-128..127], current or past leap second count, scale factor 1 second */
+    UINT16  u2UtcTot;        /* [0..65535], time data reference time of week, scale factor 2^4 seconds */
+    UINT16  u2UtcWNot;       /* [0..8191], time data reference week number, scale factor 1 week */
+    UINT8   u1UtcWNlsf;      /* [0..255], leap second reference week number, scale factor 1 week */
+    UINT8   u1UtcDN;         /* 4 bits field, leap second reference day number, scale factor 1 day */
+    INT8    i1UtcDeltaTlsf;  /* [-128..127], current or future leap second count, scale factor 1 second */
+} MTK_QZSS_ASSIST_UCP_T;
+
+/* for GLONASS  UTC model */
+typedef struct
+{
+    UINT16  u2nA;            /* [1..1461], callendar day number within four-year period beginning since the leap year, scale factor 1 day */
+    INT32   i4tauC;          /* [-2147483648..2147483647], GLONASS time scale correction to UTC(SU), scale factor 2^(-31) seconds */
+    //optional field                      /* mandatory present if GLONASS-M satellites are presnet in the current GLONASS constellation */
+    INT16   i2b1;            /* [-1024..1023],default 0.  coefficient to determine delta UT1, scale factor 2^(-10) seconds */
+    INT16   i2b2;            /* [-512..511],default 0.      coefficient to determind delta UT1, scale factor 2^(-16) seconds/msd */
+    UINT8   u1kp;            /* 2 bits field, default 0.       notification of expected leap second correction */
+} MTK_GLO_ASSIST_UCP_T;
+
+/* for SBAS  UTC model */
+typedef struct
+{
+    INT32  i4UtcA1wnt;       /* [-8388608..8388607], scale factor 2^(-50) seconds/second */
+    INT32  i4UtcA0wnt;       /* [-2147483648..2147483647], scale factor 2^(-30) seconds */
+    UINT8  u1UtcTot;         /* [0..255], scale factor 2^12 seconds */
+    UINT8  u1UtcWNt;         /* [0..255], scale factor 1 week */
+    INT8   i1UtcDeltaTls;    /* [-128..127], scale factor 1 second */
+    UINT8  u1UtcWNlsf;       /* [0..255], scale factor 1 week */
+    INT8   i1UtcDN;          /* [-128..127], scale factor 1 day */
+    INT8   i1UtcDeltaTlsf;   /* [-128..127], scale factor 1 second */
+    INT8   i1UtcStandardID;  /* [0..7], if GNSS-ID indicates SBAS, this field indicated the UTC stadard used for the SBAS network time indicated by SBAS-ID to UTC relation */
+} MTK_SBAS_ASSIST_UCP_T;
+
+/* for BDS UTC model */
+typedef struct
+{
+    INT32  i4UtcA0;       /* [-2147483648..2147483647], scale factor 2^(-30) seconds */
+    INT32  i4UtcA1;       /*[-8388608..8388607], scale factor 2^(-50) seconds/second */
+    INT8   i1UtcDeltaTls;   /* [-128..127], scale factor 1 second */
+    UINT8  u1UtcWNlsf;       /* [0..255], scale factor 1 week */
+    UINT8  u1UtcDN;          /* [-128..127], scale factor 1 day */
+    INT8   i1UtcDeltaTlsf;   /* [-128..127], scale factor 1 second */
+} MTK_BDS_ASSIST_UCP_T;
+
+
+typedef struct
+{
+    MTK_GNSS_UTC_TYPE_ENUM  u1UtcMd;
+
+    union
+    {
+       MTK_GPS_ASSIST_UCP_T   utcModel1;  /* for GPS */
+       MTK_QZSS_ASSIST_UCP_T  utcModel2;  /* for QZSS */
+       MTK_GLO_ASSIST_UCP_T   utcModel3;  /* for GLONASS */
+       MTK_SBAS_ASSIST_UCP_T utcModel4;  /* for SBAS */
+       MTK_BDS_ASSIST_UCP_T utcModel5;  /* for BDS */       
+    } data;
+} MTK_GNSS_ASSIST_UCP_T;
+/* end for gnss utc model */
+
+/* start for gnss data bit assistance */
+typedef struct
+{
+    MTK_GNSS_ID_ENUM  eGnssID;
+    UINT16   u2GnssTOD;     /* [0..3599999] milli-second, reference time of the first bit of the data modulo 1 hour, scale factor 1 second */
+   // UINT16   u2GnssTODms;   /* [0..999], fractional part of gnssTD, scale factor 1 milli-second */
+    UINT16   u2SvId;
+    UINT8    u1SigType;
+    UINT16   u2DataBitsNum; /* data bit original max is 1024 bits */
+    UINT16   u2Num; /* x th PMTK for this SV-signal */
+    UINT16   u2NumIndex; /* Index; */
+    UINT32   au4Word[16];/* 16Word*4-byte*8-bits = 2^9 =512 bit */
+} MTK_GNSS_ASSIST_DBA_T;
+/* end for gnss data bit assistance */
+
+/* start for gnss aux info */
+typedef struct
+{
+    UINT8   u1SvId;           // PRN GPS:1~32  GLO:1~24
+    UINT8    u1SigAvai;      /* 8 bits field, indicate the ranging signals supported by the satellite indicated by svID */
+    /* optional field */
+    INT8    i1ChannelId;     /* indicate the GLONASS carrier frequency number of the satellite identified by svID */
+                            /* for GLONASS[-7..13]. if there are no this parameter, this para is set "256": 0xff
+                                                      for GPS there is no part for this para in PMTK765.So need to handle this para besides GLONASS  */
+} MTK_GNSS_ASSIST_AUX_ELE_T;
+
+typedef struct
+{
+    //MTK_GNSS_AUX_TYPE_ENUM eType;
+    MTK_GNSS_ID_ENUM eGnssID;
+    UINT8 u1GnssEleNum;
+    MTK_GNSS_ASSIST_AUX_ELE_T  rGnssEle[GNSS_MAX_AUX_SAT_ELEMENT];
+
+} MTK_GNSS_ASSIST_AUX_T;
+/* end for gnss aux info */
+/* for GNSS capbility   */
+
+typedef struct
+{
+    MTK_GNSS_ID_ENUM eGnssID;
+    UINT8            u1SigBitmap;
+} MTK_GNSS_SIGNAL_T;
+
+typedef struct
+{
+    MTK_GPS_BOOL       fgADR;
+    MTK_GPS_BOOL       fgFta;
+    MTK_GPS_BOOL       fgDgnss;
+    UINT8              u1GnssNum;
+    MTK_GNSS_SIGNAL_T  GnssSigIDs[GNSS_ID_MAX_NUM];
+
+    MTK_GPS_AGNSS_PRM_SV_DATA_T SV_Data[AGNSS_RRLP_MAX_PRM];
+} MTK_AGNSS_DT_CAPBILITY_T;
+typedef struct
+{
+
+    UINT8    u1GnssTimeID;    /* gnss system time ID:eque to GNSS-ID(,0-GPS,1-SBAS, 2-QZSS,3-Galileo,4-GLONASS, 5~16 reserved) */
+    /**
+     * This field specifies the sequential number of days from the origin of the GNSS System Time as follows:
+     * GPS, QZSS, SBAS  Days from January 6th 1980 00:00:00 UTC(USNO)
+     * Galileo ¡V             TBD;
+     * GLONASS ¡V         Days from January 1st 1996
+     */
+    UINT16   u2DN;           /* [0-32767] gnssDayNumber  */
+    double   dfTod;          /* [0-86399.999] in seconds */
+    double   dfTodRms;       /* K = [0..127], uncertainty r (microseconds) = C*(((1+x)^K)-1), C=0.5, x=0.14 */
+    double   dfFTime;        // sec, Frame Time correspond to GNSS TOD
+    double   dfFTimeRms;     // ms, Frame Time RMS accuracy
+} MTK_GNSS_ASSIST_FTA_T, MTK_GNSS_AGPS_DT_FTIME_T;    // Fine Time Assistance
+#endif
+//end for AGPS_SUPPORT_GNSS
+typedef struct
+{
+    UINT8    u1Type;                 /* 1: co-clock clock drift ;2:.... */
+    UINT32   u4ClkErrRange;          /* ppb need to convert to ppm */
+    //INT32   u4ClkErrRange;          /* ppb need to convert to ppm */
+}MTK_GPS_ASSIST_FREQ_T;
+typedef struct
+{
+
+    UINT8    u1FtaType;        /* Frame sync aiding type */
+    UINT16   u2WeekNum;        /* [0-32767] gnssWeekNumber  */
+    double   dfTow;            /* [0-604799.999] in seconds */
+    double   dfTowOffset;      /* [0-999.999] in us */
+    UINT8    u1ClkDriftFlag;   // flag of clock drift. 1:
+    double   dfClkDrift;       // clock drift +/-20000 ppb (+/-20ppm)
+    UINT8    errType;
+} MTK_GNSS_ASSIST_FSYNC_T, MTK_GNSS_AGPS_DT_FSYNC_T;    // Fine Time Assistance
+
+typedef struct
+{
+    UINT16 u2Cmd;  // PMTK command ID:
+                       // please get the data arguements in the following corresponding data structure.
+    union
+    {
+        MTK_GPS_AGPS_DT_ACK_T rAck;              // PMTK001
+        MTK_GPS_AGPS_CMD_MODE_T rAgpsMode;       // PMTK290
+        MTK_GPS_AGPS_DT_REQ_ASSIST_T rReqAssist; // PMTK730
+        MTK_GPS_AGPS_DT_LOC_EST_T rLoc;          // PMTK731
+        MTK_GPS_AGPS_DT_GPS_MEAS_T rPRM;         // PMTK732
+        MTK_GPS_AGPS_DT_LOC_ERR_T rLocErr;       // PMTK733
+        MTK_GPS_AGPS_DT_FTIME_T rFTime;          // PMTK734
+        MTK_GPS_AGPS_DT_FTIME_ERR_T rFTimeErr;   // PMTK735
+        MTK_GPS_AGPS_DT_LOC_EXTRA_T rLocExtra;     // PMTK742/743/744
+#if defined(AGPS_SUPPORT_GNSS)
+        MTK_AGNSS_DT_REQ_ASSIST_T  rGnssReqAssist; // PMTK760
+        MTK_AGNSS_DT_LOC_EST_T     rGnssLoc;       // PMTK761
+        MTK_AGNSS_DT_MEAS_T        rGnssPRM;       // PMTK763
+        MTK_AGNSS_DT_CAPBILITY_T   rGnssCap;       // PMTK764
+#endif
+    } uData;
+} MTK_GPS_AGPS_RESPONSE_T;
+
+
+
+#if defined(AGPS_SUPPORT_GNSS)
+typedef struct
+{
+    UINT8 u1Arg1;  // version of Query location parameters: 1:GNSS format  0:GPS format
+    UINT8 u1Arg2;  // if is for early report? 1:early report  0:normal report
+    UINT8 u1Arg3;
+    UINT8 u1Arg4;
+} MTK_GNSS_CMD_LOC_T;
+
+typedef struct
+{
+    UINT8 u1Arg1;  // version of Query measurement parameters: 1:GNSS format  0:GPS format
+    UINT8 u1Arg2;  // if is for early report? 1:early report  0:normal report
+} MTK_GNSS_CMD_MEAS_T;
+
+typedef struct
+{
+    UINT8 u1Arg1;  // 1: Query parameters using GNSS format  0:GPS format
+} MTK_GNSS_CMD_BITMAP_T;
+
+typedef struct
+{
+    UINT8 u1Arg1;  // 1: Query parameters using GNSS format  0:GPS format
+} MTK_GNSS_CMD_CAPB_T;
+#endif
+typedef struct
+{
+  UINT16    u2Cmd;  // PMTK command ID: if the PMTK command has data arguments,
+                        // please assign the data in the following  corresponding data structure.
+  union
+  {
+    MTK_GPS_AGPS_CMD_MODE_T rMode;              // PMTK290
+    MTK_GPS_AGPS_CMD_ACCEPT_MAP_T rAcceptMap;   // PMTK292
+    MTK_GPS_AGPS_CMD_QOP_T rQop;                // PMTK293
+    MTK_GPS_ASSIST_EPH_T rAEph;             // PMTK710
+    MTK_GPS_ASSIST_ALM_T rAAlm;             // PMTK711
+    MTK_GPS_ASSIST_TIM_T rATim;             // PMTK712
+    MTK_GPS_ASSIST_LOC_T rALoc;             // PMTK713
+    MTK_GPS_ASSIST_CLK_T rAClk;             // PMTK714
+    MTK_GPS_ASSIST_KLB_T rAKlb;             // PMTK715
+    MTK_GPS_ASSIST_UCP_T rAUcp;             // PMTK716
+    MTK_GPS_ASSIST_BSV_T rABsv;             // PMTK717
+    MTK_GPS_ASSIST_ACQ_T rAAcq;             // PMTK718
+    MTK_GPS_ASSIST_FTA_T rAFta;             // PMTK719
+    MTK_GPS_ASSIST_DGP_T rARtcm;            // PMTK720
+    MTK_GPS_ASSIST_TOW_T rATow;             // PMTK725
+    MTK_GPS_AGPS_CMD_MA_LOC_T rAMA_Loc;     // PMTK739
+#if defined(AGPS_SUPPORT_GNSS)
+    MTK_GNSS_CMD_LOC_T  rLoc;             // PMTK485,1*   PMTK485,0*
+    MTK_GNSS_CMD_MEAS_T rMeas;            // PMTK486,1*   PMTK486,0*
+    MTK_GNSS_CMD_BITMAP_T rBitMap;        // PMTK487,1*   PMTK487,0*
+    MTK_GNSS_CMD_CAPB_T  rCapb;                 // PMTK493,1* PMTK493,0*
+
+    MTK_GNSS_ASSIST_TIM_T  rAGnssTim;           // PMTK752
+    MTK_GNSS_ASSIST_TMOD_T rAGnssTmod;          // PMTK753
+    MTK_GNSS_ASSIST_ION_T rAGnssIon;            // PMTK754
+    MTK_GNSS_ASSIST_UCP_T rAGnssUcp;            // PMTK755
+    MTK_GNSS_ASSIST_DBA_T rAGnssDba;            // PMTK756
+    MTK_GNSS_ASSIST_BSV_T rAGnssBsv;            // PMTK757
+    MTK_GNSS_ASSIST_ACQ_T rAGnssAcq;            // PMTK758
+    MTK_GNSS_ASSIST_EOP_T rAGnssEop;            // PMTK759
+    MTK_GNSS_ASSIST_AUX_T rAGnssAux;            // PMTK765
+    MTK_GNSS_ASSIST_EPH_T rAGnssEph;            // PMTK710
+    MTK_GNSS_ASSIST_ALM_T rAGnssAlm;            // PMTK713
+    MTK_GNSS_ASSIST_LOC_T rAGnssLoc;            // PMTK712
+    MTK_GNSS_ASSIST_FTA_T rAGnssFta;            // PMTK766
+#endif
+    MTK_GNSS_ASSIST_FSYNC_T rAGnssFsync;        // PMTK768
+    MTK_GPS_ASSIST_FREQ_T rAGPSFreq;            // PMTK680
+  } uData;
+} MTK_GPS_AGPS_CMD_DATA_T;
+
+
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ) )
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack()
+#endif
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_get_param
+ * DESCRIPTION
+ *  Get the current setting of the AGPS Agent
+ * PARAMETERS
+ *  key         [IN]   the configuration you want to know
+ *  value       [OUT]  the current setting
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_get_param (MTK_GPS_PARAM key, void* value, UINT16 srcMod, UINT16 dstMod);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_agps_set_param
+ * DESCRIPTION
+ *  Change the behavior of the AGPS Agent
+ * PARAMETERS
+ *  key         [IN]   the configuration needs to be changed
+ *  value       [IN]   the new setting
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_agps_set_param (MTK_GPS_PARAM key, const void* value, UINT16 srcMod, UINT16 dstMod);
+INT32
+mtk_agps_set_param_with_payload_len (MTK_GPS_PARAM key, const void* value, UINT16 srcMod, UINT16 dstMod, int len);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_agps_disaptcher_callback
+ * DESCRIPTION
+ *  called by MNL when need send data
+ * PARAMETERS
+ *  type: msg type, length: payload length, data: payload pointer
+ * RETURNS
+ *  none
+ *****************************************************************************/
+INT32
+mtk_gps_sys_agps_disaptcher_callback (UINT16 type, UINT16 length, char *data);
+
+#ifdef __cplusplus
+   }  /* extern "C" */
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_bee.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_bee.h
new file mode 100644
index 0000000..06f8933
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_bee.h
@@ -0,0 +1,69 @@
+/***********************************************************************
+*   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) [2009]. All rights reserved.
+*
+*************************************************************************/
+#ifndef MTK_GPS_BEE_H
+#define MTK_GPS_BEE_H
+
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+#include "mtk_gps_type.h"
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_bee_init
+ * DESCRIPTION
+ *  Initialize BEE module
+ * PARAMETERS
+ *  path             [IN]  single-byte null-terminated string of BEET000A folder path
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_bee_init(UINT8 *path);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_bee_uninit
+ * DESCRIPTION
+ *  Un-initialize BEE module
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_bee_uninit(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_bee_gen
+ * DESCRIPTION
+ *  Generate BEE data
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_bee_gen(void);
+
+
+#ifdef __cplusplus
+   }  /* extern "C" */
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_driver_wrapper.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_driver_wrapper.h
new file mode 100644
index 0000000..2ab4442
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_driver_wrapper.h
@@ -0,0 +1,97 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   mtk_gps_driver_wrapper.h
+ *
+ * Description:
+ * ------------
+ *   Prototype of  driver layer API
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_DRIVER_WRAPPER_H
+#define MTK_GPS_DRIVER_WRAPPER_H
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_threads_create
+ * DESCRIPTION
+ *  Create MNL thread in the porting layer
+ * PARAMETERS
+ * void
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32
+mtk_gps_threads_create(MTK_GPS_THREAD_ID_ENUM thread_id);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_threads_release
+ * DESCRIPTION
+ *  Release MNL thread (array) in the porting layer
+ * PARAMETERS
+ * void
+ * RETURNS
+ *  MTK_GPS_ERROR / MTK_GPS_SUCCESS
+ *****************************************************************************/
+INT32
+mtk_gps_threads_release(void);
+
+//----------------------------------------------------------------------------------
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_mnl_run
+ * DESCRIPTION
+ *  RUN MTK Nav Library
+ * PARAMETERS
+ *  default_cfg     [IN]  factory default configuration
+ *  driver_dfg       [IN]  UART/COM PORT setting
+ * RETURNS
+ *  MTK_GPS_BOOT_STATUS
+ *****************************************************************************/
+MTK_GPS_BOOT_STATUS
+mtk_gps_mnl_run(const MTK_GPS_INIT_CFG* default_cfg, const MTK_GPS_DRIVER_CFG* driver_dfg);
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_mnl_stop
+ * DESCRIPTION
+ *  STOP MTK Nav Library
+ * PARAMETERS
+ * void
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void
+mtk_gps_mnl_stop(void);
+
+
+INT32
+mtk_gps_sys_event_wait_timeout(MTK_GPS_EVENT_ENUM event_idx,int time_sec);
+
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_DRIVER_WRAPPER_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp.h
new file mode 100644
index 0000000..dc64f28
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp.h
@@ -0,0 +1,90 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   mtk_gps_sys_fp.h
+ *
+ * Description:
+ * ------------
+ *   Marco porting layer APT to Function pointer using by MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_SYS_FP_H
+#define MTK_GPS_SYS_FP_H
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+extern INT32 (*gfpmtk_gps_sys_gps_mnl_callback )(MTK_GPS_NOTIFICATION_TYPE);
+extern INT32 (*gfpmtk_gps_sys_nmea_output_to_app)(const char *,UINT32);
+extern INT32 (*gfpmtk_gps_sys_nmea_output_to_mnld)(const char *,UINT32);
+extern INT32 (*gfpmtk_gps_sys_frame_sync_enable_sleep_mode)(unsigned char);
+extern INT32 (*gfpmtk_gps_sys_frame_sync_meas_req_by_network)(void);
+extern INT32 (*gfpmtk_gps_sys_frame_sync_meas_req) (MTK_GPS_FS_WORK_MODE);
+extern INT32 (*gfpmtk_gps_sys_agps_disaptcher_callback) (UINT16, UINT16, char *);
+extern void  (*gfpmtk_gps_sys_pmtk_cmd_cb)(UINT16);
+extern int   (*gfpSUPL_encrypt)(unsigned char *, unsigned char *, unsigned int );
+extern int   (*gfpSUPL_decrypt)(unsigned char *, unsigned char *, unsigned int );
+extern INT32 (*gfmtk_gps_sys_alps_gps_dbg2file_mnld)(const char * buffer, UINT32 length);
+
+extern INT32 (*gfmtk_gps_ofl_sys_rst_stpgps_req)(void);
+extern INT32 (*gfmtk_gps_ofl_sys_submit_flp_data)(UINT8 *buf, UINT32 len);
+extern INT32 (*gfmtk_gps_ofl_sys_mnl_offload_cb)(MTK_GPS_OFL_CB_TYPE, UINT16, UINT8 *);
+
+typedef struct
+{
+    INT32  (*sys_gps_mnl_callback)(MTK_GPS_NOTIFICATION_TYPE );
+    INT32  (*sys_nmea_output_to_app)(const char *,UINT32);
+    INT32  (*sys_nmea_output_to_mnld)(const char *,UINT32);
+    INT32  (*sys_frame_sync_enable_sleep_mode)(unsigned char );
+    INT32  (*sys_frame_sync_meas_req_by_network)(void );
+    INT32  (*sys_frame_sync_meas_req)(MTK_GPS_FS_WORK_MODE );
+    INT32  (*sys_agps_disaptcher_callback)(UINT16, UINT16, char * );
+    void   (*sys_pmtk_cmd_cb)(UINT16 );
+    int    (*encrypt)(unsigned char *, unsigned char *, unsigned int );
+    int    (*decrypt)(unsigned char *, unsigned char *, unsigned int );
+
+    INT32  (*ofl_sys_rst_stpgps_req)(void);
+    INT32  (*ofl_sys_submit_flp_data)(UINT8 *buf, UINT32 len);
+
+    INT32 (*sys_alps_gps_dbg2file_mnld)(const char * buffer, UINT32 length);
+
+    // 2016.10.30 add for MNL offload
+    INT32  (*ofl_sys_mnl_offload_callback)(MTK_GPS_OFL_CB_TYPE, UINT16 , UINT8 *);
+    INT32  (*sys_gps_mnl_data2mnld_callback)(const char *, UINT32);
+} MTK_GPS_SYS_FUNCTION_PTR_T;
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_function_registery
+ * DESCRIPTION
+ *  register the body of function pointer
+ * PARAMETERS
+ *  fp_t     [IN]  function pointer API
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+INT32
+mtk_gps_sys_function_register (MTK_GPS_SYS_FUNCTION_PTR_T *fp_t);
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_SYS_FP_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp_macro.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp_macro.h
new file mode 100644
index 0000000..46fb9ec
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_sys_fp_macro.h
@@ -0,0 +1,55 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   mtk_gps_sys_fp.h
+ *
+ * Description:
+ * ------------
+ *   Marco porting layer APT to Function pointer using by MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_SYS_FP_MACRO_H
+#define MTK_GPS_SYS_FP_MACRO_H
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#define  mtk_gps_sys_gps_mnl_callback                    gfpmtk_gps_sys_gps_mnl_callback
+#define  mtk_gps_sys_nmea_output_to_app                  gfpmtk_gps_sys_nmea_output_to_app
+#define  mtk_gps_sys_nmea_output_to_mnld                 gfpmtk_gps_sys_nmea_output_to_mnld
+#define  mtk_gps_sys_frame_sync_enable_sleep_mode        gfpmtk_gps_sys_frame_sync_enable_sleep_mode
+#define  mtk_gps_sys_frame_sync_meas_req_by_network      gfpmtk_gps_sys_frame_sync_meas_req_by_network
+#define  mtk_gps_sys_frame_sync_meas_req                 gfpmtk_gps_sys_frame_sync_meas_req
+#define  mtk_gps_sys_agps_disaptcher_callback            gfpmtk_gps_sys_agps_disaptcher_callback
+#define  mtk_gps_sys_pmtk_cmd_cb                         gfpmtk_gps_sys_pmtk_cmd_cb
+#define  SUPL_encrypt                                    gfpSUPL_encrypt
+#define  SUPL_decrypt                                    gfpSUPL_decrypt
+#define  mtk_gps_sys_alps_gps_dbg2file_mnld              gfmtk_gps_sys_alps_gps_dbg2file_mnld
+
+#define mtk_gps_ofl_sys_rst_stpgps_req      gfmtk_gps_ofl_sys_rst_stpgps_req
+#define mtk_gps_ofl_sys_submit_flp_data     gfmtk_gps_ofl_sys_submit_flp_data
+#define mtk_gps_ofl_sys_mnl_offload_cb      gfmtk_gps_ofl_sys_mnl_offload_cb
+#define  mtk_gps_sys_msg_output_to_app                   gfpmtk_gps_sys_msg_output_to_app
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_SYS_FP_MACRO_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_type.h b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_type.h
new file mode 100644
index 0000000..68f6201
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/inc/mtk_gps_type.h
@@ -0,0 +1,3601 @@
+/***********************************************************************
+*   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) [2008]. All rights reserved.
+*
+*************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   mtk_gps_type.h
+ *
+ * Description:
+ * ------------
+ *   Data types used by MTK navigation library
+ *
+ ****************************************************************************/
+
+#ifndef MTK_GPS_TYPE_H
+#define MTK_GPS_TYPE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#define MTK_GPS_SV_MAX_NUM      48
+#define MTK_GPS_SV_MAX_PRN      32
+#define MTK_QZS_SV_MAX_PRN      5   // QZSS PRN : 193~197
+#define MTK_GLEO_SV_MAX_NUM     53  // Galileo SV number, should be >= MGLEOID
+#define MTK_GLON_SV_MAX_NUM     24  // Glonass SV number, should be >= MGLONID
+#define MTK_BEDO_SV_MAX_NUM     37  // Beidou SV number, should be >= MBEDOID
+#define MTK_GPS_ENABLE_DEBUG_MSG (0x01)
+#define MTK_GPS_NMEA_SOCKET_DISABLE (0xFFFFF)
+#define MTK_GPS_LIB_VER_LEN_MAX      64
+
+/**The file & data lenght and type number definition for MTKNAV**/
+#define AGT_MTKNAV_TYPE_MAX_LEN (1024)  //The max length of one type is 1kB
+
+// MTK_GNSS_CONFIGURATION for AGNSS part
+#define MTK_CONFIG_AGPS_MODE_BIT_MASK     (1 << 8)
+#define MTK_CONFIG_AGLONASS_MODE_BIT_MASK (1 << 9)
+#define MTK_CONFIG_ABEIDOU_MODE_BIT_MASK  (1 << 10)
+
+#define AGPS_SET_GPS_ENABLE               ((0x01<<0) & (0xFF))
+#define AGPS_SET_GLONASS_ENABLE           ((0x01<<1) & (0xFF))
+#define AGPS_SET_BEIDOU_ENABLE            ((0x01<<2) & (0xFF))
+#define AGPS_SET_GALILEO_ENABLE           ((0x01<<3) & (0xFF))
+#define AGPS_SET_AGLONASS_ENABLE          ((0x01<<4) & (0xFF))
+#define AGPS_SET_AGPS_ENABLE              ((0x01<<5) & (0xFF))
+#define AGPS_SET_ABEIDOU_ENABLE           ((0x01<<6) & (0xFF))
+#define AGPS_SET_AGALILEO_ENABLE          ((0x01<<7) & (0xFF))
+
+
+/*******************************************************************************
+ * Type Definitions
+ *******************************************************************************/
+typedef  unsigned int             UINT4;
+typedef  signed int               INT4;
+
+typedef unsigned char           UINT8;
+typedef signed char             INT8;
+
+typedef unsigned short int      UINT16;
+typedef signed short int        INT16;
+
+typedef unsigned int            UINT32;
+typedef signed int              INT32;
+
+typedef signed long long       INT64;
+
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ))
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack(4)
+#endif
+
+// GPS Measurement
+
+#define MTK_GPS_MEASUREMENT_HAS_SNR                                            (1<<0) // A valid 'snr' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_ELEVATION                                (1<<1) // A valid 'elevation' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY        (1<<2) // A valid 'elevation uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_AZIMUTH                                    (1<<3) // A valid 'azimuth' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY            (1<<4) // A valid 'azimuth uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_PSEUDORANGE                            (1<<5) // A valid 'pseudorange' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY   (1<<6) // A valid 'pseudorange uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CODE_PHASE                              (1<<7) // A valid 'code phase' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY      (1<<8) // A valid 'code phase uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9) // A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_CYCLES                       (1<<10) // A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_PHASE                         (1<<11) // A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12) // A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_BIT_NUMBER                               (1<<13) // A valid 'bit number' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT               (1<<14) // A valid 'time from last bit' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                         (1<<15) // A valid 'doppler shift' is stored in the data structure. */
+#define MTK_GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16) // A valid 'doppler shift uncertainty' is stored in the data structure.
+#define MTK_GPS_MEASUREMENT_HAS_USED_IN_FIX                              (1<<17) // A valid 'used in fix' flag is stored in the data structure.
+
+#define MTK_GPS_LOSS_OF_LOCK_UNKNOWN      0 // The indicator is not available or it is unknown.
+#define MTK_GPS_LOSS_OF_LOCK_OK                  1 // The measurement does not present any indication of loss of lock.
+#define MTK_GPS_LOSS_OF_LOCK_CYCLE_SLIP   2 // Loss of lock between previous and current observation: cycle slip possible.
+
+#define MTK_GPS_MULTIPATH_INDICATOR_UNKNOWN     0 // The indicator is not available or unknown.
+#define MTK_GPS_MULTIPATH_INDICATOR_DETECTED     1 // The measurement has been indicated to use multipath.
+#define MTK_GPS_MULTIPATH_INDICATOR_NOT_USED     2 // The measurement has been indicated Not to use multipath.
+
+#define MTK_GPS_MEASUREMENT_STATE_UNKNOWN              0
+#define MTK_GPS_MEASUREMENT_STATE_CODE_LOCK            (1<<0)
+#define MTK_GPS_MEASUREMENT_STATE_BIT_SYNC               (1<<1)
+#define MTK_GPS_MEASUREMENT_STATE_SUBFRAME_SYNC   (1<<2)
+#define MTK_GPS_MEASUREMENT_STATE_TOW_DECODED      (1<<3)
+
+#define MTK_GPS_ADR_STATE_UNKNOWN                       0
+#define MTK_GPS_ADR_STATE_VALID                     (1<<0)
+#define MTK_GPS_ADR_STATE_RESET                     (1<<1)
+#define MTK_GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+// Gps Clock
+#define MTK_GPS_CLOCK_HAS_LEAP_SECOND             (1<<0)  // A valid 'leap second' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_TIME_UNCERTAINTY   (1<<1)  // A valid 'time uncertainty' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_FULL_BIAS                  (1<<2)  // A valid 'full bias' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_BIAS                            (1<<3)  // A valid 'bias' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_BIAS_UNCERTAINTY   (1<<4)  // A valid 'bias uncertainty' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_DRIFT                          (1<<5 ) // A valid 'drift' is stored in the data structure.
+#define MTK_GPS_CLOCK_HAS_DRIFT_UNCERTAINTY  (1<<6) // A valid 'drift uncertainty' is stored in the data structure.
+
+#define MTK_GPS_CLOCK_TYPE_UNKNOWN                  0
+#define MTK_GPS_CLOCK_TYPE_LOCAL_HW_TIME       1
+#define MTK_GPS_CLOCK_TYPE_GPS_TIME                  2
+
+// Gps NavigationMessage
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN    0
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_L1CA            1 // L1 C/A message contained in the structure.
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV        2 // L2-CNAV message contained in the structure.
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV        3 // L5-CNAV message contained in the structure.
+#define MTK_GPS_NAVIGATION_MESSAGE_TYPE_CNAV2          4 // CNAV-2 message contained in the structure.
+
+#define GPS_DEBUG_LOG_FILE_NAME_MAX_LEN    128 //The max lenght of debug log file name, include the path name
+
+#define ASSIST_REQ_BIT_NTP  0x01    // NTP request bitmap
+#define ASSIST_REQ_BIT_NLP  0x02    // NLP request bitmap
+
+// GNSS Measurement
+#define MTK_GNSS_MAX_SVS 64
+#define MTK_GNSS_MAX_MEASUREMENT   64
+
+typedef UINT32 MTK_GnssMeasurementflags;
+#define MTK_GNSS_MEASUREMENT_HAS_SNR                               (1<<0)/** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)/** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)/** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)/** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE      (1<<18)
+
+typedef UINT16 MTK_GnssAccumulatedDeltaRangestate;
+#define MTK_GNSS_ADR_STATE_UNKNOWN                       0
+#define MTK_GNSS_ADR_STATE_VALID                     (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET                     (1<<1)
+#define MTK_GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+#define MTK_GNSS_ADR_STATE_HALF_CYCLE_RES            (1<<3)  // half cycle resolved 
+
+
+typedef INT16 MTK_GnssNavigationmessageType;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101/** GPS L1 C/A message contained in the structure.  */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602/** Galileo F/NAV message contained in the structure. */
+
+typedef UINT16 MTK_NavigationMessageStatus;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN              0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+typedef UINT8 MTK_GnssSvFlags;
+#define MTK_GNSS_SV_FLAGS_NONE                      0
+#define MTK_GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA        (1 << 0)
+#define MTK_GNSS_SV_FLAGS_HAS_ALMANAC_DATA          (1 << 1)
+#define MTK_GNSS_SV_FLAGS_USED_IN_FIX               (1 << 2)
+
+typedef UINT32 MTK_GnssMeasurementstate;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+
+typedef UINT8 MTK_GnssConstellationtype;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN      0
+#define MTK_GNSS_CONSTELLATION_GPS          1
+#define MTK_GNSS_CONSTELLATION_SBAS         2
+#define MTK_GNSS_CONSTELLATION_GLONASS      3
+#define MTK_GNSS_CONSTELLATION_QZSS         4
+#define MTK_GNSS_CONSTELLATION_BEIDOU       5
+#define MTK_GNSS_CONSTELLATION_GALILEO      6
+
+// Gnsss Clock
+typedef UINT16 MTK_GnssClockflags;
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS                      (1<<3)/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT                     (1<<5)/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)/** A valid 'drift uncertainty' is stored in the data structure. */
+
+// Gnsss NavigationMessage
+typedef UINT8 MTK_GnssMultipathindicator;
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT                 1/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2/** The measurement is indicated to be not affected by multipath. */
+
+/**QEPO GNSS Bitmap**/
+#define AGT_QEPO_GP_BIT (0x01<<0)
+#define AGT_QEPO_GL_BIT (0x01<<1)
+#define AGT_QEPO_BD_BIT (0x01<<2)
+#define AGT_QEPO_GA_BIT (0x01<<3)
+/****The bit number of QEPO download response result****/
+/****The Lowest 4 bit is the value of QEPO download response(Pass or Fail)****/
+/****The next high 4 bit is the QEPO GNSS  Bitmap****/
+#define MTK_QEPO_RSP_BIT_NUM 4
+
+
+//*****************************************************************************
+// User System Configurations
+//*****************************************************************************
+typedef enum
+{
+    HOST_USER_CONFIG_SYS_1 = 1, // user configuration in system operation
+    HOST_USER_CONFIG_SYS_2 = 2, // user configuration in GPS operation
+    HOST_USER_CONFIG_SYS_3 = 3,  // user configuration in Anti-Jamming Debug
+    HOST_USER_CONFIG_SYS_4 = 4,  //  user configuration for aiding data to NVRAM
+    HOST_USER_CONFIG_SYS_5 = 5,  //  user configuration for aiding almanac data to NVRAM
+    HOST_USER_CONFIG_SYS_6 = 6,  //  user configuration for aiding eph data to NVRAM
+    HOST_USER_CONFIG_SYS_7 = 7,  //  user configuration for aiding position data to NVRAM
+    HOST_USER_CONFIG_SYS_8 = 8,  //  user configuration for aiding time data to NVRAM
+    HOST_USER_CONFIG_SYS_9 = 9,  //  user configuration for clean ehp data from NVRAM
+    HOST_USER_CONFIG_SYS_10 = 10,  //  user configuration for clean alman data from NVRAM
+    HOST_USER_CONFIG_SYS_11 = 11,  //  user configuration for chn test
+    HOST_USER_CONFIG_SYS_12 = 12,  //  user configuration for jammer test
+    HOST_USER_CONFIG_SYS_13 = 13,  //  user configuration for phase test
+    HOST_USER_CONFIG_SYS_14 = 14,  //  user configuration for phase test
+    HOST_USER_CONFIG_SYS_15 = 15,  //  user configuration for time_change_notify
+    HOST_USER_CONFIG_SYS_16 = 16,  //  user configuration for time_update_notify
+    HOST_USER_CONFIG_SYS_17 = 17,  //  user configuration for debug_config
+    HOST_USER_CONFIG_SYS_18 = 18,  //  user configuration for update NVfile immedate
+    HOST_USER_CONFIG_SYS_19 = 19,  //  user configuration for setting tcxo mode
+      HOST_USER_CONFIG_SYS_20 = 20,  //  user configuration for TSX XVT
+    HOST_USER_CONFIG_SYS_21 = 21,  //  user configuration for GNSS jammer test
+    HOST_USER_CONFIG_SYS_END  //  user configuration for aiding almanac data to NVRAM
+}MTK_GPS_USER_SYSTEM_CONFIG;
+
+#define USER_SYS_1_ENABLE_DEBUG ( 1 << 0)
+#define USER_SYS_2_TRIGGER_PPS ( 1 << 0)
+
+//*****************************************************************************
+// User System Stauts
+//*****************************************************************************
+typedef enum
+{
+    USER_SYS_ANT_STATUS = 1
+}MTK_GPS_SYSTEM_STATUS;
+#define MTK_SYS_ANT_STATUS_AOK ( 1 << 0)
+#define MTK_SYS_ANT_STATUS_ASHORT ( 1 << 1)
+
+
+
+typedef enum
+{
+  MTK_GPS_FALSE = 0,
+  MTK_GPS_TRUE = 1
+} MTK_GPS_BOOL;
+
+typedef enum
+{
+  MTK_GPS_START_DEFAULT = 0,
+  MTK_GPS_START_HOT,
+  MTK_GPS_START_WARM,
+  MTK_GPS_START_COLD,
+  MTK_GPS_START_FULL,
+  MTK_GPS_START_BATTERY,
+  MTK_GPS_START_AGPS,
+  MTK_GPS_START_D_EPH_ALM, // delete ephemeris and almanac only
+  MTK_GPS_START_D_TIME     // delete time only
+} MTK_GPS_START_TYPE;
+
+typedef enum
+{
+  MTK_GPS_START_RESULT_ERROR = 0,
+  MTK_GPS_START_RESULT_OK
+} MTK_GPS_START_RESULT;
+
+typedef enum
+{
+  MTK_GPS_MSG_FIX_READY,
+  MTK_GPS_MSG_DEBUG_READY,
+  MTK_GPS_MSG_CONFIG_READY,
+  MTK_GPS_MSG_TEST_STATUS_READY,
+  MTK_GPS_MSG_BUFFER_ENOUGH,
+  MTK_GPS_MSG_AGPS_RESPONSE,
+  MTK_GPS_MSG_PMTK_RESPONSE,
+  MTK_GPS_MSG_FIX_PROHIBITED,
+  MTK_GPS_MSG_ASSIST_READY,
+  MTK_GPS_MSG_MNL_START,
+  MTK_GPS_MSG_MNL_RESTART_NTF,
+  MTK_GPS_MSG_MNL_INIT_FAIL,
+  MTK_GPS_MSG_REQUEST_NW_LOCATION,
+  MTK_GPS_MSG_NEED_RESTART
+} MTK_GPS_NOTIFICATION_TYPE;
+
+typedef enum
+{
+  MTK_GPS_FIX_Q_INVALID = 0,
+  MTK_GPS_FIX_Q_GPS = 1,
+  MTK_GPS_FIX_Q_DGPS = 2,
+  MTK_GPS_FIX_Q_EST = 6
+} MTK_GPS_FIX_QUALITY;
+
+typedef enum
+{
+  MTK_GPS_FIX_TYPE_INVALID = 1,
+  MTK_GPS_FIX_TYPE_2D = 2,
+  MTK_GPS_FIX_TYPE_3D = 3
+} MTK_GPS_FIX_TYPE;
+
+typedef enum
+{
+  MTK_DGPS_MODE_NONE = 0,
+  MTK_DGPS_MODE_RTCM = 1,
+  MTK_DGPS_MODE_SBAS = 2,
+  MTK_DGPS_MODE_AUTO = 3
+} MTK_GPS_DGPS_MODE;
+
+typedef enum
+{
+  MTK_AGPS_MODE_NONE = 1,
+  MTK_AGPS_MODE_SUPL = 2,
+  MTK_AGPS_MODE_EPO  = 4,
+  MTK_AGPS_MODE_BEE  = 8,
+  MTK_AGPS_MODE_AUTO = 16
+} MTK_GPS_AGPS_MODE;
+
+// Thread definition
+typedef enum
+{
+    MTK_MOD_NIL = 0,
+    MTK_MOD_MNL,
+    MTK_MOD_DSPIN,
+    MTK_MOD_PMTKIN,
+    MTK_MOD_AGENT,
+    MTK_MOD_BEE_GEN,
+    MTK_MOD_DISPATCHER,
+    MTK_MOD_RTCM,
+    MTK_MOD_EPO_FILE_UPDATER,
+    MTK_MOD_END_LIST
+} MTK_GPS_MODULE;
+
+// API from Dispatcher to Agent
+typedef enum
+{
+    MTK_AGPS_MSG_EPO = 0,
+    MTK_AGPS_MSG_BEE,
+    MTK_AGPS_MSG_SUPL,
+    MTK_AGPS_MSG_SUPL_PMTK,
+    MTK_AGPS_MSG_PROFILE,
+    MTK_AGPS_MSG_SUPL_TERMINATE,  //dispatcher send terminate to indicate SUPL stop
+    MTK_AGPS_MSG_REQ_NI,          //request AGPS aiding from dispatcher
+    MTK_AGPS_MSG_REQ,             //request AGPS aiding from mnl
+    MTK_AGPS_MSG_AGT_BEE_REQ,     //AGENT request next mode(BEE)
+    MTK_AGPS_MSG_AGT_SUPL_REQ,    //AGENT request next mode(SUPL)
+    MTK_AGPS_MSG_REQ_QEPO,        //MNL request quarter EPO
+    MTK_AGPS_MSG_TERMINATE,
+    MTK_AGPS_MSG_EPO_FILE_UPDATE_DONE,   // Notify agent to inject EPO after MNLD update it done
+    MTK_AGPS_MSG_QEPO_RESPONSE,  //Notify agent the QEPO download/update result
+    MTK_AGPS_MSG_LPPE_STATE_SYNC,//Notify agent LPPE status
+    MTK_AGPS_MSG_REQ_MTKNAV,        //MNL request MTKNAV
+    MTK_AGPS_MSG_MTKNAV_RESPONSE,  //Notify agent the MTKNAV download/update result
+    MTK_AGPS_MSG_END_LIST
+} MTK_GPS_AGPS_AGENT_MSG_TYPE;
+
+// Callback from Agent to Dispatcher
+typedef enum
+{
+    MTK_AGPS_CB_SUPL_PMTK = 0,
+    MTK_AGPS_CB_ASSIST_REQ,
+    MTK_AGPS_CB_SUPL_NI_REQ,
+    MTK_AGPS_CB_START_REQ,
+    MTK_AGPS_CB_AGPS_RAWDATA_CONT,
+    MTK_AGPS_CB_BITMAP_UPDATE,      //this message is used for NTP NTP request to MNLD->HAL GPS->locationservice
+    MTK_AGPS_CB_QEPO_DOWNLOAD_REQ,
+    MTK_AGPS_CB_LPPE_ASSIST_REQ,
+    MTK_AGPS_CB_MTKNAV_DOWNLOAD_REQ,
+    MTK_AGPS_CB_END_LIST
+} MTK_GPS_AGPS_CB_MSG_TYPE;
+
+typedef struct
+{
+  UINT32 ntp[2];           //ntp: mini-second, indicate the time tick(mini-second) from Jan.1.1970
+  UINT32 timeReference[2]; //indicate the timestamp of ntp sync with network
+  INT32 uncertainty;
+}MTK_GPS_NTP_T;
+
+typedef struct
+{
+  double lattidude;
+  double longitude;
+  float  accuracy;
+  UINT32 timeReference[2]; //indicate the timestamp of location generated
+  UINT8  type;            // indicate location type: 0: NLP, 1: fixed location
+  UINT8  started ;         // 0 MNL not run / 1 MNL run
+}MTK_GPS_NLP_T;
+
+
+// AGPS feature on/off
+typedef enum
+{
+    MTK_AGPS_FEATURE_OFF = 0,
+    MTK_AGPS_FEATURE_ON = 1
+} MTK_GPS_AGPS_FUNC_ONOFF;
+
+typedef struct
+{
+  UINT8 EPO_enabled;
+  UINT8 BEE_enabled;
+  UINT8 SUPL_enabled;
+  UINT8 SUPLSI_enabled;
+  UINT8 EPO_priority;
+  UINT8 BEE_priority;
+  UINT8 SUPL_priority;
+  UINT8 fgGpsAosp_Ver;
+  UINT8 LPPE_enabled;
+} MTK_AGPS_USER_PROFILE;
+
+typedef struct
+{
+  UINT16    type;           /* message ID */
+  UINT16    length;         /* length of 'data' */
+  char      data[1];        /* message content */
+} MTK_GPS_MSG;
+
+typedef struct
+{
+  UINT16    srcMod;
+  UINT16    dstMod;
+  UINT16    type;           /* message ID */
+  UINT16    length;         /* length of 'data' */
+  char      data[1];        /* message content */
+} MTK_GPS_AGPS_AGENT_MSG;
+//MTK_GPS_AGPS_AGENT_MSG definition need to sync to SUPL msg 's definition
+typedef enum
+{
+  MTK_BEE_DISABLE = 0,
+  MTK_BEE_ENABLE = 1
+} MTK_GPS_BEE_EN;
+
+typedef enum
+{
+  MTK_BRDC_DISABLE = 0,
+  MTK_BRDC_ENABLE = 1
+} MTK_GPS_BRDC_EN;
+
+typedef enum
+{
+  MTK_DBG_DISABLE = 0,
+  MTK_DBG_ERR,
+  MTK_DBG_WRN,
+  MTK_DBG_INFO,
+  MTK_DBG_END
+} MTK_GPS_DBG_LEVEL;
+
+
+typedef enum
+{
+  MDBG_BOOT = 0,
+  MDBG_TIME,
+  MDBG_COMM,
+  MDBG_MEM,
+  MDBG_MSG,
+  MDBG_STORE,
+  MDBG_AL,
+  MDBG_GPS,
+  MDBG_AGPS,
+  MDBG_FS,
+  MDBG_ALL,
+  MDBG_TYPE_END
+} MTK_GPS_DBG_TYPE;
+
+typedef enum
+{
+  MTK_QZSS_DISABLE = 0,
+  MTK_QZSS_ENABLE = 1
+} MTK_QZSS_SEARCH_MODE;
+
+typedef enum
+{
+  MTK_NO_SPEED_FILTERING = 0,
+  MTK_SPEED_FILTERING_0_POINT_2 = 1,
+  MTK_SPEED_FILTERING_0_POINT_4 = 2,
+  MTK_SPEED_FILTERING_0_POINT_6 = 3,
+  MTK_SPEED_FILTERING_0_POINT_8 = 4,
+  MTK_SPEED_FILTERING_1_POINT_0 = 5,
+  MTK_SPEED_FILTERING_1_POINT_5 = 6,
+  MTK_SPEED_FILTERING_2_POINT_0 = 7
+} MTK_LOW_SPEED_FILTERING_MODE;
+
+
+
+typedef struct
+{
+  UINT16    year;           /* years since 1900 */
+  UINT8     month;          /* 0-11 */
+  UINT8     mday;           /* 1-31 */
+  UINT8     hour;           /* 0-23 */
+  UINT8     min;            /* 0-59 */
+  UINT8     sec;            /* 0-59 */
+  UINT8     pad1;
+  UINT16    msec;           /* 0-999 */
+  UINT16    pad2;
+} MTK_GPS_TIME;
+
+typedef enum
+{
+  MTK_TCXO_NORMAL,  //normal mode
+  MTK_TCXO_PHONE    //bad mode
+} MTK_GPS_TCXO_MODE;
+
+typedef enum
+{
+  MTK_AIC_OFF,  //AIC off
+  MTK_AIC_ON    //AIC on
+} MTK_GPS_AIC_MODE;
+
+typedef enum
+{
+  MTK_SIB8_16_OFF,  //SIB8/SIB16 off
+  MTK_SIB8_16_ON   //ASIB8/SIB16 on
+} MTK_GPS_SIB8_16_EN;
+typedef enum
+{
+  MTK_DEBUG2APP_OFF,  //Debug to APP off
+  MTK_DEBUG2APP_ON   //Debug to APP on
+} MTK_GPS_DEBUG2APP_EN;
+
+typedef enum
+{
+  MTK_LPPE_OFF,  //LPPE off
+  MTK_LPPE_ON   //LPPE on
+} MTK_GPS_LPPE_EN;
+
+typedef struct
+{
+  UINT16    version;
+  UINT16    size;
+  MTK_GPS_TIME      utc_time;
+  INT16     leap_second;            /* GPS-UTC time difference */
+  UINT16    WeekNo;                 /* GPS week number */
+  UINT32    TOW;                    /* GPS time of week (integer part) */
+  UINT8     fix_quality;            /* MTK_GPS_FIX_QUALITY for GPGGA */
+  UINT8     fix_type;               /* MTK_GPS_FIX_TYPE for GPGSA */
+  double        clock_drift;            /* clock drift (s/s) */
+  double        clock_bias;             /* clock bias (s) */
+  double        LLH[4];                 /* LLH[0]: Latitude (degree) */
+                                        /* LLH[1]: Longitude (degree) */
+                                        /* LLH[2]: Height WGS84 (m) */
+                                        /* LLH[3]: Height Mean Sea Level (m) */
+  float         gspeed;                 /* 2D ground speed (m/s) */
+  float         vspeed;                 /* vertical speed (m/s) */
+  float         heading;                /* track angle (deg) */
+  float         PDOP, HDOP, VDOP, TDOP; /* dilution of precision */
+  float         EPE[3];                 /* estimated position error (m) */
+                                        /* EPE[0]: North accuracy */
+                                        /* EPE[1]: East accuracy */
+                                        /* EPE[2]: vertical accuracy */
+  float         EVE[3];                 /* estimated velocity error (m/s) */
+                                        /* EVE[0]: North accuracy */
+                                        /* EVE[1]: East accuracy */
+                                        /* EVE[2]: vertical accuracy */
+  float         Pos_2D_Accuracy; // Position Accuracy in Horizontal Direction [m]
+  float         Pos_3D_Accuracy; // Position Accuracy in 3-D space [m]
+  float         Vel_3D_Accuracy;  // Velocity Accuracy in 3-D space [m]
+  float         DGPS_age;               /* time since last DGPS update (s) */
+  UINT16    DGPS_station_ID;
+  UINT8     DGPS_fix_mode;          /* MTK_GPS_DGPS_MODE: 0(N/A); 1(RTCM); 2(SBAS) */
+  UINT8     sv_used_num;            /* for GPGSA */
+  UINT8     sv_in_view_num;         /* for GPGSV */
+  UINT8     sv_used_prn_list[MTK_GPS_SV_MAX_NUM];
+  UINT8     sv_used_type_list[MTK_GPS_SV_MAX_NUM];
+  UINT8     sv_in_view_prn_list[MTK_GPS_SV_MAX_NUM];
+  UINT8     sv_in_view_type_list[MTK_GPS_SV_MAX_NUM];
+  INT8      sv_in_view_elev[MTK_GPS_SV_MAX_NUM];
+  UINT16    sv_in_view_azim[MTK_GPS_SV_MAX_NUM];
+  float     sv_in_view_snr[MTK_GPS_SV_MAX_NUM];
+  UINT8    sv_eph_valid[MTK_GPS_SV_MAX_PRN];  /*  sv ephemeris status 0: no ephemeris, 1: broadcast eph, 2: BEE ephmeris, */
+  UINT8    sv_eph_day[MTK_GPS_SV_MAX_PRN]; /* day of BEE  */
+  UINT8    fgMulti_GNSS;
+} MTK_GPS_POSITION;
+
+typedef struct
+{ /* GPSS/QZSS index 0~31 represents PRN 1~32, respectively */
+  UINT8     health[MTK_GPS_SV_MAX_PRN];   /* nonzero: healthy */
+  UINT8     eph[MTK_GPS_SV_MAX_PRN];      /* nonzero: ephemeris available */
+  UINT8     alm[MTK_GPS_SV_MAX_PRN];      /* nonzero: almanac available */
+  UINT8     dgps[MTK_GPS_SV_MAX_PRN];     /* nonzero: DGPS correction ready */
+  UINT8     codelock[MTK_GPS_SV_MAX_PRN]; /* nonzero: code lock */
+  UINT8     freqlock[MTK_GPS_SV_MAX_PRN]; /* nonzero: frequency lock */
+  UINT8     carrlock[MTK_GPS_SV_MAX_PRN]; /* nonzero: carrier lock */
+
+  /* index 0~4 represents PRN 193~197, respectively */
+  UINT8     qzshealth[MTK_QZS_SV_MAX_PRN];   /* nonzero: healthy */
+  UINT8     qzseph[MTK_QZS_SV_MAX_PRN];      /* nonzero: ephemeris available */
+  UINT8     qzsalm[MTK_QZS_SV_MAX_PRN];      /* nonzero: almanac available */
+  UINT8     qzsdgps[MTK_QZS_SV_MAX_PRN];     /* nonzero: DGPS correction ready */
+  UINT8     qzscodelock[MTK_QZS_SV_MAX_PRN]; /* nonzero: code lock */
+  UINT8     qzsfreqlock[MTK_QZS_SV_MAX_PRN]; /* nonzero: frequency lock */
+  UINT8     qzscarrlock[MTK_QZS_SV_MAX_PRN]; /* nonzero: carrier lock */
+} MTK_GPS_SV_INFO;
+
+typedef struct
+{ /* GALILEO */
+  UINT8     health[MTK_GLEO_SV_MAX_NUM];   /* nonzero: healthy */
+  UINT8     eph[MTK_GLEO_SV_MAX_NUM];      /* nonzero: ephemeris available */
+  UINT8     alm[MTK_GLEO_SV_MAX_NUM];      /* nonzero: almanac available */
+  UINT8     dgps[MTK_GLEO_SV_MAX_NUM];     /* nonzero: DGPS correction ready */
+  UINT8     codelock[MTK_GLEO_SV_MAX_NUM]; /* nonzero: code lock */
+  UINT8     freqlock[MTK_GLEO_SV_MAX_NUM]; /* nonzero: frequency lock */
+  UINT8     carrlock[MTK_GLEO_SV_MAX_NUM]; /* nonzero: carrier lock */
+} MTK_GLEO_SV_INFO;
+
+typedef struct
+{ /* BLONASS PRN 1~24 represents */
+  UINT8     health[MTK_GLON_SV_MAX_NUM];   /* nonzero: healthy */
+  UINT8     eph[MTK_GLON_SV_MAX_NUM];      /* nonzero: ephemeris available */
+  UINT8     alm[MTK_GLON_SV_MAX_NUM];      /* nonzero: almanac available */
+  UINT8     dgps[MTK_GLON_SV_MAX_NUM];     /* nonzero: DGPS correction ready */
+  UINT8     codelock[MTK_GLON_SV_MAX_NUM]; /* nonzero: code lock */
+  UINT8     freqlock[MTK_GLON_SV_MAX_NUM]; /* nonzero: frequency lock */
+  UINT8     carrlock[MTK_GLON_SV_MAX_NUM]; /* nonzero: carrier lock */
+} MTK_GLON_SV_INFO;
+
+typedef struct
+{ // Beidou
+    UINT8     health[MTK_BEDO_SV_MAX_NUM];   /* nonzero: healthy */
+    UINT8     eph[MTK_BEDO_SV_MAX_NUM];      /* nonzero: ephemeris available */
+    UINT8     alm[MTK_BEDO_SV_MAX_NUM];      /* nonzero: almanac available */
+    UINT8     dgps[MTK_BEDO_SV_MAX_NUM];     /* nonzero: DGPS correction ready */
+    UINT8     codelock[MTK_BEDO_SV_MAX_NUM]; /* nonzero: code lock */
+    UINT8     freqlock[MTK_BEDO_SV_MAX_NUM]; /* nonzero: frequency lock */
+    UINT8     carrlock[MTK_BEDO_SV_MAX_NUM]; /* nonzero: carrier lock */
+} MTK_BEDO_SV_INFO;
+
+typedef INT32 (*MTK_GPS_CALLBACK)(MTK_GPS_NOTIFICATION_TYPE msg);
+
+
+typedef enum
+{
+  MTK_DATUM_WGS84,
+  MTK_DATUM_TOKYO_M,
+  MTK_DATUM_TOKYO_A,
+  MTK_DATUM_USER_SETTING,
+  MTK_DATUM_ADINDAN_BURKINA_FASO,
+  MTK_DATUM_ADINDAN_CAMEROON,
+  MTK_DATUM_ADINDAN_ETHIOPIA,
+  MTK_DATUM_ADINDAN_MALI,
+  MTK_DATUM_ADINDAN_MEAN_FOR_ETHIOPIA_SUDAN,
+  MTK_DATUM_ADINDAN_SENEGAL,
+  MTK_DATUM_ADINDAN_SUDAN,
+  MTK_DATUM_AFGOOYE_SOMALIA,
+  MTK_DATUM_AIN_EL_ABD1970_BAHRAIN,
+  MTK_DATUM_AIN_EL_ABD1970_SAUDI_ARABIA,
+  MTK_DATUM_AMERICAN_SAMOA1962_AMERICAN_SAMOA,
+  MTK_DATUM_ANNA_1_ASTRO1965_COCOS_ISLAND,
+  MTK_DATUM_ANTIGU_ISLAND_ASTRO1943_ANTIGUA,
+  MTK_DATUM_ARC1950_BOTSWANA,
+  MTK_DATUM_ARC1950_BURUNDI,
+  MTK_DATUM_ARC1950_LESOTHO,
+  MTK_DATUM_ARC1950_MALAWI,
+  MTK_DATUM_ARC1950_MEAN_FOR_BOTSWANA,
+  MTK_DATUM_ARC1950_SWAZILAND,
+  MTK_DATUM_ARC1950_ZAIRE,
+  MTK_DATUM_ARC1950_ZAMBIA,
+  MTK_DATUM_ARC1950_ZIMBABWE,
+  MTK_DATUM_ARC1960_MEAN_FOR_KENYA_TANZANIA,
+  MTK_DATUM_ARC1960_KENYA,
+  MTK_DATUM_ARC1960_TAMZAMIA,
+  MTK_DATUM_ASCENSION_ISLAND1958_ASCENSION,
+  MTK_DATUM_ASTRO_BEACONE1945_IWO_JIMA,
+  MTK_DATUM_ASTRO_DOS714_ST_HELENA_ISLAND,
+  MTK_DATUM_ASTRO_TERN_ISLAND_FRIG1961_TERN_ISLAND,
+  MTK_DATUM_ASTRONOMICAL_STATION1952_MARCUS_ISLAND,
+  MTK_DATUM_AUSTRALIAN_GEODETIC1966_AUSTRALIA_TASMANIA,
+  MTK_DATUM_AUSTRALIAN_GEODETIC1984_AUSTRALIA_TASMANIA,
+  MTK_DATUM_AYABELLE_LIGHTHOUSE_DJIBOUTI,
+  MTK_DATUM_BELLEVUE_IGN_EFATE_ERROMANGO_ISLAND,
+  MTK_DATUM_BERMUDA1957_BERMUDA,
+  MTK_DATUM_BISSAU_GUUINEA_BISSAU,
+  MTK_DATUM_BOGOTA_OBSERVAORY_COLOMBIA,
+  MTK_DATUM_BUKIT_RIMPAH_INDONESIA,
+  MTK_DATUM_CAMP_AREA_ASTRO_ANTARCTICA,
+  MTK_DATUM_CAMPO_INCHAUSPE_ARGENTINA,
+  MTK_DATUM_CANTON_ASTRO1966_PHOENIX_ISLAND,
+  MTK_DATUM_CAPE_SOUTH_AFRICA,
+  MTK_DATUM_CAPE_CANAVERAL_BAHAMAS_FLORIDA,
+  MTK_DATUM_CARTHAGE_TUNISIA,
+  MTK_DATUM_CHATHAM_ISLAND_ASTRO1971_NEW_ZEALAND,
+  MTK_DATUM_CHUA_ASTRO_PARAGUAY,
+  MTK_DATUM_CORREGO_ALEGRE_BRAZIL,
+  MTK_DATUM_DABOLA_GUINEA,
+  MTK_DATUM_DECEPTION_ISLAND_DECEPTION_ISLAND_ANTARCTIA,
+  MTK_DATUM_DJAKARTA_BATAVIA_INDONESIA_SUMATRA,
+  MTK_DATUM_DOS1968_NEW_GEORGIA_ISLAND_GIZO_ISLAND,
+  MTK_DATUM_EASTER_ISLAND1967_EASTER_ISLAND,
+  MTK_DATUM_ESTONIA_COORDINATE_SYSTEM1937_ESTONIA,
+  MTK_DATUM_EUROPEAN1950_CYPRUS,
+  MTK_DATUM_EUROPEAN1950_EGYPT,
+  MTK_DATUM_EUROPEAN1950_ENGLAND_CHANNEL_ISLANDS_SCOTLAND_SHETLAND_ISLANDS,
+  MTK_DATUM_EUROPEAN1950_ENGLAND_IRELAND_SCOTLAND_SHETLAND_ISLANDS,
+  MTK_DATUM_EUROPEAN1950_FINLAND_NORWAY,
+  MTK_DATUM_EUROPEAN1950_GREECE,
+  MTK_DATUM_EUROPEAN1950_IRAN,
+  MTK_DATUM_EUROPEAN1950_ITALY_SARDINIA,
+  MTK_DATUM_EUROPEAN1950_ITALT_SLCILY,
+  MTK_DATUM_EUROPEAN1950_MALTA,
+  MTK_DATUM_EUROPEAN1950_MEAN_FOR_AUSTRIA_BELGIUM,//_DENMARK_FINLAND_FRANCE_WGERMANY_GIBRALTAR_GREECE_ITALY_LUXEMBOURG_NETHERLANDS_NORWAY_PORTUGAL_SPAIN_SWEDEN_SWITZERLAND,
+  MTK_DATUM_EUROPEAN1950_MEAN_FOR_AUSTRIA_DEBNMARK,//_FRANCE_WGERMANY_NETHERLAND_SWITZERLAND,
+  MTK_DATUM_EUROPEAN1950_MEAN_FOR_IRAG_ISRAEL_JORDAN,//_LEBANON_KUWAIT_SAUDI_ARABIA_SYRIA,
+  MTK_DATUM_EUROPEAN1950_PORTUGAL_SPAIN,
+  MTK_DATUM_EUROPEAN1950_TUNISIA,
+  MTK_DATUM_EUROPEAN1979_MEAN_FOR_AUSTRIA_FINLAND_,//NETHERLANDS_NORWAY_SPAIN_SWEDEN_SWITZERLAND,
+  MTK_DATUM_FORT_THOMAS1955_NEVIS_ST_KITTS_LEEWARD_ISLANDS,
+  MTK_DATUM_GAN1970_REPUBLIC_OF_MALDIVES,
+  MTK_DATUM_GEODETIC_DATAUM1970_NEW_ZEALAND,
+  MTK_DATUM_GRACIOSA_BASE_SW1948_AZORES_FAIAL_GRACIOSA_PICO_SAO,
+  MTK_DATUM_GUAM1963_GUAM,
+  MTK_DATUM_GUNUNG_SEGARA_INDONESIA_KALIMANTAN,
+  MTK_DATUM_GUX_1_ASTRO_GUADALCANAL_ISLAND,
+  MTK_DATUM_HERAT_NORTH_AFGHANISTAN,
+  MTK_DATUM_HERMANNSKOGEL_DATUM_CROATIA_SERBIA_BOSNIA_HERZEGOIVNA,
+  MTK_DATUM_HJORSEY1955_ICELAND,
+  MTK_DATUM_HONGKONG1963_HONGKONG,
+  MTK_DATUM_HU_TZU_SHAN_TAIWAN,
+  MTK_DATUM_INDIAN_BANGLADESH,
+  MTK_DATUM_INDIAN_INDIA_NEPAL,
+  MTK_DATUM_INDIAN_PAKISTAN,
+  MTK_DATUM_INDIAN1954_THAILAND,
+  MTK_DATUM_INDIAN1960_VIETNAM_CON_SON_ISLAND,
+  MTK_DATUM_INDIAN1960_VIETNAM_NEAR16N,
+  MTK_DATUM_INDIAN1975_THAILAND,
+  MTK_DATUM_INDONESIAN1974_INDONESIA,
+  MTK_DATUM_IRELAND1965_IRELAND,
+  MTK_DATUM_ISTS061_ASTRO1968_SOUTH_GEORGIA_ISLANDS,
+  MTK_DATUM_ISTS073_ASTRO1969_DIEGO_GARCIA,
+  MTK_DATUM_JOHNSTON_ISLAND1961_JOHNSTON_ISLAND,
+  MTK_DATUM_KANDAWALA_SRI_LANKA,
+  MTK_DATUM_KERGUELEN_ISLAND1949_KERGUELEN_ISLAND,
+  MTK_DATUM_KERTAU1948_WEST_MALAYSIA_SINGAPORE,
+  MTK_DATUM_KUSAIE_ASTRO1951_CAROLINE_ISLANDS,
+  MTK_DATUM_KOREAN_GEODETIC_SYSTEM_SOUTH_KOREA,
+  MTK_DATUM_LC5_ASTRO1961_CAYMAN_BRAC_ISLAND,
+  MTK_DATUM_LEIGON_GHANA,
+  MTK_DATUM_LIBERIA1964_LIBERIA,
+  MTK_DATUM_LUZON_PHILIPPINES_EXCLUDING_MINDANAO,
+  MTK_DATUM_LUZON_PHILLIPPINES_MINDANAO,
+  MTK_DATUM_MPORALOKO_GABON,
+  MTK_DATUM_MAHE1971_MAHE_ISLAND,
+  MTK_DATUM_MASSAWA_ETHIOPIA_ERITREA,
+  MTK_DATUM_MERCHICH_MOROCCO,
+  MTK_DATUM_MIDWAY_ASTRO1961_MIDWAY_ISLANDS,
+  MTK_DATUM_MINNA_CAMEROON,
+  MTK_DATUM_MINNA_NIGERIA,
+  MTK_DATUM_MONTSERRAT_ISLAND_ASTRO1958_MONTSERRAT_LEEWARD_ISLAND,
+  MTK_DATUM_NAHRWAN_OMAN_MASIRAH_ISLAND,
+  MTK_DATUM_NAHRWAN_SAUDI_ARABIA,
+  MTK_DATUM_NAHRWAN_UNITED_ARAB_EMIRATES,
+  MTK_DATUM_NAPARIMA_BWI_TRINIDAD_TOBAGO,
+  MTK_DATUM_NORTH_AMERICAN1927_ALASKA_EXCLUDING_ALEUTIAN_IDS,
+  MTK_DATUM_NORTH_AMERICAN1927_ALASKA_ALEUTIAN_IDS_EAST_OF_180W,
+  MTK_DATUM_NORTH_AMERICAN1927_ALASKA_ALEUTIAN_IDS_WEST_OF_180W,
+  MTK_DATUM_NORTH_AMERICAN1927_BAHAMAS_EXCEPT_SAN_SALVADOR_ISLANDS,
+  MTK_DATUM_NORTH_AMERICAN1927_BAHAMAS_SAN_SALVADOR_ISLANDS,
+  MTK_DATUM_NORTH_AMERICAN1927_CANADA_ALBERTA_BRITISH_COLUMBIA,
+  MTK_DATUM_NORTH_AMERICAN1927_CANADA_MANITOBA_ONTARIO,
+  MTK_DATUM_NORTH_AMERICAN1927_CANADA_NEW_BRUNSWICK_NEWFOUNDLAND_NOVA_SCOTIA_QUBEC,
+  MTK_DATUM_NORTH_AMERICAN1927_CANADA_NORTHWEST_TERRITORIES_SASKATCHEWAN,
+  MTK_DATUM_NORTH_AMERICAN1927_CANADA_YUKON,
+  MTK_DATUM_NORTH_AMERICAN1927_CANAL_ZONE,
+  MTK_DATUM_NORTH_AMERICAN1927_CUBA,
+  MTK_DATUM_NORTH_AMERICAN1927_GREENLAND_HAYES_PENINSULA,
+  MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_ANTIGUA_BARBADOS_BARBUDA_CAICOS, // _ISLANDS_CUBA_DOMINICAN_GRAND_CAYMAN_JAMAICA_TURKS_ISLANDS,
+  MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_BELIZE_COSTA_RICA_SALVADOR_GUATEMALA,//_HONDURAS_NICARAGUA,
+  MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CANADA,
+  MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CONUS,
+  MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CONUS_EAST_OF_MISSISSIPPI_RIVER, //_INCLUDING_LOUISIANA_MISSOURI_MINNESOTA,
+  MTK_DATUM_NORTH_AMERICAN1927_MEAN_FOR_CONUS_WEST_OF_MISSISSIPPI_RIVER,//_EXCLUDING_LOUISIANA_MINNESOTA_MISSOURI,
+  MTK_DATUM_NORTH_AMERICAN1927_MEXICO,
+  MTK_DATUM_NORTH_AMERICAN1983_ALASKA_EXCLUDING_ALEUTIAN_IDS,
+  MTK_DATUM_NORTH_AMERICAN1983_ALEUTIAN_IDS,
+  MTK_DATUM_NORTH_AMERICAN1983_CANADA,
+  MTK_DATUM_NORTH_AMERICAN1983_CONUS,
+  MTK_DATUM_NORTH_AMERICAN1983_HAHWII,
+  MTK_DATUM_NORTH_AMERICAN1983_MEXICO_CENTRAL_AMERICA,
+  MTK_DATUM_NORTH_SAHARA1959_ALGERIA,
+  MTK_DATUM_OBSERVATORIO_METEOROLOGICO1939_AZORES_CORVO_FLORES_ISLANDS,
+  MTK_DATUM_OLD_EGYPTIAN1907_EGYPT,
+  MTK_DATUM_OLD_HAWAIIAN_HAWAII,
+  MTK_DATUM_OLD_HAWAIIAN_KAUAI,
+  MTK_DATUM_OLD_HAWAIIAN_MAUI,
+  MTK_DATUM_OLD_HAWAIIAN_MEAN_FOR_HAWAII_KAUAI_MAUI_OAHU,
+  MTK_DATUM_OLD_HAWAIIAN_OAHU,
+  MTK_DATUM_OMAN_OMAN,
+  MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_ENGLAND,
+  MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_ENGLAND_ISLE_OF_MAN_WALES,
+  MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_MEAN_FOR_ENGLAND_ISLE_OF_MAN,//_SCOTLAND_SHETLAND_ISLAND_WALES,
+  MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_SCOTLAND_SHETLAND_ISLANDS,
+  MTK_DATUM_ORDNANCE_SURVEY_GREAT_BRITIAN1936_WALES,
+  MTK_DATUM_PICO_DE_LAS_NIEVES_CANARY_ISLANDS,
+  MTK_DATUM_PITCAIRN_ASTRO1967_PITCAIRN_ISLAND,
+  MTK_DATUM_POINT58_MEAN_FOR_BURKINA_FASO_NIGER,
+  MTK_DATUM_POINTE_NOIRE1948_CONGO,
+  MTK_DATUM_PORTO_SANTO1936_PORTO_SANTO_MADERIA_ISLANDS,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_BOLOVIA,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_CHILE_NORTHERN_NEAR_19DS,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_CHILE_SOUTHERN_NEAN_43DS,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_COLOMBIA,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_ECUADOR,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_GUYANA,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_MEAN_FOR_BOLIVIA_CHILE,//_COLOMBIA_ECUADOR_GUYANA_PERU_VENEZUELA,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_PERU,
+  MTK_DATUM_PROVISIONAL_SOUTH_AMERICAN1956_VENEZUELA,
+  MTK_DATUM_PROVISIONAL_SOUTH_CHILEAN1963_CHILE_NEAR_53DS_HITO_XV3,
+  MTK_DATUM_PUERTO_RICO_PUERTO_RICO_VIRGIN_ISLANDS,
+  MTK_DATUM_PULKOVO1942_RUSSIA,
+  MTK_DATUM_QATAR_NATIONAL_QATAR,
+  MTK_DATUM_QORNOQ_GREENLAND_SOUTH,
+  MTK_DATUM_REUNION_MASCARENE_ISLAND,
+  MTK_DATUM_ROME1940_ITALY_SARDINIA,
+  MTK_DATUM_S42_PULKOVO1942_HUNGARY,
+  MTK_DATUM_S42_PULKOVO1942_POLAND,
+  MTK_DATUM_S42_PULKOVO1942_CZECHOSLAVAKIA,
+  MTK_DATUM_S42_PULKOVO1942_LATIVA,
+  MTK_DATUM_S42_PULKOVO1942_KAZAKHSTAN,
+  MTK_DATUM_S42_PULKOVO1942_ALBANIA,
+  MTK_DATUM_S42_PULKOVO1942_ROMANIA,
+  MTK_DATUM_SJTSK_CZECHOSLAVAKIA_PRIOR1_JAN1993,
+  MTK_DATUM_SANTO_DOS1965_ESPIRITO_SANTO_ISLAND,
+  MTK_DATUM_SAO_BRAZ_AZORES_SAO_MIGUEL_SANTA_MARIA_IDS,
+  MTK_DATUM_SAPPER_HILL1943_EAST_FALKLAND_ISLAND,
+  MTK_DATUM_SCHWARZECK_NAMIBIA,
+  MTK_DATUM_SELVAGEM_GRANDE1938_SALVAGE_ISLANDS,
+  MTK_DATUM_SIERRA_LEONE1960_SIERRA_LEONE,
+  MTK_DATUM_SOUTH_AMERICAN1969_ARGENTINA,
+  MTK_DATUM_SOUTH_AMERICAN1969_BOLIVIA,
+  MTK_DATUM_SOUTH_AMERICAN1969_BRAZIAL,
+  MTK_DATUM_SOUTH_AMERICAN1969_CHILE,
+  MTK_DATUM_SOUTH_AMERICAN1969_COLOMBIA,
+  MTK_DATUM_SOUTH_AMERICAN1969_ECUADOR,
+  MTK_DATUM_SOUTH_AMERICAN1969_ECUADOR_BALTRA_GALAPAGOS,
+  MTK_DATUM_SOUTH_AMERICAN1969_GUYANA,
+  MTK_DATUM_SOUTH_AMERICAN1969_MEAN_FOR_ARGENTINA_BOLIVIA_BRAZIL,//_CHILE_COLOMBIA_ECUADOR_GUYANA_PARAGUAY_PERU_TRINIDAD_TOBAGO_VENEZUELA,
+  MTK_DATUM_SOUTH_AMERICAN1969_PARAGUAY,
+  MTK_DATUM_SOUTH_AMERICAN1969_PERU,
+  MTK_DATUM_SOUTH_AMERICAN1969_TRINIDAD_TOBAGO,
+  MTK_DATUM_SOUTH_AMERICAN1969_VENEZUELA,
+  MTK_DATUM_SOUTH_ASIA_SINGAPORE,
+  MTK_DATUM_TANANARIVE_OBSERVATORY1925_MADAGASCAR,
+  MTK_DATUM_TIMBALAI1948_BRUNEI_E_MALAYSIA_SABAH_SARAWAK,
+  MTK_DATUM_TOKYO_JAPAN,
+  MTK_DATUM_TOKYO_MEAN_FOR_JAPAN_SOUTH_KOREA_OKINAWA,
+  MTK_DATUM_TOKYO_OKINAWA,
+  MTK_DATUM_TOKYO_SOUTH_KOREA,
+  MTK_DATUM_TRISTAN_ASTRO1968_TRISTAM_DA_CUNHA,
+  MTK_DATUM_VITI_LEVU1916_FIJI_VITI_LEVU_ISLAND,
+  MTK_DATUM_VOIROL1960_ALGERIA,
+  MTK_DATUM_WAKE_ISLAND_ASTRO1952_WAKE_ATOLL,
+  MTK_DATUM_WAKE_ENIWETOK1960_MARSHALL_ISLANDS,
+  MTK_DATUM_WGS1972_GLOBAL_DEFINITION,
+  MTK_DATUM_WGS1984_GLOBAL_DEFINITION,
+  MTK_DATUM_YACARE_URUGUAY,
+  MTK_DATUM_ZANDERIJ_SURINAME
+} MTK_GPS_DATUM;
+
+/************************************************
+ * defines for set_param and get_param
+ ************************************************/
+/*-------- keys --------*/
+typedef enum
+{
+  MTK_PARAM_CMD_TERMINATE,
+  MTK_PARAM_CMD_RESET_DSP,
+  MTK_PARAM_CMD_RESET_KERNEL,
+  MTK_PARAM_CMD_CONFIG,
+  MTK_PARAM_CMD_TESTMODE,
+  MTK_PARAM_CMD_RESTART,
+  MTK_PARAM_DGPS_CONFIG,
+  MTK_PARAM_NAV_CONFIG,
+  MTK_PARAM_BUF_CONFIG,
+  MTK_PARAM_LIB_VERSION,
+  MTK_PARAM_LIB_RELEASE_INFO,
+  MTK_PARAM_TCXO_SINGLE_CONFIG,
+  MTK_PARAM_TCXO_MULTIPLE_CONFIG,
+  MTK_PARAM_EPH_PROGRESS_CONFIG,
+  MTK_PARAM_EPO_STAGE_CONFIG,
+  MTK_PARAM_CMD_STOP,
+  MTK_PARAM_CMD_SLEEP,
+  MTK_PARAM_CMD_WAKEUP,
+  MTK_PARAM_CMD_BLOCK,
+  MTK_PARAM_BEE_CONFIG,
+  MTK_PARAM_BRDC_CONFIG,
+  MTK_PARAM_FRAME_SYNC_RESP,
+  MTK_PARAM_CMD_CONFIG_EPO_DATA,
+  MTK_PARAM_CMD_CONFIG_EPO_TIME,
+  MTK_PARAM_CMD_CONFIG_EPO_POS,
+  MTK_PARAM_CMD_CLR_CLK_DFT,
+  MTK_MSG_EPO_REQ,
+  MTK_MSG_EPO_RESP,
+  MTK_MSG_BEE_REQ,
+  MTK_MSG_BEE_RESP,
+  MTK_MSG_REQ_ASSIST,
+  MTK_MSG_AGENT_BEE_REQ,
+  MTK_MSG_AGENT_SUPL_REQ,
+  MTK_MSG_BEE_IND,
+  MTK_MSG_AGPS_MSG_REQ_NI,
+  MTK_MSG_AGPS_MSG_SUPL_PMTK,
+  MTK_MSG_AGPS_MSG_SUPL_TERMINATE,
+  MTK_MSG_AGPS_MSG_PROFILE,
+  MTK_MSG_AGPS_MSG_RESET_SM,
+  MTK_MSG_VTIMER_IND,
+  MTK_MSG_AL_CFG,
+  MTK_MSG_AL_DEE_CFG,
+  MTK_PARAM_SYSTEM_CONFIG,
+  MTK_PARAM_SYSTEM_STATUS,
+  MTK_PARAM_CMD_SEARCH_QZSS,
+  MTK_PARAM_CMD_LOW_SPEED_FILTERING,
+  MTK_PARAM_NMEA_OUTPUT,
+  MTK_PARAM_CMD_RTC_CFG,
+  MTK_PARAM_CMD_MNL_INIT,
+  MTK_MSG_AGPS_MSG_AGENT_TERMINATE,
+  MTK_PARAM_QUERY_AGC,
+  MTK_MSG_RAW_MEAS,
+  MTK_MSG_REPLACE_LLH,
+  MTK_MSG_QUARTER_EPO_REQ,
+  MTK_MSG_EPO_FILE_UPDATE_DONE,
+  MTK_PARAM_CMD_AUTO_DESENSE,
+  MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+  MTK_PARAM_NLP_LLA,
+  MTK_PARAM_CMD_SWITCH_CONSTELLATION,
+  MTK_PARAM_CMD_SIB8_16_ENABLE,
+  MTK_PARAM_CMD_LPPE_ENABLE,
+  MTK_AGPS_MSG_SUPL_LPPE_DATA,
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_IONO, // refer to gnss_ha_common_ionospheric_model_struct
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_TROP, // refer to gnss_ha_common_troposphere_model_struct
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_ALT,  // refer to gnss_ha_common_altitude_assist_struct
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_SOLAR,// refer to gnss_ha_common_solar_radiation_struct
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_CCP,  // refer to gnss_ha_common_ccp_assist_struct
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_CCP, // refer to gnss_ha_generic_ccp_assist_struct
+  MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_DM,  // refer to gnss_ha_generic_degradation_model_struct
+  MTK_PARAM_MTKNAV_DOWNLOAD_RESPONSE,
+  MTK_MSG_MTKNAV_REQ,
+  MTK_PARAM_CMD_CONFIG_MTKNAV_CLEAR,
+  MTK_PARAM_CMD_CONFIG_MTKNAV_DATA,
+  MTK_PARAM_CMD_DEBUG2APP_CONFIG,
+} MTK_GPS_PARAM;
+
+/*------- values -------*/
+/* MTK_PARAM_CMD_TERMINATE : terminate GPS main thread: no payload */
+
+/* MTK_PARAM_CMD_CONFIG : schedule an event for get/set aiding data or config:
+   no payload */
+
+/* MTK_PARAM_CMD_TESTMODE : enter/leave a test mode */
+typedef enum
+{
+  MTK_TESTMODE_OFF = 0,
+  MTK_TESTMODE_CHANNEL,
+  MTK_TESTMODE_JAMMER,
+  MTK_TESTMODE_PHASE,
+  MTK_TESTMODE_PER,
+  MTK_TESTMODE_TTICK_OVERFLOW,
+  MTK_TESTMODE_ENTER_MP,
+  MTK_TESTMODE_LEAVE_MP,
+  MTK_TESTMODE_CW_MODE,
+  MTK_TESTMODE_GNSS_JAMMER,
+  MTK_TESTMODE_CN0
+} MTK_GPS_TESTMODE;
+
+typedef struct
+{
+  MTK_GPS_TESTMODE test_mode;
+  UINT8     svid;
+  UINT8     SVid_GLO1;    // SVid_GLO1    :  201 ~214 to represent GLONASS Frequency ID
+  UINT8     SVid_GLO2;    // SVid_GLO2    :  for example, GLONASS FreqID = -7 ==> SVid_GLO1 = -7 +208 = 201;
+  UINT8     SVid_GLO3;    // SVid_GLO3    :  for example, GLONASS FreqID = 6 ==> SVid_GLO1 = 6 +208 = 214;
+  UINT8     SVid_BD;
+  UINT32    time;
+  UINT8     threshold;
+  UINT16    targetCount;
+  UINT8     CN0;
+} MTK_GPS_PARAM_TESTMODE;
+
+#if 1
+//Auto Desense
+
+#define AUTODSN_TEST_CNT_MAX 50
+
+
+typedef enum
+{
+    MTK_GNSS_AUTODSN_STOP = 0,
+    MTK_GNSS_AUTODSN_CW_MODE = 1,
+    MTK_GNSS_AUTODSN_SIGNAL_MODE,
+    MTK_GNSS_AUTODSN_NORMAL_MODE,
+    MTK_GNSS_AUTODSN_MODE_MAX
+}MTK_GNSS_AUTODSN_MODE;
+
+#if 0
+typedef enum
+{
+    MTK_GNSS_AUTODSN_TI_SUSPEND = 1,
+    MTK_GNSS_AUTODSN_TI_LCM_ONOFF,
+    MTK_GNSS_AUTODSN_TI_LCM_UPDATE,
+    MTK_GNSS_AUTODSN_TI_BACKLIGHT,
+    MTK_GNSS_AUTODSN_TI_WIFI_TX,
+    MTK_GNSS_AUTODSN_TI_WIFI_RX,
+    MTK_GNSS_AUTODSN_TI_MAX = 120
+}MTK_GNSS_AUTODSN_TEST_ITEM;
+#endif
+
+typedef struct
+{
+  MTK_GNSS_AUTODSN_MODE test_mode;
+  UINT8     test_item;
+  UINT8     item_state;
+  UINT8     test_count;
+  UINT8     sv_count;
+  UINT8     SVid_GPS;
+  UINT8     SVid_GLO1;    // SVid_GLO1    :  201 ~214 to represent GLONASS Frequency ID
+  UINT8     SVid_GLO2;    // SVid_GLO2    :  for example, GLONASS FreqID = -7 ==> SVid_GLO1 = -7 +208 = 201;
+  UINT8     SVid_GLO3;    // SVid_GLO3    :  for example, GLONASS FreqID = 6 ==> SVid_GLO1 = 6 +208 = 214;
+  UINT8     SVid_BD;
+} MTK_GNSS_PARAM_AUTODSN_MODE;
+
+typedef struct{
+UINT16 sv_id;
+float snr;
+INT8 ele;
+UINT16 azm;
+}MTK_GNSS_BASIC_INFO;
+#endif
+
+/* MTK_PARAM_CMD_RESTART : trigger restart of GPS main thread and dsp code */
+typedef struct
+{
+  MTK_GPS_START_TYPE restart_type;      /* MTK_GPS_START_HOT, MTK_GPS_START_WARM, MTK_GPS_START_COLD, MTK_GPS_START_FULL */
+} MTK_GPS_PARAM_RESTART;
+
+/* MTK_PARAM_BEE_CONFIG : configuration of bee */
+typedef struct
+{
+  MTK_GPS_BEE_EN bee_en;      /* MTK_BEE_DISABLE MTK_BEE_ENABLE */
+} MTK_GPS_PARAM_BEE_CONFIG;
+
+/* MTK_PARAM_BRDC_CONFIG : configuration of broadcast satellite data */
+typedef struct
+{
+  MTK_GPS_BRDC_EN brdc_en;      /* MTK_BRDC_DISABLE MTK_BRDC_ENABLE */
+} MTK_GPS_PARAM_BRDC_CONFIG;
+
+
+typedef struct
+{
+    UINT8  ucSVid;
+    UINT16 u2Weekno;
+    char data[24];
+}MTK_AIDING_PARAM_ALMANAC;
+
+typedef struct
+{
+    UINT8  ucSVid;
+    char data[72];
+}MTK_AIDING_PARAM_EPHEMERIS;
+
+typedef struct
+{
+    UINT16 u2Weekno;
+    double     Tow;
+    float      timeRMS;
+}MTK_AIDING_PARAM_TIME;
+
+typedef struct
+{
+    double LLH[3];
+}MTK_AIDING_PARAM_POSITION;
+
+typedef struct
+{
+    UINT8 SVid;
+    UINT8 SVid_GLO1;
+    UINT8 SVid_GLO2;
+    UINT8 SVid_GLO3;
+    UINT8 SVid_BD;
+    INT32 action;
+}MTK_PARAM_CHN_TEST;
+
+typedef struct
+{
+    UINT16 mode;
+    UINT16 arg;
+    INT32 action;
+}MTK_PARAM_JAMMER_TEST;
+
+typedef struct
+{
+    INT32 action;
+    UINT32 time;
+    UINT8 SVid;
+}MTK_PARAM_PHASE_TEST;
+
+typedef struct
+{
+    INT16 Threshold;
+    UINT16 SVid;
+    UINT16 TargetCount;
+}MTK_PARAM_PER_TEST;
+
+typedef struct
+{
+    UINT8 fgSyncGpsTime;
+    INT32 i4RtcDiff;
+}MTK_PARAM_TIME_UPDATE_NOTIFY;
+
+typedef struct
+{
+    MTK_GPS_DBG_TYPE DbgType;
+    MTK_GPS_DBG_LEVEL DbgLevel;
+}MTK_PARAM_DEBUG_CONFIG;
+
+typedef struct
+{
+   MTK_GPS_NLP_T  NLP;         // indicate location type: 0: NLP, 1: fixed location
+   MTK_GPS_TIME utc;
+   UINT8 read_flag;     // 0 = non-readed / 1 = readed
+}MTK_GPS_NLP_UTC_T;
+
+//mtk_gps_debug_config(mtk_gps_dbg_type DbgType, mtk_gps_dbg_level DbgLevel)
+
+
+/* MTK_PARAM_SYSTEM_CONFIG : configuration of system parameters */
+typedef struct
+{
+  MTK_GPS_USER_SYSTEM_CONFIG system_config_type;   /* system config type */
+  UINT32 system_config_value;              /* set/get system config  value*/
+  MTK_AIDING_PARAM_EPHEMERIS param_eph;
+  MTK_AIDING_PARAM_ALMANAC  param_almanac;
+  MTK_AIDING_PARAM_POSITION param_position;
+  MTK_AIDING_PARAM_TIME     param_time;
+  MTK_PARAM_TIME_UPDATE_NOTIFY param_time_update_notify;
+  MTK_PARAM_DEBUG_CONFIG param_debug_config;
+    //
+  MTK_PARAM_CHN_TEST       param_chn_test;
+  MTK_PARAM_JAMMER_TEST  param_jam_test;
+  MTK_PARAM_PHASE_TEST   param_pha_test;
+  MTK_PARAM_PER_TEST     param_per_test;
+  MTK_GPS_TCXO_MODE      param_tcxo_mode;
+  //
+  INT32 i4RtcDiff;
+  UINT8 TSX_XVT;
+
+} MTK_GPS_PARAM_SYSTEM_CONFIG;
+
+/* MTK_PARAM_SYSTEM_STATUS : status of system parameters */
+typedef struct
+{
+  MTK_GPS_SYSTEM_STATUS system_status_type;   /* system status type */
+  UINT32 system_status_value;              /* set/get system status value*/
+} MTK_GPS_PARAM_SYSTEM_STATUS;
+
+/* MTK_PARAM_DGPS_CONFIG */
+typedef struct
+{
+  MTK_GPS_DGPS_MODE dgps_mode;          /* Off/RTCM/SBAS */
+  UINT8     dgps_timeout;           /* DGPS timeout in seconds */
+  MTK_GPS_BOOL      sbas_test_mode;         /* TRUE=test; FALSE=integrity */
+  UINT8     sbas_prn;               /* 0=automatic; 120-139=specific PRN */
+  MTK_GPS_BOOL      full_correction;        /* SBAS data correction mode */
+                                        /* TRUE=full [Fast/Long-Term and IONO] */
+                                        /* FALSE=partial [Fast/Long-Term or IONO] */
+  MTK_GPS_BOOL      select_corr_only;       /* satellite selection mode */
+                                        /* TRUE=only SVs with corrections */
+                                        /* FALSE=any SVs available */
+} MTK_GPS_PARAM_DGPS_CFG;
+
+/* MTK_PARAM_NAV_CONFIG */
+typedef struct
+{
+  UINT32    fix_interval;           /* fix interval in milliseconds */
+                                        /* 1000=>1Hz, 200=>5Hz, 2000=>0.5Hz */
+  MTK_GPS_DATUM datum;                  /* datum */
+  INT8      elev_mask;              /* elevation angle mask in degree */
+} MTK_GPS_PARAM_NAV_CFG;
+
+/*  MTK_PARAM_BUF_CONFIG */
+typedef struct
+{
+  UINT16    buf_empty_threshold;    /* If the buffer free space reach this value
+                                           then it will report to callback once */
+  UINT16    buf_empty_size;         /* Buffer free space in bytes, read only */
+} MTK_GPS_PARAM_BUF_CFG;
+
+/*  MTK_PARAM_AL_CONFIG : config always locate */
+typedef enum
+{
+  MTK_AL_TYPE_NORMAL        =  0, // Navigation
+  MTK_AL_TYPE_USER_PERIODIC =  1, // User periodic mode
+  MTK_AL_TYPE_AUTO_PERIODIC =  9  // Auto periodic mode
+} MTK_GPS_AL_TYPE;
+
+typedef struct
+{
+  MTK_GPS_AL_TYPE type;                 /* application type */
+  UINT32      u4FirstRunTime;              /* run time for peridic mode, (milli-second) */
+  UINT32      u4FirstSlpTime;              /* sleep time for peridic mode, (milli-second)*/
+  UINT32      u4SecondRunTime;              /* run time for peridic mode, (milli-second) */
+  UINT32      u4SecondSlpTime;              /* sleep time for peridic mode, (milli-second)*/
+} MTK_PARAM_AL_CFG;
+
+typedef struct
+{
+  UINT8       u1SV ;                /* SV number for DEE extension start criterion */
+  UINT8       u1SNR;              /* SNR threshold for DEE extension start criterion */
+  UINT32     u4ExtensionThreshold;     /* Extension time limitation for DEE, (milli-second) */
+  UINT32     u4ExtensionGap;              /* Extension gap limitation between neighbor DEE , (milli-second)*/
+} MTK_PARAM_AL_DEE_CFG;
+typedef struct
+{
+  char           support_lppe ;
+  char      vertion[MTK_GPS_LIB_VER_LEN_MAX];
+} MTK_GPS_MNL_INFO;
+
+typedef struct
+{
+  UINT32     u4EPOWORD[18];        /* 18 words [LSB first] of one EPO segment data (total 72 bytes) */
+  UINT8      u1SatID;              /* 1~32 */
+} MTK_GPS_PARAM_EPO_DATA_CFG;
+
+typedef struct
+{
+  UINT32    u4Type;
+  UINT32    u4Len;
+  UINT32    u4Data[(AGT_MTKNAV_TYPE_MAX_LEN)/sizeof(UINT32)];        /* [LSB first] one type of MTKNAV data  */
+  UINT32    u4Csm;
+} MTK_GPS_PARAM_MTKNAV_DATA_CFG;
+
+typedef struct
+{
+  UINT16      u2YEAR ;             /* > 2000 */
+  UINT8       u1MONTH;             /* 1~12 */
+  UINT8       u1DAY;               /* 1~31*/
+  UINT8       u1HOUR;              /* 0~23*/
+  UINT8       u1MIN;               /* 0~59*/
+  UINT8       u1SEC;               /* 0~59*/
+} MTK_GPS_PARAM_EPO_TIME_CFG;
+
+typedef struct
+{
+  double      dfLAT;              /* > -90 and <90 (degree)*/
+  double      dfLON;              /* > -180 and <180 (degree)*/
+  double      dfALT;              /* (m) */
+  UINT16      u2YEAR;               /* > 2000 */
+  UINT8       u1MONTH;             /* 1~12 */
+  UINT8       u1DAY;               /* 1~31*/
+  UINT8       u1HOUR;              /* 0~23*/
+  UINT8       u1MIN;               /* 0~59*/
+  UINT8       u1SEC;               /* 0~59*/
+} MTK_GPS_PARAM_EPO_POS_CFG;
+
+typedef struct
+{
+  float      r4TcxoOffest;        /*  TCXO offest frequency (Hz)*/
+  UINT8      u1SatID;              /* 1~32 */
+} MTK_GPS_PARAM_TCXO_CFG;
+
+typedef struct
+{
+  float         r4EphProgress[MTK_GPS_SV_MAX_PRN];        /* The current Eph Progress (0~1)*/
+} MTK_GPS_PARAM_EPH_PROGRESS_CFG;
+
+typedef struct
+{
+  UINT32     u4EpoStage;              /* The invalid/valid Epo Stage in bit map format(0/1)*/
+} MTK_GPS_PARAM_EPO_STAGE_CFG;
+
+typedef enum
+{
+  MTK_GPS_FS_RESULT_INIT = 0,           /* FS request initial value  */
+  MTK_GPS_FS_RESULT_ERR,                /* FS request error and clear naram's data  */
+  MTK_GPS_FS_RESULT_ERR_NOT_CLR,        /* FS request error but don't clear nvram's data */
+  MTK_GPS_FS_RESULT_OK                  /* FS request success */
+} MTK_GPS_FS_RESULT;
+
+typedef enum
+{
+  MTK_GPS_FS_WORK_MODE_AIDING = 0,      /* FS request for aiding phase  */
+  MTK_GPS_FS_WORK_MODE_MAINTAIN         /* FS request for maintain phase  */
+} MTK_GPS_FS_WORK_MODE;
+
+/* MTK_PARAM_FRAME_SYNC_RESP : receive a result of a frame sync meas request */
+typedef struct
+{
+  MTK_GPS_FS_RESULT eResult;            /* frame sync measurement request result */
+  double            dfFrameTime;        /* frame time of the issued frame pulse */
+} MTK_GPS_PARAM_FRAME_SYNC_RESP;
+
+/* MTK_PARAM_QZSS_SEARCH_CONFIG : configuration of broadcast satellite data */
+typedef struct
+{
+  MTK_QZSS_SEARCH_MODE qzss_en;      /* MTK_QZSS_DISABLE MTK_QZSS_ENABLE */
+} MTK_PARAM_QZSS_SEARCH_MODE;
+
+
+/* MTK_PARAM_LOW_SPEED_FILTERING_CONFIGURATION : configuration of low speed filtering setting */
+typedef struct
+{
+  MTK_LOW_SPEED_FILTERING_MODE low_speed_filtering_en;      /* MTK_LOW_SPEED_FILTERING_SETTING */
+} MTK_PARAM_LOW_SPEED_FILTERING;
+
+
+
+/* MTK_PARAM_QUERY_AGC : query AGC value */
+typedef struct
+{
+  UINT16 u2AGC;               /* AGC value */
+} MTK_GPS_PARAM_QUERY_AGC_VALUE;
+
+
+/*  MTK_PARAM_PMTK_CMD : receive a PMTK message for BEE safety design */
+#define MTK_PMTK_CMD_MAX_SIZE            256
+typedef struct
+{
+  char pmtk[MTK_PMTK_CMD_MAX_SIZE];         /* Buffer free space in bytes, read only */
+} MTK_GPS_PARAM_PMTK_CMD;
+
+typedef struct
+{
+  UINT16  u2Bitmap;
+  INT16   i2WeekNo;
+  INT32   i4Tow;
+  MTK_GPS_BOOL    fgFirstReq;
+} MTK_GPS_PARAM_AGPS_REQ;
+
+typedef struct
+{
+  UINT16 u2AckCmd;
+  UINT8 u1Flag;
+} MTK_GPS_PMTKD_001T;
+
+typedef struct{
+  double dfRtcDltTime;
+} MTK_GPS_PMTKD_243_T;
+
+typedef struct{
+  MTK_GPS_BOOL fgSet; // reference location: 0 - clear,  1 - set
+  double dfRefLat;
+  double dfRefLon;
+  float fRefAlt;
+} MTK_GPS_PMTKD_244_T;
+
+typedef struct
+{
+    UINT16 u2Cmd;  // PMTK command ID:
+                       // please get the data arguements in the following corresponding data structure.
+    union
+    {
+        MTK_GPS_PMTKD_001T rAck;              // PMTK001
+    } uData;
+} MTK_GPS_PMTK_RESPONSE_T;
+
+typedef struct
+{
+  UINT16    u2Cmd;  // PMTK command ID: if the PMTK command has data arguments,
+                        // please assign the data in the following corresponding data structure.
+  union
+  {
+    MTK_GPS_PMTKD_243_T r243;
+    MTK_GPS_PMTKD_244_T r244;
+  } uData;
+} MTK_GPS_PMTK_DATA_T;
+
+
+typedef struct
+{
+  UINT16 type;
+  UINT16 mcc;
+  UINT16 mnc;
+  UINT16 lac;
+  UINT16 cid;
+} MTK_GPS_REF_LOCATION_CELLID;
+
+typedef struct
+{
+  UINT8 mac[6];
+} MTK_GPS_REF_LOCATION_MAC;
+
+/** Represents ref locations */
+typedef struct
+{
+  UINT16 type; // 0 : Cell ID; 1: MAC
+  union
+  {
+     MTK_GPS_REF_LOCATION_CELLID   cellID;
+     MTK_GPS_REF_LOCATION_MAC      mac;
+  }u;
+} MTK_GPS_REF_LOCATION;
+
+
+typedef enum
+{
+  MTK_IF_SW_EMULATION = 0,
+  MTK_IF_UART_NO_HW_FLOW_CTRL,
+  MTK_IF_UART_HW_FLOW_CTRL,
+  MTK_IF_SPI,
+  MTK_IF_APB
+} MTK_GPS_IF_TYPE;
+
+typedef enum
+{
+  MTK_PPS_DISABLE = 0,
+  MTK_PPS_ATFER_TTFF,
+  MTK_PPS_3D_FIX,
+  MTK_PPS_2D_FIX,
+  MTK_PPS_ALWAYS
+} MTK_GPS_PPS_MODE;
+
+// ******************   Important Notice *************************//
+// In oder to make sure the GNSS configuration works correctly,
+// Please delete "mtk_gps.dat" after change the MTK_GNSS_CONFIGURATION setting.
+typedef enum
+{
+  MTK_CONFIG_GPS_GLONASS = 0,
+  MTK_CONFIG_GPS_BEIDOU,
+  MTK_CONFIG_GPS_GLONASS_BEIDOU,
+  MTK_CONFIG_GPS_ONLY,
+  MTK_CONFIG_BEIDOU_ONLY,
+  MTK_CONFIG_GLONASS_ONLY,
+  MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO,
+  MTK_CONFIG_GPS_GALILEO,  
+  MTK_CONFIG_GPS_GLONASS_GALILEO,
+  MTK_CONFIG_GALILEO_ONLY
+} MTK_GNSS_CONFIGURATION;
+
+typedef struct
+{
+   UINT32 pps_version;
+   UINT16 pps_delay;
+   UINT8  pps_polarity;
+   UINT16 pps_duty;
+} MTK_GPS_PPS_CFG;
+
+
+// for AOSP AGPS:
+//   1. PMTK data don't encript
+//   2. don't output PMTK010 to AGPSD
+typedef enum
+{
+    MTK_GPS_NORMAL_MODE = 0, // used for legacy AGPS
+    MTK_GPS_AOSP_MODE = 1,   // used in AOSP AGPS
+}MTK_GPS_VERSION_MODE;
+
+/* factory default configuration for mtk_gps_init() */
+typedef struct
+{
+  MTK_GPS_IF_TYPE   if_type;        /* interface type UART/SPI */
+  MTK_GPS_PPS_MODE  pps_mode;       /* 1PPS mode, Default: MTK_PPS_3D_FIX */
+  MTK_GPS_DATUM     datum;          /* datum */
+  MTK_GPS_DGPS_MODE dgps_mode;  /* Off/RTCM/SBAS */
+  MTK_GPS_TCXO_MODE tcxo_mode;
+  UINT16    pps_duty;       /* PPS pulse high duration (ms), Range: 0~999, Default: 100 */
+  UINT8     pps_port;       /* pps output port select */
+  UINT8     u1ClockType;    // FLASH_SIG_USE_16368_TCXO         0     // 16.368M integer, the most stable
+                            // FLASH_SIG_USE_16369M_TCXO    1    // 16.369M integer, generated freq has bias
+                            // FLASH_SIG_USE_26M_FRAC_TCXO  2    // not used
+                            // FLASH_SIG_USE_26M_INT_TCXO   3    // 26M integer, generated freq has bias,
+                            // FLASH_SIG_USE_WIDERANGE_XTAL 0xFE // wide range crystal.
+                            // FLASH_SIG_USE_WIDERANGE      0xFF // wide range, more power consumption, no freq bias
+  UINT16    hw_Clock_Drift;    /* TCXO clock drift in ppb (500=0.5ppm; 2500=2.5ppm) */
+  UINT32    hw_Clock_Freq;     /* TCXO frequency in Hz */
+  UINT32    if_link_spd;    /* interface link speed (bps of UART) */
+  UINT32    fix_interval;   /* fix interval in milliseconds */
+                                /* 1000=>1Hz, 200=>5Hz, 2000=>0.5Hz */
+  UINT8     Int_LNA_Config; /* for 3326, 1: internal LNA, for 3336,1: high gain, for 3332, 1: high gain */
+
+  UINT32    reservedx;
+  void*     reservedy;
+  MTK_GNSS_CONFIGURATION  GNSSOPMode;      // In oder to make sure the GNSS configuration works correctly,
+                                           // Please delete "mtk_gps.dat" after change the MTK_GNSS_CONFIGURATION setting.
+  UINT32    C0;
+  UINT32    C1;
+  UINT32    initU;
+  UINT32    lastU;
+  MTK_GPS_VERSION_MODE mtk_gps_version_mode; //AOSP or not
+  UINT8     Int_IMAX_Config; // O: no IMAX test, 1 IMAX
+  UINT8     Jamming_Detection_Msg;  // 0: Disable PMTKSPF message output, 1: Enable PMTKSPF message output
+  UINT32    eLNA_pin_num;  //gps eLNA pin number
+  UINT8     sv_type_agps_set;
+  UINT8     pps_polarity;     /* Range: 0~1   , Default: 0 */
+  UINT16    pps_delay;        /* Range: 0~2000, Default: 0 */
+  INT8      elev_mask;        /* Range: 0~90 */
+} MTK_GPS_INIT_CFG;
+
+
+typedef struct
+{
+  UINT32       nmea_link_spd; //NMEA Baydrate
+  UINT8        DebugType;
+                  // 1: Enable Agent debug
+                   // 0: Disable Agent debug
+  char         nv_file_name[30]; // NV ram file name
+  char         ofl_nv_file_name[30]; // NV ram file name for offload mode
+  char         dbg_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN]; // NMEA dbg file name
+  char         dsp_port_name[30];  //DSP port name
+  char         nmea_port_name[30]; //NMEA out port name
+  char         nmeain_port_name[30];//NMEA in port name
+  UINT8        bee_path_name[30];  // HS patch name
+  UINT8        epo_file_name[30]; // epo working file
+  UINT8        epo_update_file_name[30]; // epo updated file
+  UINT8        qepo_file_name[30]; // qepo working file
+  UINT8        qepo_update_file_name[30]; // qepo updated file
+  UINT8        qepo_bd_file_name[30]; // qepo working file
+  UINT8        qepo_bd_update_file_name[30]; // qepo updated file
+  INT32        gps_test_mode; // GPS TEST MODE, 1: Enable TSET MODE, 0 : Normal MODE
+  UINT8        u1AgpsMachine; // 0: for field test or Spirent ULTS (Default value in MNL), 1: R&S CRTU
+  int          dsp_fd;
+  UINT8        reserved;
+  UINT32       log_file_max_size; //The max size limitation of one debug log file, 1MB(1024*1024)~48MB(48*1024*1024), default is 20MB
+  UINT32       log_folder_max_size; //The max size limitation of the debug log folder, log_file_max_size*12~512MB(512*1024*1024), default is 240MB
+  UINT32    socket_port;//The socket port number. 0xFFFFF: close socket
+  char         hal_ver[30];
+  char         mnld_ver[30];
+  UINT8        mtknav_file_name[30]; // mtknav working file
+  UINT8        mtknav_update_file_name[30]; // mtknav updated file
+  UINT8        qepo_ga_file_name[30]; // Galileo qepo working file
+  UINT8        qepo_ga_update_file_name[30]; //Galileo qepo updated file
+  /* new member should be added bellow here */
+  UINT8        raw_meas_enable;
+} MTK_GPS_DRIVER_CFG;
+
+/** GPS measurement support **/
+typedef struct
+{
+   UINT32 size;
+   UINT32 flag;
+   INT8 PRN;
+   double TimeOffsetInNs;
+   UINT16 state;
+   INT64 ReGpsTowInNs;                    //Re: Received
+   INT64 ReGpsTowUnInNs;               //Re: Received, Un:Uncertainty
+   double Cn0InDbHz;
+   double PRRateInMeterPreSec;       // PR: Pseuderange
+   double PRRateUnInMeterPreSec;   // PR: Pseuderange Un:Uncertainty
+   UINT16 AcDRState10;                      // Ac:Accumulated, DR:Delta Range
+   double AcDRInMeters;                    // Ac:Accumulated, DR:Delta Range
+   double AcDRUnInMeters;                // Ac:Accumulated, DR:Delta Range, Un:Uncertainty
+   double PRInMeters;                        // PR: Pseuderange
+   double PRUnInMeters;
+   double CPInChips;                          // CP: Code Phase
+   double CPUnInChips;                      // CP: Code Phase
+   float CFInhZ;                                  // CP: Carrier Frequency
+   INT64 CarrierCycle;
+   double CarrierPhase;
+   double CarrierPhaseUn;                 // Un:Uncertainty
+   UINT8 LossOfLock;
+   INT32 BitNumber;
+   INT16 TimeFromLastBitInMs;
+   double DopperShiftInHz;
+   double DopperShiftUnInHz;           // Un:Uncertainty
+   UINT8 MultipathIndicater;
+   double SnrInDb;
+   double ElInDeg;                             // El: elevation
+   double ElUnInDeg;                         // El: elevation, Un:Uncertainty
+   double AzInDeg;                            // Az: Azimuth
+   double AzUnInDeg;                        // Az: Azimuth
+   char UsedInFix;
+}MTK_GPS_MEASUREMENT;
+
+typedef struct
+{
+   UINT32 size;
+   UINT16 flag;
+   INT16 leapsecond;
+   UINT8 type;
+   INT64 TimeInNs;
+   double TimeUncertaintyInNs;
+   INT64 FullBiasInNs;
+   double BiasInNs;
+   double BiasUncertaintyInNs;
+   double DriftInNsPerSec;
+   double DriftUncertaintyInNsPerSec;
+}MTK_GPS_CLOCK;
+
+typedef struct
+{
+   UINT32 size;
+   INT8 type;
+   UINT8 prn;
+   INT16 messageID;
+   INT16 submessageID;
+   UINT32 length;
+   UINT8 data[40]; // 10 word
+} MTK_GPS_NAVIGATION_EVENT;
+
+typedef struct {
+    UINT32 size;
+    MTK_GnssMeasurementflags flags;
+    INT16 svid;
+    MTK_GnssConstellationtype constellation;
+    double time_offset_ns;
+    UINT32 state;
+    INT64 received_sv_time_in_ns;
+    INT64 received_sv_time_uncertainty_in_ns;
+    double c_n0_dbhz;
+    double pseudorange_rate_mps;
+    double pseudorange_rate_uncertainty_mps;
+    MTK_GnssAccumulatedDeltaRangestate accumulated_delta_range_state;
+    double accumulated_delta_range_m;
+    double accumulated_delta_range_uncertainty_m;
+    float carrier_frequency_hz;
+    INT64 carrier_cycles;
+    double carrier_phase;
+    double carrier_phase_uncertainty;
+    MTK_GnssMultipathindicator multipath_indicator;
+    double snr_db;
+} Gnssmeasurement;
+
+typedef struct {
+    UINT32 size;
+    MTK_GnssClockflags flags;
+    INT16 leap_second;
+    INT64 time_ns;
+    double time_uncertainty_ns;
+    INT64 full_bias_ns;
+    double bias_ns;
+    double bias_uncertainty_ns;
+    double drift_nsps;
+    double drift_uncertainty_nsps;
+    UINT32 hw_clock_discontinuity_count;
+} Gnssclock;
+
+typedef struct {
+    UINT32 size;
+    INT16 svid;
+    MTK_GnssNavigationmessageType type;
+    UINT16 status;
+    INT16 message_id;
+    INT16 submessage_id;
+    UINT32 data_length;
+    union
+    {
+      UINT8 GP_data[40];
+      UINT8 GL_data[12];
+      UINT8 BD_data[40];
+      UINT8 GA_data[40];
+    } uData;
+} GnssNavigationmessage;
+
+
+typedef struct
+{
+    double  latitude[2]; /* latitude in radius */
+    double  longitude[2]; /* longitude in radius */
+    double  altitude[2]; /* altitude in meters above the WGS 84 reference ellipsoid */
+    float   KF_velocity[3]; /* Kalman Filter velocity in meters per second under (N,E,D) frame */
+    float   LS_velocity[3]; /* Least Square velocity in meters per second under (N,E,D) frame */
+    float   HACC; /*  position horizontal accuracy in meters */
+    float   VACC; /*  vertical accuracy in meters */
+    float   KF_velocitySigma[3]; /* Kalman Filter velocity one sigma error in meter per second under (N,E,D) frame */
+    float   LS_velocitySigma[3]; /* Least Square velocity one sigma error in meter per second under (N,E,D) frame */
+    float   HDOP; /* horizontal dilution of precision value in unitless */
+    float   confidenceIndex[3]; /* GPS confidence index */
+    unsigned int   gps_sec; /* Timestamp of GPS location */
+    unsigned int   leap_sec; /* correct GPS time with phone kernel time */
+} MNL_location_output_t;
+
+typedef struct
+{
+    double  latitude; /* latitude in radius */
+    double  longitude; /* longitude in radius */
+    double  altitude; /* altitude in meters above the WGS 84 reference ellipsoid */
+    float   velocity[3]; /* SENSOR velocity in meters per second under (N,E,D) frame */
+    float   acceleration[3]; /* SENSOR acceleration in meters per second^2 under (N,E,D) frame */
+    float   HACC; /*  position horizontal accuracy in meters */
+    float   VACC; /*  vertical accuracy in meters */
+    float   velocitySigma[3]; /* SENSOR velocity one sigma error in meter per second under (N,E,D) frame */
+    float   accelerationSigma[3]; /* SENSOR acceleration one sigma error in meter per second^2 under (N,E,D) frame */
+    float   bearing; /* SENSOR heading in degrees UNDER (N,E,D) frame*/
+    float   confidenceIndex[3]; /*  SENSOR confidence index */
+    float   barometerHeight;         /*barometer height in meter*/
+    int     valid_flag[4]; /*  SENSOR AGMB hardware valid flag */
+    int     staticIndex; /* AR status [static, move, uncertain],[0,1,99]*/
+    unsigned long long timestamp; /* Timestamp of SENSOR location */
+} MNL_location_input_t;
+
+typedef enum
+{
+    // To MPE
+    CMD_START_MPE_REQ = 0x00, // no payload , request start of MPE
+    CMD_STOP_MPE_REQ,         // no payload, request stop of MPE
+    CMD_SET_MPE_MODE,         //  set MPE operational mode
+    CMD_DEINIT_MPE_REQ,             //Request shutdown of MPE
+    CMD_GET_SENSOR_RAW_REQ,    //  request for raw sensor data
+    CMD_GET_SENSOR_CALIBRATION_REQ,  //  request for calibrated sensor data
+    CMD_GET_SENSOR_FUSION_REQ, //  request for sensor fusion data (Euler angle)
+    CMD_SET_GPS_AIDING_REQ,     //Request MPE send fused location (per request, by FLP)
+    CMD_GET_ADR_STATUS_REQ,     // Request MPE send AR & heading status (per request, by MNL)
+    CMD_SEND_GPS_TIME_RES,       //Send GPS timeto MPE
+
+    // From MPE
+    CMD_START_MPE_RES = 0x20,  //no payload, response MPE start status
+    CMD_STOP_MPE_RES,          //no payload, response MPE stop status
+    CMD_SEND_SENSOR_RAW_RES,   // response  MPE sensor raw data
+    CMD_SEND_SENSOR_CALIBRATION_RES, // response MPE  calibrated sensor data
+    CMD_SEND_SENSOR_FUSION_RES, // response MPE  fused sensor  data
+    CMD_SEND_GPS_AIDING_RES,     //PDR response fused loc status upon request to FLP
+    CMD_SEND_ADR_STATUS_RES,     //ADR response AR & heading status upon request to MNL
+    CMD_SEND_GPS_TIME_REQ,       //Request for GPS time for recording & replay purpose
+    CMD_MPE_END = 0x30
+}MPE_CMD;
+
+//location source
+typedef enum
+{
+    MPE_LOC_SOURCE_FLP = 1,
+    MPE_LOC_SOURCE_GNSS = 2,
+    MPE_LOC_SOURCE_OTHER = 4,
+    MPE_LOC_SOURCE_END
+} MPE_LOC_SOURCE;
+
+typedef struct
+{
+  UINT32    type;           /* message ID */
+  UINT32    length;         /* length of 'data' */
+} MPE_MSG;
+
+typedef int (*MPECallBack)(); /* Callback function register in mnld, for 1sec delay issue*/
+
+// MTK_GPS_INIT_CFG.opmode defines
+#define MTK_INITCFG_OPMODE_2D_FIRSTFIX (1 << 2)
+
+// Task synchronization related type
+typedef enum
+{
+  MTK_MUTEX_BIN_Q = 0,
+  MTK_MUTEX_MSG_CNT,
+  MTK_MUTEX_NV_HANDLE,
+  MTK_MUTEX_DEBUG,
+  MTK_MUTEX_MSG_Q,
+  MTK_MUTEX_AGPS_MSG_CNT,
+  MTK_MUTEX_AGPS_MSG_Q,
+  //#ifdef SUPPORT_MULTI_INTERFACE
+  //#endif
+  //MTK_MUTEX_STAGE1,
+  MTK_MUTEX_AARDVARK_I2C_DATA,
+  MTK_MUTEX_AARDVARK_I2C,
+  MTK_MUTEX_AARDVARK_SPI,
+  MTK_MUTEX_FILE,
+  MTK_MUTEX_END
+} MTK_GPS_MUTEX_ENUM;
+
+typedef enum
+{
+  MTK_EVENT_GPS = 0,
+  MTK_EVENT_HS,
+  MTK_EVENT_AGENT,
+  MTK_EVENT_FILE,
+  MTK_EVENT_END
+} MTK_GPS_EVENT_ENUM;
+
+typedef enum
+{
+    GPS_MNL_THREAD_UNKNOWN          = -1,
+    GPS_MNL_THREAD_DSP_INPUT        = 0,
+    GPS_MNL_THREAD_PMTK_INPUT       = 1,
+    GPS_MNL_THREAD_BEE              = 2,
+    GPS_MNL_THREAD_MNL              = 3,
+    GPS_MNL_THREAD_AGENT            = 4,
+    GPS_MNL_THREAD_FILE_CONTROL     = 5,
+
+    // flush data in slots to connsys(/dev/stpgps)
+    GPS_MNL_THREAD_MNL_OFL_OUTPUT   = 6,
+
+    // fwrite(dbg log) may block too long (>5s) to block offload pkt parser,
+    //   then the time of no NMEA will exceed 5s, and libmnl.so will be reset.
+    // create a dedicated thread for offload fwrite to avoid it blocks offload
+    //   main thread (GPS_MNL_THREAD_MNL).
+    GPS_MNL_THREAD_MNL_OFL_DEBUG    = 7,
+
+    GPS_MNL_THREAD_NUM              = 8
+} MTK_GPS_THREAD_ID_ENUM;
+
+typedef enum
+{
+  MNL_STATUS_DEF = 0,
+  MNL_DSP_UART_INIT_ERR,
+  MNL_NMEA_UART_INIT_ERR,
+  MNL_NMEAIN_UART_INIT_ERR,
+  MNL_GPS_HW_CHECK_ERR,
+  MNL_GPS_MUTEX_INIT_ERR,
+  MNL_GPS_MUTEX_CREATE_ERR,
+  MNL_MNL_THREAD_CREATE_ERR,
+  MNL_MNL_THREAD_ADJUST_ERR,
+  MNL_DSP_THREAD_CREATE_ERR,
+  MNL_DSP_THREAD_ADJUST_ERR,
+  MNL_PMTK_THREAD_CREATE_ERR,
+  MNL_PMTK_THREAD_ADJUST_ERR,
+  MNL_PMTK_APP_THREAD_CREATE_ERR,
+  MNL_BEE_THREAD_CREATE_ERR,
+  MNL_AGT_THREAD_CREATE_ERR,
+  MNL_FILE_CONTROL_THREAD_CREATE_ERR,
+  MNL_DSP_BOOT_ERR,
+  MNL_INIT_SUCCESS = 18,
+  MNL_OFFLOAD_INIT_ERR = 19
+} MTK_GPS_BOOT_STATUS;
+
+typedef enum
+{
+   HS_DEFAULT_STATUS,
+   HS_INIT_ERR,
+   HS_RUN_SUCCESS
+}mtk_gps_hotstill_status;
+
+typedef enum
+{
+    /*MT6620*/
+    MT6620_E1 = 0,
+    MT6620_E2,
+    MT6620_E3,
+    MT6620_E4,
+    MT6620_EN,  // MUST smaller than 0x10
+    /*MT6628*/
+    MT6628_E1 = 0 + (0x10),
+    MT6628_E2,
+    MT6628_EN,  // MUST smaller then 0x20
+    /*MT3332*/
+    MT3332_E1 = 0 + (0x20),
+    MT3332_E2,
+    MT3332_EN,  // MUST smaller then 0x30
+    /*MT3336*/
+    MT3336_E1 = 0 + (0x30),
+    MT3336_E2,
+    MT3336_EN,
+    MT6572_E1 = 0 + (0x40),
+    MT6572_EN,
+    MT6582_E1 = 0 + (0x50),
+    MT6582_EN ,
+    MT6592_E1 = 0 + (0x60),
+    MT6592_EN ,
+    MT6571_E1 = 0 + (0x70),
+    MT6571_EN,
+    MT6630_E1 = 0 + (0x80),
+    MT6630_E2,
+    MT6630_EN,
+    MT6752_E1 = 0 + (0x90),
+    MT6752_EN,
+    MT6735_E1 = 0 + (0xA0),
+    MT6735_EN,
+    MT6735M_E1 = 0 + (0xB0),
+    MT6735M_EN,
+    MT6753_E1 = 0 + (0xC0),
+    MT6753_EN,
+    MT6580_E1 = 0 + (0xD0),
+    MT6580_EN,
+    MT6755_E1 = 0 + (0xE0),
+    MT6755_EN,
+    MT6797_E1 = 0 + (0xF0),
+    MT6797_EN,
+    MT6632_E1 = 0 + (0x100),
+    MT6632_E3,
+    MT6632_EN,
+    MT6757_E1 = 0 + (0x110),
+    MT6757_EN,
+    MT6570_E1 = 0 + (0x120),
+    MT6570_EN,
+    MT6759_E1 = 0 + (0x130),
+    MT6759_EN,
+    MT6763_E1 = 0 + (0x140),
+    MT6763_EN,
+    MT6758_E1 = 0 + (0x150),
+    MT6758_EN,
+    MT6739_E1 = 0 + (0x160),
+    MT6739_EN,
+    MT6771_E1 = 0 + (0x170),
+    MT6771_EN,
+    MT6775_E1 = 0 + (0x180),
+    MT6775_EN,
+    MT6765_E1 = 0 + (0x190),
+    MT6765_EN
+}eMTK_GPS_CHIP_TYPE;
+
+//#define MTK_GPS_THIP_KEY          (0xFFFF6620) //
+#define MTK_GPS_CHIP_KEY_MT6620   (0xFFFF6620)
+#define MTK_GPS_CHIP_KEY_MT6628   (0xFFFF6628)
+#define MTK_GPS_CHIP_KEY_MT3332   (0xFFFF3332)
+#define MTK_GPS_CHIP_KEY_MT3336   (0xFFFF3336)
+#define MTK_GPS_CHIP_KEY_MT6572   (0xFFFF6572)
+#define MTK_GPS_CHIP_KEY_MT6582   (0xFFFF6582)
+#define MTK_GPS_CHIP_KEY_MT6592   (0xFFFF6592)
+#define MTK_GPS_CHIP_KEY_MT6571   (0xFFFF6571)
+#define MTK_GPS_CHIP_KEY_MT6630   (0xFFFF6630)
+#define MTK_GPS_CHIP_KEY_MT6752   (0xFFFF6752)
+#define MTK_GPS_CHIP_KEY_MT6735   (0xFFFF6735)
+#define MTK_GPS_CHIP_KEY_MT6735M   (0xFFFE6735)
+#define MTK_GPS_CHIP_KEY_MT6739   (0xFFFF6739)
+#define MTK_GPS_CHIP_KEY_MT6753   (0xFFFF6753)
+#define MTK_GPS_CHIP_KEY_MT6763   (0xFFFF6763)
+#define MTK_GPS_CHIP_KEY_MT6580   (0xFFFF6580)
+#define MTK_GPS_CHIP_KEY_MT6570   (0xFFFF6570)
+#define MTK_GPS_CHIP_KEY_MT6755   (0xFFFF6755)
+#define MTK_GPS_CHIP_KEY_MT6797   (0xFFFF6797)
+#define MTK_GPS_CHIP_KEY_MT6759   (0xFFFF6759)
+#define MTK_GPS_CHIP_KEY_MT6632   (0xFFFF6632)
+#define MTK_GPS_CHIP_KEY_MT6757   (0xFFFF6757)
+#define MTK_GPS_CHIP_KEY_MT6758   (0xFFFF6758)
+#define MTK_GPS_CHIP_KEY_MT6771   (0xFFFF6771)
+#define MTK_GPS_CHIP_KEY_MT6775   (0xFFFF6775)
+#define MTK_GPS_CHIP_KEY_MT6765   (0xFFFF6765)
+
+/* Return value for most APIs */
+#define MTK_GPS_SUCCESS                 (0)
+#define MTK_GPS_ERROR                   (-1)
+#define MTK_GPS_ERROR_NMEA_INCOMPLETE   (-2)
+#define MTK_GPS_ERROR_TIME_CHANGED      (1)
+#define MTK_GPS_NO_MSG_RECEIVED         (1)
+
+
+#define MTK_GPS_DELETE_EPHEMERIS        0x0001
+#define MTK_GPS_DELETE_ALMANAC          0x0002
+#define MTK_GPS_DELETE_POSITION         0x0004
+#define MTK_GPS_DELETE_TIME             0x0008
+#define MTK_GPS_DELETE_IONO             0x0010
+#define MTK_GPS_DELETE_UTC              0x0020
+#define MTK_GPS_DELETE_HEALTH           0x0040
+#define MTK_GPS_DELETE_SVDIR            0x0080
+#define MTK_GPS_DELETE_SVSTEER          0x0100
+#define MTK_GPS_DELETE_SADATA           0x0200
+#define MTK_GPS_DELETE_RTI              0x0400
+#define MTK_GPS_DELETE_CLK              0x0800
+#define MTK_GPS_DELETE_CELLDB_INFO      0x8000
+#define MTK_GPS_DELETE_ALL              0xFFFF
+
+
+//start for AGPS_SUPPORT_GNSS
+#define GNSS_MAX_REF_TIME_SAT_ELEMENT                    16  /* 64 for LPP, 16 for RRC, 12 for RRLP. Use 16 to reduce structure size */
+#define GNSS_MAX_REF_CELL_FTA_ELEMENT                    16  /* 16 for LPP, 1 for RRC/RRLP */
+
+#define GNSS_MAX_GNSS_GENERIC_ASSIST_DATA_ELEMENT        16  /* 16 for LPP, 8 for RRC/RRLP in provide assistance data;
+                                                                16 for LPP/RRLP, 8 for RRC in capability */
+
+/* GNSS Time Model */
+#define GNSS_MAX_TIME_MODEL_ELEMENT                       4  /* 15 for LPP, 7 for RRC/RRLP, Use 4 since gnss-TO-ID only 4 (GPS, Galileo, QZSS, GLONASS) */
+
+/* GNSS DGNSS */
+#define GNSS_MAX_DGNSS_SGN_TYPE_ELEMENT                   3  /* 3 for LPP/RRLP, 8 for RRC */
+#define GNSS_MAX_DGNSS_CORRECTION_INFO_ELEMENT           16  /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Navigation Model */
+#define GNSS_MAX_NAV_SAT_ELEMENT                         16  /* 64 for LPP/RRC, 32 for RRLP. Use 16 to reduce structure size */
+#define GNSS_MAX_NAV_SAT_ELEMENT_BIT_POS                 64  /* 64 for LPP/RRC, 32 for RRLP, dedicated for assist data req */
+#define GNSS_MAX_NAV_STD_CLK_MODEL_ELEMENT                4  /* 2 for LPP/RRLP, 4 for RRC */
+#define GNSS_MAX_NAV_CLOCK_MODEL_ELEMENT                  5  /* currently there is 5 clock models */
+#define GNSS_MAX_NAV_ORBIT_MODEL_ELEMENT                  5  /* currently there is 5 orbit models */
+
+/* GNSS Real Time Integrity */
+#define GNSS_MAX_RTI_BAD_SAT_ELEMENT                     16  /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Data Bit Assistance */
+#define GNSS_MAX_DBA_SGN_TYPE_ELEMENT                     8  /* 8 for LPP/RRC/RRLP */
+#define GNSS_MAX_DBA_SAT_ELEMENT                         16  /* 64 for LPP/RRC, 32 for RRLP. Use 16 to reduce structure size */
+#define GNSS_MAX_DBA_BIT_LENGTH                          64  /* 1024 bit for LPP/RRC/RRLP, but RRLP use integer intead of bit. Process only max 64 bits to reduce structure size */
+
+/* GNSS Acquisition Assitance */
+#define GNSS_MAX_ACQ_ASSIST_SAT_ELEMENT                  16  /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Almanac */
+#define GNSS_MAX_ALMANAC_SAT_ELEMENT                     32  /* 64 for LPP/RRC, 36 for RRLP. Use 32 to reduce structure size */
+
+/* GNSS Auxiliary Information */
+#define GNSS_MAX_AUX_SAT_ELEMENT                         16  /* 64 for LPP/RRC/RRLP. Use 16 to reduce structure size */
+
+/* GNSS Measurement Info */
+#define GNSS_MAX_MEASURED_GNSS_ELEMENT                   GNSS_MAX_SUPPORT_NUM  /* 16 for LPP, 8 for RRC/RRLP, Use GNSS_MAX_SUPPORT_NUM (4) to reduce structure size */
+#define GNSS_MAX_MEASURED_SGN_PER_GNSS_ELEMENT                              4  /* 8 for LPP/RRC/RRLP, Use 4 to reduce structure size */
+#define GNSS_MAX_MEASURED_SAT_PER_SGN_ELEMENT                              16  /* 64 for LPP/RRC, 16 for RRLP. Use 16 to reduce structure size */
+
+/* GNSS Request Additional Generic Assist Data */
+#define GNSS_MAX_REQ_ADD_GENERIC_ASSIST_DATA_ELEMENT     GNSS_MAX_SUPPORT_NUM  /* 16 for LPP, 8 for RRC, unspecified for RRLP (up to 40 bytes), Use 9 since number of generic assistance data type is only 9 */
+
+
+/* GNSS ID Bitmap, use one-byte representation */
+#define GNSS_ID_BITMAP_NONE     0x00
+#define GNSS_ID_BITMAP_GPS      0x8000  /* gps     (0) */
+#define GNSS_ID_BITMAP_SBAS     0x4000  /* sbas    (1) */
+#define GNSS_ID_BITMAP_QZSS     0x2000  /* qzss    (2) */
+#define GNSS_ID_BITMAP_GALILEO  0x1000  /* galileo (3) */
+#define GNSS_ID_BITMAP_GLONASS  0x0800  /* glonass (4) */
+#define GNSS_ID_BITMAP_BEIDOU   0x0400  /* beidou  (5) */
+
+
+#define GNSS_ID_BITMAP_GPS_GLONASS  (GNSS_ID_BITMAP_GPS | GNSS_ID_BITMAP_GLONASS)
+#define GNSS_ID_BITMAP_GPS_BEIDOU   (GNSS_ID_BITMAP_GPS | GNSS_ID_BITMAP_BEIDOU )
+
+/* TBD: check with WCN, MT6630 support GPS+QZSS+GLONASS+Galileo+Beidou */
+#define GNSS_MAX_SUPPORT_NUM    0x02 /* A-GPS + A-GLONASS */
+
+/* SBAS ID Bitmap, use one-byte representation */
+#define SBAS_ID_BITMAP_NONE   0x00
+#define SBAS_ID_BITMAP_WASS   0x80  /* waas  (0) */
+#define SBAS_ID_BITMAP_EGNOS  0x40  /* egnos (1) */
+#define SBAS_ID_BITMAP_MSAS   0x20  /* msas  (2) */
+#define SBAS_ID_BITMAP_GAGAN  0x10  /* gagan (3) */
+
+/* GNSS Signal IDs Bitmap, use one-byte representation
+ * GNSS    | Bit 1  | Bit 2 | Bit 3 | Bit 4 | Bit 5 | Bit 6 | Bit 7 | Bit 8 |
+ * --------+--------+-------+-------+-------+-------+-------+-------+-------+
+ * GPS     | L1 C/A |  L1C  |  L2C  |   L5  | -- reserved --|-------|-------|
+ * SBAS    | L1     | -- reserved --|-------|-------|-------|-------|-------|
+ * QZSS    | QZS-L1 |QZS-L1C|QZS-L2C| QZS-L5| -- reserved --|-------|-------|
+ * GLONASS | G1     |   G2  |  G3   | -- reserved --|-------|-------|-------|
+ * Galileo | E1     |   E5a |  E5b  |   E6  |E5a+E5b| -- reserved --|-------|
+*/
+/* TBD: need confirmation GNSS signal spectrum from WCN */
+#define GNSS_SGN_ID_BITMAP_GPS_L1C_A       0x80  /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_GPS_L1C         0x40  /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_GPS_L2C         0x20  /* bit 3 */
+#define GNSS_SGN_ID_BITMAP_GPS_L5          0x10  /* bit 4 */
+
+#define GNSS_SGN_ID_BITMAP_SBAS_L1         0x80  /* bit 1 */
+
+#define GNSS_SGN_ID_BITMAP_QZSS_L1C_A      0x80  /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_QZSS_L1C        0x40  /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_QZSS_L2C        0x20  /* bit 3 */
+#define GNSS_SGN_ID_BITMAP_QZSS_L5         0x10  /* bit 4 */
+
+#define GNSS_SGN_ID_BITMAP_GLONASS_G1      0x80  /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_GLONASS_G2      0x40  /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_GLONASS_G3      0x20  /* bit 3 */
+
+#define GNSS_SGN_ID_BITMAP_GALILEO_E1      0x80  /* bit 1 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E5A     0x40  /* bit 2 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E5B     0x20  /* bit 3 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E6      0x10  /* bit 4 */
+#define GNSS_SGN_ID_BITMAP_GALILEO_E5_A_B  0x08  /* bit 5 */
+
+/* GNSS Signal ID value */
+#define GNSS_SGN_ID_VALUE_GPS_L1C_A       0
+#define GNSS_SGN_ID_VALUE_GPS_L1C         1
+#define GNSS_SGN_ID_VALUE_GPS_L2C         2
+#define GNSS_SGN_ID_VALUE_GPS_L5          3
+
+#define GNSS_SGN_ID_VALUE_SBAS_L1         0
+
+#define GNSS_SGN_ID_VALUE_QZSS_L1C_A      0
+#define GNSS_SGN_ID_VALUE_QZSS_L1C        1
+#define GNSS_SGN_ID_VALUE_QZSS_L2C        2
+#define GNSS_SGN_ID_VALUE_QZSS_L5         3
+
+#define GNSS_SGN_ID_VALUE_GLONASS_G1      0
+#define GNSS_SGN_ID_VALUE_GLONASS_G2      1
+#define GNSS_SGN_ID_VALUE_GLONASS_G3      2
+
+#define GNSS_SGN_ID_VALUE_GALILEO_E1      0
+#define GNSS_SGN_ID_VALUE_GALILEO_E5A     1
+#define GNSS_SGN_ID_VALUE_GALILEO_E5B     2
+#define GNSS_SGN_ID_VALUE_GALILEO_E6      3
+#define GNSS_SGN_ID_VALUE_GALILEO_E5_A_B  4
+
+#define GNSS_SGN_ID_VALUE_BEIDOU_B1I      0
+#define GNSS_SGN_ID_VALUE_BEIDOU_B2I      1
+
+#define GNSS_SGN_ID_VALUE_MAX             7
+
+/* GNSS Clock and Orbit Model Value (for Navigation Model) */
+#define GNSS_NAV_CLOCK_MODEL_1_VALUE_STANDARD  1  /* model-1 */
+#define GNSS_NAV_CLOCK_MODEL_2_VALUE_NAV       2  /* model-2 */
+#define GNSS_NAV_CLOCK_MODEL_3_VALUE_CNAV      3  /* model-3 */
+#define GNSS_NAV_CLOCK_MODEL_4_VALUE_GLONASS   4  /* model-4 */
+#define GNSS_NAV_CLOCK_MODEL_5_VALUE_SBAS      5  /* model-5 */
+
+#define GNSS_NAV_ORBIT_MODEL_1_VALUE_KEPLERIAN_SET       1  /* model-1 */
+#define GNSS_NAV_ORBIT_MODEL_2_VALUE_NAV_KEPLERIAN_SET   2  /* model-2 */
+#define GNSS_NAV_ORBIT_MODEL_3_VALUE_CNAV_KEPLERIAN_SET  3  /* model-3 */
+#define GNSS_NAV_ORBIT_MODEL_4_VALUE_GLONASS_ECEF        4  /* model-4 */
+#define GNSS_NAV_ORBIT_MODEL_5_VALUE_SBAS_ECEF           5  /* model-5 */
+
+/* Almanac Model Value */
+#define GNSS_ALMANAC_MODEL_1_VALUE_KEPLERIAN_SET          1  /* model-1 */
+#define GNSS_ALMANAC_MODEL_2_VALUE_NAV_KEPLERIAN_SET      2  /* model-2 */
+#define GNSS_ALMANAC_MODEL_3_VALUE_REDUCED_KEPLERIAN_SET  3  /* model-3 */
+#define GNSS_ALMANAC_MODEL_4_VALUE_MIDI_KEPLERIAN_SET     4  /* model-4 */
+#define GNSS_ALMANAC_MODEL_5_VALUE_GLONASS_SET            5  /* model-5 */
+#define GNSS_ALMANAC_MODEL_6_VALUE_ECEF_SBAS_SET          6  /* model-6 */
+
+/* UTC Model Value */
+#define GNSS_UTC_MODEL_1_VALUE  1  /* model-1 (0) */
+#define GNSS_UTC_MODEL_2_VALUE  2  /* model-2 (1) */
+#define GNSS_UTC_MODEL_3_VALUE  3  /* model-3 (2) */
+#define GNSS_UTC_MODEL_4_VALUE  4  /* model-4 (3) */
+/* Ionoshoeruc Model */
+#define GNSS_ION_MODEL_KLOBUCHAR  0x80  /* klobuchar (0) */
+#define GNSS_ION_MODEL_NEQUICK    0x40  /* neQuick   (1) */
+
+
+/* Navigation Model */
+#define GNSS_NAV_CLOCK_MODEL_1_STANDARD  0x80  /* model-1 (0) */
+#define GNSS_NAV_CLOCK_MODEL_2_NAV       0x40  /* model-2 (1) */
+#define GNSS_NAV_CLOCK_MODEL_3_CNAV      0x20  /* model-3 (2) */
+#define GNSS_NAV_CLOCK_MODEL_4_GLONASS   0x10  /* model-4 (3) */
+#define GNSS_NAV_CLOCK_MODEL_5_SBAS      0x08  /* model-5 (4) */
+
+#define GNSS_NAV_ORBIT_MODEL_1_KEPLERIAN_SET       0x80  /* model-1 (0) */
+#define GNSS_NAV_ORBIT_MODEL_2_NAV_KEPLERIAN_SET   0x40  /* model-2 (1) */
+#define GNSS_NAV_ORBIT_MODEL_3_CNAV_KEPLERIAN_SET  0x20  /* model-3 (2) */
+#define GNSS_NAV_ORBIT_MODEL_4_GLONASS_ECEF        0x10  /* model-4 (3) */
+#define GNSS_NAV_ORBIT_MODEL_5_SBAS_ECEF           0x08  /* model-5 (4) */
+
+
+/* Almanac */
+#define GNSS_ALMANAC_MODEL_1_KEPLERIAN_SET          0x80  /* model-1 (0) */
+#define GNSS_ALMANAC_MODEL_2_NAV_KEPLERIAN_SET      0x40  /* model-2 (1) */
+#define GNSS_ALMANAC_MODEL_3_REDUCED_KEPLERIAN_SET  0x20  /* model-3 (2) */
+#define GNSS_ALMANAC_MODEL_4_MIDI_KEPLERIAN_SET     0x10  /* model-4 (3) */
+#define GNSS_ALMANAC_MODEL_5_GLONASS_SET            0x08  /* model-5 (4) */
+#define GNSS_ALMANAC_MODEL_6_ECEF_SBAS_SET          0x04  /* model-6 (5) */
+
+
+/* UTC Model*/
+#define GNSS_UTC_MODEL_1  0x80  /* model-1 (0) */
+#define GNSS_UTC_MODEL_2  0x40  /* model-2 (1) */
+#define GNSS_UTC_MODEL_3  0x20  /* model-3 (2) */
+#define GNSS_UTC_MODEL_4  0x10  /* model-4 (3) */
+
+
+
+/* NNUM ********************************************************************/
+typedef enum
+{
+    PMTK_CMD_VER_0 = 0,   //conversional GPS
+    PMTK_CMD_VER_1 = 1,   //GNSS
+    PMTK_CMD_VER_END
+} MTK_GNSS_CMD_VER_ENUM;
+typedef enum
+{
+    C2K_AGPS_DISABLE = 0,  // Disable C2K AGPS
+    C2K_AGPS_ENABLE  = 1,  // Enable C2K AGPS
+    C2K_AGPS_End
+} MTK_C2K_AGPS_ENUM;
+typedef enum
+{
+    MTK_GPS_KLB_WILD_USE  = 0,   //KLB model only for QZSS
+    MTK_GPS_KLB_QZSS_ONLY = 3,    //KLB model only for QZSS
+    MTK_GPS_KLB_TYPE_END
+} MTK_GPS_KLB_DATAID_ENUM;
+
+typedef enum
+{
+    GNSS_NETWORK_CELL_NULL  = 0,
+    GNSS_NETWORK_CELL_EUTRA = 1,
+    GNSS_NETWORK_CELL_UTRA  = 2,
+    GNSS_NETWORK_CELL_GSM   = 3,
+    GNSS_NETWORK_CELL_END
+} MTK_GNSS_NETWORK_CELL_ENUM;
+
+
+typedef enum
+{
+    GNSS_ID_GPS     = 0,
+    GNSS_ID_SBAS    = 1,
+    GNSS_ID_QZSS    = 2,
+    GNSS_ID_GALILEO = 3,
+    GNSS_ID_GLONASS = 4,
+    GNSS_ID_BEIDOU  = 5,
+    GNSS_ID_MAX_NUM
+} MTK_GNSS_ID_ENUM;
+
+
+typedef enum
+{
+    GNSS_TO_ID_GPS  = 1,
+    GNSS_TO_ID_GALILEO ,
+    GNSS_TO_ID_QZSS    ,
+    GNSS_TO_ID_GLONASS ,
+    GNSS_TO_ID_BEIDOU  ,
+    GNSS_TO_ID_END
+} MTK_GNSS_TO_ID_ENUM;
+
+
+typedef enum
+{
+    SBAS_ID_WAAS   = 0,
+    SBAS_ID_EGNOS  = 1,
+    SBAS_ID_MSAS   = 2,
+    SBAS_ID_GAGAN  = 3,
+    SBAS_ID_BEIDOU = 4,
+    SBAS_ID_END
+} MTK_SBAS_ID_ENUM;
+
+
+typedef enum
+{
+    GNSS_COMMON_ASSIST_TIM   = 0,
+    GNSS_COMMON_ASSIST_LOC   = 1,
+    GNSS_COMMON_ASSIST_ION   = 2,
+    GNSS_COMMON_ASSIST_EOP   = 3,
+
+} MTK_GNSS_COMMON_ASSIST_ENUM;
+
+
+typedef enum
+{
+    GNSS_GENERIC_ASSIST_TMD   = 0,
+    GNSS_GENERIC_ASSIST_DGNSS = 1,
+    GNSS_GENERIC_ASSIST_EPH   = 2,
+    GNSS_GENERIC_ASSIST_RTI   = 3,
+    GNSS_GENERIC_ASSIST_DBA   = 4,
+    GNSS_GENERIC_ASSIST_ACQ   = 5,
+    GNSS_GENERIC_ASSIST_ALM   = 6,
+    GNSS_GENERIC_ASSIST_UTC   = 7,
+    GNSS_GENERIC_ASSIST_AUX   = 8,
+    GNSS_GENERIC_ASSIST_END   = 9,
+} MTK_GNSS_GENERIC_ASSIST_ENUM;
+
+
+typedef enum
+{
+    GNSS_CLOCK_MODEL_TYPE_STANDARD,
+    GNSS_CLOCK_MODEL_TYPE_NAV,
+    GNSS_CLOCK_MODEL_TYPE_CNAV,
+    GNSS_CLOCK_MODEL_TYPE_GLONASS,
+    GNSS_CLOCK_MODEL_TYPE_SBAS
+} gnss_clock_model_type_enum;
+
+
+typedef enum
+{
+    GNSS_ORBIT_MODEL_TYPE_KEPLERIAN_SET,
+    GNSS_ORBIT_MODEL_TYPE_NAV_KEPLERIAN_SET,
+    GNSS_ORBIT_MODEL_TYPE_CNAV_KEPLERIAN_SET,
+    GNSS_ORBIT_MODEL_TYPE_GLONASS_ECEF,
+    GNSS_ORBIT_MODEL_TYPE_SBAS_ECEF
+} gnss_orbit_model_type_enum;
+
+
+typedef enum
+{
+    GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D60,
+    GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D80,
+    GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D100,
+    GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_D120,
+    GNSS_ACQ_ASSIST_DOPPLER_UNCERTAINTY_EXT_ENUM_NO_INFO
+} MTK_GNSS_ACQ_DOPP_UNCERT_EXT_ENUM;
+
+
+typedef enum
+{
+    GNSS_ALMANAC_TYPE_KEPLERIAN_SET,
+    GNSS_ALMANAC_TYPE_NAV_KEPLERIAN_SET,
+    GNSS_ALMANAC_TYPE_REDUCED_KEPLERIAN_SET,
+    GNSS_ALMANAC_TYPE_MIDI_KEPLERIAN_SET,
+    GNSS_ALMANAC_TYPE_GLONASS_SET,
+    GNSS_ALMANAC_TYPE_ECEF_SBAS_SET,
+} gnss_almanac_type_enum;
+
+
+typedef enum
+{
+    UTC_MODEL_GPS,
+    UTC_MODEL_QZSS,
+    UTC_MODEL_GLO,
+    UTC_MODEL_SBAS,
+    UTC_MODEL_BEIDOU,
+    UTC_MODEL_UNKNOWN,
+} MTK_GNSS_UTC_TYPE_ENUM;
+
+typedef enum
+{
+    GNSS_AUX_TYPE_GPS,
+    GNSS_AUX_TYPE_GLONASS
+} MTK_GNSS_AUX_TYPE_ENUM;
+
+typedef enum
+{
+    MTK_QEPO_RSP_UPDATE_SUCCESS = 0,
+    MTK_QEPO_RSP_UPDATE_FAIL,
+    MTK_QEPO_RSP_DOWNLOAD_FAIL,
+    MTK_QEPO_RSP_NETWORK_CONNECT_FAIL,
+    MTK_QEPO_RSP_SIZE_FAIL,
+    MTK_QEPO_RSP_TIMEOUT
+}MTK_QEPO_RSP;
+
+typedef enum
+{
+    MTK_MTKNAV_RSP_UPDATE_SUCCESS = 0,
+    MTK_MTKNAV_RSP_UPDATE_FAIL,
+    MTK_MTKNAV_RSP_DOWNLOAD_FAIL,
+    MTK_MTKNAV_RSP_NETWORK_CONNECT_FAIL,
+    MTK_MTKNAV_RSP_SIZE_FAIL,
+    MTK_MTKNAV_RSP_NO_UPDATE,
+    MTK_MTKNAV_RSP_TIMEOUT
+}MTK_MTKNAV_RSP;
+
+typedef enum {
+    //PAYLOAD = 12byte:
+    //uint32, whether 1st run
+    //uint32, heart_beat cnt, start at 0
+    //uint32, max micro-secends to next heartbeat
+    MTK_GPS_OFL_CB_HEART_BEAT = 0,
+
+    MTK_GPS_OFL_CB_CNT
+} MTK_GPS_OFL_CB_TYPE;
+
+//end for AGPS_SUPPORT_GNSS
+#if ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 200000 ))
+// for ADS1.x
+#elif ( defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400000 ) )
+// for RVCT2.x or RVCT3.x
+#else
+#pragma pack()
+#endif
+/*gnss2lcsp_enum*/
+
+/* MACROS *******************************************************************/
+
+/**
+ * among LPP/RRC/RRLP, the max number of elements for GNSS data is different in some data fields.
+ * we take the largest value as element definition for common interface
+ */
+#define LPPE_IONOSPHERIC_STATIC_MODEL_VALID (0x1<<0)
+#define LPPE_IONOSPHERIC_PERIODIC_MODEL_VALID (0x1<<1)
+#define LPPE_TROPOSPHERE_MODEL_VALID (0x1<<2)
+#define LPPE_ALTITUDE_ASSIST_VALID (0x1<<3)
+#define LPPE_SOLAR_RADIATION_VALID (0x1<<4)
+#define LPPE_ASSIST_COMMON_CCP_COM_PARA_VALID (0x1<<5)
+#define LPPE_ASSIST_COMMON_CCP_CTR_PARA_VALID (0x1<<6)
+#define LPPE_ASSIST_GENERIC_CCP_VALID (0x1<<7)
+#define LPPE_ASSIST_GENERIC_DM_VALID (0x1<<8)
+
+/* GNSS measurement fields validity bitmask */
+#define GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY   0x01
+#define GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY    0x02
+#define GNSS_MEAS_INFO_DOPPLER_VALIDITY           0x04
+#define GNSS_MEAS_INFO_ADR_VALIDITY               0x08
+#define GNSS_MEAS_INFO_ALL_VALIDITY               0x0F
+
+#define CHECK_GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY(validity)      ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY(validity)        (validity |= GNSS_MEAS_INFO_CARRIER_QUALITY_VALIDITY)
+
+#define CHECK_GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY(validity)       ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY(validity)         (validity |= GNSS_MEAS_INFO_INT_CODE_PHASE_VALIDITY)
+
+#define CHECK_GNSS_MEAS_INFO_DOPPLER_VALIDITY(validity)              ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_DOPPLER_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_DOPPLER_VALIDITY(validity)                (validity |= GNSS_MEAS_INFO_DOPPLER_VALIDITY)
+
+#define CHECK_GNSS_MEAS_INFO_ADR_VALIDITY(validity)                  ((validity & GNSS_MEAS_INFO_ALL_VALIDITY) & GNSS_MEAS_INFO_ADR_VALIDITY) ? KAL_TRUE : KAL_FALSE
+#define SET_GNSS_MEAS_INFO_ADR_VALIDITY(validity)                    (validity |= GNSS_MEAS_INFO_ADR_VALIDITY)
+
+
+/* GNSS assist data type bitmask */
+#define GNSS_ASSIST_MASK_NONE                        0x0
+
+#define GNSS_COM_ASSIST_MASK_REF_TIME                (1 << 0)  /* 0x0001 */
+#define GNSS_COM_ASSIST_MASK_REF_LOCATION            (1 << 1)  /* 0x0002 */
+#define GNSS_COM_ASSIST_MASK_IONOSPHERE              (1 << 2)  /* 0x0004 */
+#define GNSS_COM_ASSIST_MASK_EARTH_ORIENT_PARAMS     (1 << 3)  /* 0x0008 */
+
+#define GNSS_GEN_ASSIST_MASK_TIME_MODEL              (1 << 4)  /* 0x0010 */
+#define GNSS_GEN_ASSIST_MASK_DGNSS_CORRECTION        (1 << 5)  /* 0x0020 */
+#define GNSS_GEN_ASSIST_MASK_NAV_MODEL               (1 << 6)  /* 0x0040 */
+#define GNSS_GEN_ASSIST_MASK_RTI                     (1 << 7)  /* 0x0080 */
+#define GNSS_GEN_ASSIST_MASK_DATA_BIT_ASSIST         (1 << 8)  /* 0x0100 */
+#define GNSS_GEN_ASSIST_MASK_ACQUISITION             (1 << 9)  /* 0x0200 */
+#define GNSS_GEN_ASSIST_MASK_ALMANAC                 (1 <<10)  /* 0x0400 */
+#define GNSS_GEN_ASSIST_MASK_UTC_MODEL               (1 <<11)  /* 0x0800 */
+#define GNSS_GEN_ASSIST_MASK_AUX_INFO                (1 <<12)  /* 0x1000 */
+
+
+#define GNSS_ASSIST_MB_MANDATORY_MASK                (GNSS_COM_ASSIST_MASK_REF_TIME            | \
+                                                      GNSS_COM_ASSIST_MASK_REF_LOCATION        | \
+                                                      GNSS_COM_ASSIST_MASK_IONOSPHERE          | \
+                                                      GNSS_COM_ASSIST_MASK_EARTH_ORIENT_PARAMS | \
+                                                      GNSS_GEN_ASSIST_MASK_TIME_MODEL          | \
+                                                      GNSS_GEN_ASSIST_MASK_DGNSS_CORRECTION    | \
+                                                      GNSS_GEN_ASSIST_MASK_NAV_MODEL           | \
+                                                      GNSS_GEN_ASSIST_MASK_RTI                 | \
+                                                      GNSS_GEN_ASSIST_MASK_DATA_BIT_ASSIST     | \
+                                                      GNSS_GEN_ASSIST_MASK_ALMANAC             | \
+                                                      GNSS_GEN_ASSIST_MASK_UTC_MODEL           | \
+                                                      GNSS_GEN_ASSIST_MASK_AUX_INFO)     /* 0x1DFF */
+
+
+#define GNSS_ASSIST_MA_MANDATORY_MASK               (GNSS_COM_ASSIST_MASK_REF_TIME             | \
+                                                     GNSS_GEN_ASSIST_MASK_ACQUISITION          | \
+                                                     GNSS_GEN_ASSIST_MASK_AUX_INFO)      /* 0x1201 */
+
+
+#define GNSS_ASSIST_TIME_INDEPENDENT_MASK           (GNSS_COM_ASSIST_MASK_REF_LOCATION)  /* 0x0002 */
+
+
+#define GNSS_LAST_SEC_TIME       1000
+#define GNSS_MDT_GPS_RESPONSE_TIME  1000
+#define GNSS_MDT_LBS_ERRC_PERIOD_TIME  1280
+#define GNSS_INIT_TIMER_INTERVAL       10000
+
+
+/* ---LPPe HA GNSS Interface--- maximum element definition */
+#define GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL_ELEMENT     16
+#define GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL              8
+//#define GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL              1
+
+#define GNSS_HA_MAX_STORM_ELEMENT                     16
+#define GNSS_HA_MAX_LOCAL_TROPO_DELAY_AREA_ELEMENT     8
+#define GNSS_HA_MAX_LOCAL_TROPO_DELAY_TIME_ELEMENT     8
+//#define GNSS_HA_MAX_LOCAL_TROPO_DELAY_TIME_ELEMENT     1
+
+#define GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_ELEMENT       8
+#define GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_TIME_ELEMENT  8
+//#define GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_TIME_ELEMENT  1
+
+#define GNSS_HA_MAX_ALTITUDE_ASSIST_AREA_ELEMENT       8
+#define GNSS_HA_MAX_PRESSURE_ASSIST_ELEMENT           16
+//#define GNSS_HA_MAX_PRESSURE_ASSIST_ELEMENT           1
+
+#define GNSS_HA_MAX_CCP_SIGNAL_SUPP_ELEMENT            8
+#define GNSS_HA_MAX_CCP_PREF_STATION_LIST_ELEMENT      8  /* OMA-TS-LPPe: maxReferenceStations */
+#define GNSS_HA_MAX_WA_IONO_SURF_PER_SV_ELEMENT       16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_MECHANICS_SV_ELEMENT              16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_DCB_LIST_ELEMENT                  16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_DCB_ELEMENT                       16
+#define GNSS_HA_MAX_DEGRAD_MODEL_ELEMENT              16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_CCP_GENERIC_ELEMENT                8
+//#define GNSS_HA_MAX_CCP_GENERIC_ELEMENT                4
+
+#define GNSS_HA_MAX_CCP_PER_SIG_ELEMENT                8
+#define GNSS_HA_MAX_CCP_PER_SV_ELEMENT                16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+//#define GNSS_HA_MAX_CCP_PER_SV_ELEMENT                8  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+
+#define GNSS_HA_MAX_REQ_NAV_MODEL_ID_ELEMENT           8
+#define GNSS_HA_MAX_MEAS_PER_GNSS_ELEMENT             16
+#define GNSS_HA_MAX_MEAS_PER_SIGNAL_ELEMENT            8
+#define GNSS_HA_MAX_MEAS_PER_SV_ELEMENT               16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+#define GNSS_HA_MAX_TEC_PER_SV_ELEMENT                16  /* OMA-TS-LPPe: defines 64, reduce size to 16 */
+
+#define GNSS_HA_MAX_GNSS_GENERIC_ASSIST_DATA_ELEMENT  16
+#define GNSS_HA_MAX_GENERIC_AD_NAV_MODEL_ID_ELEMENT    8
+#define GNSS_HA_MAX_HA_GNSS_CAPA_ELEMENT               8
+
+
+/* ---LPPe HA GNSS Interface--- optional field validity bit definition */
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_BH_VALID      0x80
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_CH_VALID      0x40
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_AW_VALID      0x20
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_BW_VALID      0x10
+#define GNSS_HA_MAPPING_FUNC_PARAMS_BIT_CW_VALID      0x08
+
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_EH_VALID     0x80
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_ZW0_VALID    0x40
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_EW_VALID     0x20
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_GN_VALID     0x10
+#define GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_GE_VALID     0x08
+
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GN_PRESSURE       0x80
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GE_PRESSURE       0x40
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_TEMPERATURE       0x20
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_TEMPERATURE_RATE  0x10
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GN_TEMPERATURE    0x08
+#define GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_GE_TEMPERATURE    0x04
+
+
+/* ---LPPe HA GNSS Interface--- bitmask field bit defintion */
+#define GNSS_HA_COMM_AD_REQ_IONO_BIT_KLOBUCHAR_MODEL        0x01
+#define GNSS_HA_COMM_AD_REQ_IONO_BIT_IONO_STORM_WARNING     0x02
+
+#define GNSS_HA_COMM_AD_REQ_TROPO_BIT_DELAY_LIST            0x01
+#define GNSS_HA_COMM_AD_REQ_TROPO_BIT_SURFACE_PARAMS        0x02
+
+#define GNSS_HA_IONO_MEAS_REQ_BIT_TEC_PER_SV                0x01
+#define GNSS_HA_IONO_MEAS_REQ_BIT_ZENITH_TEC                0x02
+
+#define GNSS_HA_COMM_IONO_AD_SUPP_BIT_LOCAL_KLOBUCHAR            0x01
+#define GNSS_HA_COMM_IONO_AD_SUPP_BIT_IONO_STORM_WARNING         0x02
+#define GNSS_HA_COMM_IONO_AD_SUPP_BIT_WIDE_AREA_IONO_SURFACE     0x04
+
+#define GNSS_HA_COMM_TROPO_AD_SUPP_BIT_LOCAL_TROPOSPHERE_DELAY   0x01
+#define GNSS_HA_COMM_TROPO_AD_SUPP_BIT_SURFACE_PARAMETERS        0x02
+#define GNSS_HA_COMM_TROPO_AD_SUPP_BIT_MULTI_GRID_POINTS         0x04
+
+#define GNSS_HA_COMM_CCP_AD_SUPP_BIT_SUPPORT_AREA_ASSIST         0x01
+#define GNSS_HA_COMM_CCP_AD_SUPP_BIT_MULTI_REF_STATION           0x02
+
+#define GNSS_HA_GENE_AD_SUPP_BIT_BIT_TEC_PER_SV                  0x01
+#define GNSS_HA_GENE_AD_SUPP_BIT_BIT_ZENITH_TEC                  0x02
+
+#define GNSS_HA_MODE_SUPPORT_BIT_UE_BASED                        0x01
+#define GNSS_HA_MODE_SUPPORT_BIT_UE_ASSISTED                     0x02
+
+#define GNSS_HA_ANT_SUPPORT_BIT_ANT_DESCRIPTION                  0x01
+#define GNSS_HA_ANT_SUPPORT_BIT_ANT_ORIENTATION                  0x02
+
+
+
+/* NNUM ********************************************************************/
+
+typedef enum
+{
+    GNSS_NETWORK_CELL_TYPE_NULL,
+    GNSS_NETWORK_CELL_TYPE_EUTRA,
+    GNSS_NETWORK_CELL_TYPE_UTRA,
+    GNSS_NETWORK_CELL_TYPE_GSM
+} gnss_network_cell_type_enum;
+
+typedef enum
+{
+    GNSS_COMMON_ASSIST_DATA_TYPE_REF_TIME,
+    GNSS_COMMON_ASSIST_DATA_TYPE_REF_LOCACTION,
+    GNSS_COMMON_ASSIST_DATA_TYPE_ION_MODEL,
+    GNSS_COMMON_ASSIST_DATA_TYPE_EARTH_ORIENT_PARAMS
+} gnss_common_assist_data_type_enum;
+
+
+typedef enum
+{
+    GNSS_GENERIC_ASSIST_DATA_TYPE_TIME_MODEL,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_DGNSS_CORRECTION,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_NAVIGATION_MODEL,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_RTI,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_DATA_BIT_ASSIST,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_ACQUISITION,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_ALMANAC,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_UTC_MODEL,
+    GNSS_GENERIC_ASSIST_DATA_TYPE_AUX_INFO
+} gnss_generic_assist_data_type_enum;
+
+typedef enum
+{
+    GNSS_NAV_MODEL_REQ_TYPE_STORED_NAV_LIST,
+    GNSS_NAV_MODEL_REQ_TYPE_REQ_NAV_LIST
+} gnss_nav_model_req_type_enum;
+
+typedef enum
+{
+    GNSS_UTC_MODEL_TYPE_MODEL1,
+    GNSS_UTC_MODEL_TYPE_MODEL2,
+    GNSS_UTC_MODEL_TYPE_MODEL3,
+    GNSS_UTC_MODEL_TYPE_MODEL4
+} gnss_utc_model_type_enum;
+
+
+typedef enum
+{
+    GNSS_AUX_INFO_GNSS_TYPE_GPS,
+    GNSS_AUX_INFO_GNSS_TYPE_GLONASS
+} gnss_aux_info_gnss_type_enum;
+
+
+typedef enum
+{
+    GNSS_POS_RESULT_TYPE_POS_CNF,
+    GNSS_POS_RESULT_TYPE_ASSIST_DATA_REQ
+} gnss_pos_result_type_enum;
+
+
+typedef enum
+{
+    GNSS_MEAS_RESULT_TYPE_MEAS_CNF,
+    GNSS_MEAS_RESULT_TYPE_ASSIST_DATA_REQ
+} gnss_meas_result_type_enum;
+
+
+typedef enum
+{
+    GNSS_LOC_RESULT_NULL,
+    GNSS_LOC_RESULT_NO_ERROR,
+    GNSS_LOC_RESULT_UNDEFINED,
+    GNSS_LOC_RESULT_REQ_TIMEOUT,
+    GNSS_LOC_RESULT_NOT_ENOUGH_SATELLITES,
+    GNSS_LOC_RESULT_ASSIST_DATA_MISSING,  /* not used in POS(MEAS)_REQ/CNF primitive */
+
+    /* dedicated for RRLP */
+    GNSS_LOC_RESULT_METHOD_NOT_SUPPORTED,
+    GNSS_LOC_RESULT_REFERENCE_BTS_NOT_SERVING_BTS,
+
+    /* dedicated for RRC */
+    GNSS_LOC_RESULT_NOT_ACCOMPLISHED_TIMING_OF_CELL_FRAMES,  /* similar to FINE_TIME_ASSISTANCE_MEASUREMENTS_NOT_POSSIBLE */
+    GNSS_LOC_RESULT_REFERENCE_CELL_NOT_SERVING_CELL,         /* reference cell's SFN cannot be decoded */
+
+    /* dedicated for LPP */
+    GNSS_LOC_RESULT_FINE_TIME_ASSISTANCE_MEASUREMENTS_NOT_POSSIBLE,  /* fineTimeAssistanceMeasurementsNotPossible IE present */
+    GNSS_LOC_RESULT_ADR_MEASUREMENTS_NOT_POSSIBLE,                   /* adrMeasurementsNotPossible IE present */
+    GNSS_LOC_RESULT_MULTI_FREQUENCY_MEASUREMENTS_NOT_POSSIBLE        /* multiFrequencyMeasurementsNotPossible IE present */
+
+} gnss_loc_result_enum;
+
+typedef enum {
+    TIME_SIB_RESULT_OK          =0,         /* ERRC/EL1 reported useful info, check fields in lbs_errc_read_time_sib_ind_struct */
+    TIME_SIB_RESULT_NOT_TRY     =1,         /* No valid SIB info, and LBS doesn¡¦t need to try again */
+    TIME_SIB_RESULT_RE_TRY      =2,         /* No valid SIB info, and LBS may try again */
+    TIME_SIB_RESULT_TIMEOUT     =3          /* While trying to read SIB for time sync, guard timer timeouts(2s), Can retry, ask ERRC for further check*/
+} time_sib_result_enum;
+
+typedef enum {
+    TIME_SIB_CDMA_SYS_TIME_SYNC  =0,
+    TIME_SIB_CDMA_SYS_TIME_ASYNC =1
+} time_sib_cdma_sys_time_type_enum;
+
+typedef enum {
+    GNSS_TIME,
+    GPS_TIME,
+    UTC_TIME
+} frame_sync_pulse_time_type_enum;
+
+
+/* ---LPPe HA GNSS Interface--- */
+typedef enum
+{
+    GNSS_HA_IONO_MODEL_TYPE_STATIC_MODEL,
+    GNSS_HA_IONO_MODEL_TYPE_PERIODIC_MODEL
+} gnss_ha_iono_model_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_COMMON_ASSIST_DATA_TYPE_IONO_MODEL,
+    GNSS_HA_COMMON_ASSIST_DATA_TYPE_TROPO_MODEL,
+    GNSS_HA_COMMON_ASSIST_DATA_TYPE_ALTITUDE,
+    GNSS_HA_COMMON_ASSIST_DATA_TYPE_SOLAR_RAD,
+    GNSS_HA_COMMON_ASSIST_DATA_TYPE_CCP_ASSIST,
+} gnss_ha_common_assist_data_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_GENERIC_ASSIST_DATA_TYPE_WA_ION_SURF,
+    GNSS_HA_GENERIC_ASSIST_DATA_TYPE_SV_MECHANICS,
+    GNSS_HA_GENERIC_ASSIST_DATA_TYPE_SV_DCB,
+    GNSS_HA_GENERIC_ASSIST_DATA_TYPE_DEGRAD_MODEL,
+    GNSS_HA_GENERIC_ASSIST_DATA_TYPE_CCP_ASSIST,
+    GNSS_HA_GENERIC_ASSIST_DATA_TYPE_NAV_MODEL,
+} gnss_ha_generic_assist_data_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_CCP_ASSIST_COMMON_TYPE_COMMOM,
+    GNSS_HA_CCP_ASSIST_COMMON_TYPE_CONTROL
+} gnss_ha_ccp_assist_common_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_SV_TYPE_GPS_IIR,
+    GNSS_HA_SV_TYPE_GPS_IIRM,
+    GNSS_HA_SV_TYPE_GPS_IIF,
+    GNSS_HA_SV_TYPE_GPS_III,
+    GNSS_HA_SV_TYPE_GLONASS_M,
+    GNSS_HA_SV_TYPE_GLONASS_K1,
+    GNSS_HA_SV_TYPE_GLONASS_K2,
+    GNSS_HA_SV_TYPE_GLONASS_KM,
+    GNSS_HA_SV_TYPE_UNKNOWN
+} gnss_ha_sv_type_enum;
+
+
+typedef enum
+{
+   GNSS_HA_DCB_REF_PD_PILOT,
+   GNSS_HA_DCB_REF_PD_DATA,
+   GNSS_HA_DCB_REF_PD_NOT_APPLICABLE
+} gnss_ha_dcb_ref_pd_enum;
+
+
+typedef enum
+{
+    GNSS_HA_CODE_PHASE_ERR_TYPE_RMS,
+    GNSS_HA_CODE_PHASE_ERR_TYPE_CNR
+} gnss_ha_code_phase_err_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_AGNSS_QOR_TYPE_10_M,
+    GNSS_HA_AGNSS_QOR_TYPE_1_KM,
+    GNSS_HA_AGNSS_QOR_TYPE_10_KM,
+    GNSS_HA_AGNSS_QOR_TYPE_100_KM
+} gnss_ha_agnss_qor_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_HORI_UNC_TYPE_CEP,
+    GNSS_HA_HORI_UNC_TYPE_ELLIPSE
+} gnss_ha_hori_unc_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_MULTIPATH_DETECTION_TYPE_LOW,
+    GNSS_HA_MULTIPATH_DETECTION_TYPE_MODERATE,
+    GNSS_HA_MULTIPATH_DETECTION_TYPE_HIGH,
+    GNSS_HA_MULTIPATH_DETECTION_TYPE_NOT_MEASURED
+} gnss_ha_multipath_detect_type_enum;
+
+
+typedef enum
+{
+    GNSS_HA_TGT_ERR_CAUSE_UNDEFINED,
+    GNSS_HA_TGT_ERR_CAUSE_HA_METHOD_NOT_SUPPORTED
+} gnss_ha_tgt_err_cause_enum;
+
+
+typedef enum
+{
+    GNSS_HA_TGT_IONO_MEAS_ERR_CAUSE_UNDEFINED,
+    GNSS_HA_TGT_IONO_MEAS_ERR_CAUSE_IONO_MEAS_NOT_SUPPORTED,
+    GNSS_HA_TGT_IONO_MEAS_ERR_CAUSE_IONO_MEAS_NOT_AVAILABLE
+} gnss_ha_tgt_iono_meas_err_cause_enum;
+
+typedef enum
+{
+    GNSS_HA_TGT_ENV_OBSERVE_ERR_CAUSE_UNDEFINED,
+    GNSS_HA_TGT_ENV_OBSERVE_ERR_CAUSE_SURF_MEAS_NOT_SUPPORTED,
+    GNSS_HA_TGT_ENV_OBSERVE_ERR_CAUSE_SURF_MEAS_NOT_AVAILABLE
+} gnss_ha_tgt_env_observe_err_cause_enum;
+
+
+typedef enum
+{
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_UNDEFINED,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_NOT_SUPPORTED_BY_TARGET,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_UNAVAILABLE_FOR_ALL_REQUESTED_SIGNALS,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_ANTENNA_INFO_NOT_SUPPORTED,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_ANTENNA_INFO_NOT_AVAILABLE,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_PRESSURE_INFO_NOT_SUPPORTED,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_PRESSURE_INFO_NOT_AVAILABLE,
+    GNSS_HA_TGT_GNSS_ERR_CAUSE_GNSS_UNABLE_TO_MODIFY_CTRL_PARAMS
+} gnss_ha_tgt_gnss_err_cause_enum;
+
+
+typedef enum
+{
+    GNSS_HA_REQ_CCP_REF_STATION_TYPE_POS_BASED,
+    GNSS_HA_REQ_CCP_REF_STATION_TYPE_ID_BASED,
+    GNSS_HA_REQ_CCP_REF_STATION_TYPE_KILL_LIST
+} gnss_ha_req_ccp_ref_station_type_enum;
+
+/*gnss2lcsp_struct*/
+
+typedef char                kal_bool;
+typedef unsigned char       kal_uint8;
+typedef char                kal_int8;
+typedef unsigned short      kal_uint16;
+typedef short               kal_int16;
+typedef unsigned int        kal_uint32;
+typedef int                 kal_int32;
+typedef unsigned long long  kal_uint64;
+typedef long long           kal_int64;
+
+/*=== GNSS Common Assistance Data ===*/
+
+/* start for gnss reference time */
+typedef struct
+{
+    kal_uint8   svID;         /* satellite PRN [1..64] */
+    kal_uint16  tlmWord;      /* telemetry message [0..16383] */
+    kal_uint8   antiSpoof;    /* anti spoof flag [0..1] */
+    kal_uint8   alert;        /* alert flag [0..1] */
+    kal_uint8   tlmRsvdBits;  /* 2 bit reserved bits [0..3] */
+} gnss_gps_tow_assist_struct;
+
+
+typedef struct
+{
+    MTK_GNSS_ID_ENUM                gnssTimeID;
+    /**
+     * This field specifies the sequential number of days from the origin of the GNSS System Time as follows:
+     * GPS, QZSS, SBAS ¡V Days from January 6th 1980 00:00:00 UTC(USNO)
+     * Galileo ¡V TBD;
+     * GLONASS ¡V Days from January 1st 1996
+     */
+    kal_uint16                  gnssDayNumber;           /* [0..32767] */
+    kal_uint32                  gnssTimeOfDay;           /* [0..86399] in seconds */
+    kal_bool                    gnssTimeOfDayFracMsecValid;
+    kal_uint16                  gnssTimeOfDayFracMsec;   /* [0..999] in milli-seconds */
+    kal_bool                    notificationLeapSecondValid;
+    kal_uint8                   notificationLeapSecond;  /* only present when gnss=GLONASS */
+    kal_uint8                   numGpsTowAssist;         /* only present when gnss=GPS */
+    gnss_gps_tow_assist_struct  gpsTowAssist[GNSS_MAX_REF_TIME_SAT_ELEMENT];
+} gnss_system_time_struct;
+
+/* start for gnss reference location */
+typedef struct
+{
+    kal_bool    signOfLatitude;        /* TRUE: SOUTH, FALSE: NORTH */
+    kal_uint32  degreesLatitude;       /* [0..8388607] */
+    kal_int32   degreesLongitude;      /* [-8388608..8388607] */
+    kal_bool    signOfAltitude;        /* TRUE: DEPTH, FALSE: HEIGHT */
+    kal_uint16  altitude;              /* [0..32767] */
+    kal_uint8   uncertaintySemiMajor;  /* K: [0..127], uncertainty r (meter) = C*((1+x)^K-1), C=10, x=0.1 */
+    kal_uint8   uncertaintySemiMinor;  /* K: [0..127], uncertaintyr (meter) = C*((1+x)^K-1), C=10, x=0.1 */
+    kal_uint8   orientationMajorAxis;  /* bearing angle degree: [0-179] */
+    kal_uint8   uncertaintyAltitude;   /* K: [0..127], uncertainty h (meter) = C*((1+x)^K-1), C=45, x=0.025 */
+    kal_uint8   confidence;            /* [0..100] */
+} gnss_reference_location_struct;
+/* end for gnss reference location */
+
+/* ---LPPe HA GNSS Interface---begin--- */
+typedef struct
+{
+    gnss_system_time_struct  beginTime;          /* specify the start time of the validity period */
+    kal_bool                 beginTimeAltValid;
+    kal_uint16               beginTimeAlt;       /* [0..2881], specify the alternative start time, and the start time is relative the time the message was received, scale factor 15 min (range from 0 minutes to 43215 min = 30 days) */
+    kal_uint16               duration;           /* [0..2881], specify the duration of the validity period after the beginTime, scale factor 15 min (range from 0 minutes to 43215 min = 30 days) */
+} gnss_ha_validity_period_struct;
+
+
+typedef struct
+{
+    kal_uint8                 regionSizeInv;       /* [1..255], specify the inverse of the size of each side of the region in degrees, for value N the size is 10/N degrees */
+    kal_bool                  areaWidthValid;
+    kal_uint16                areaWidth;           /* [2..9180], specify the number of regions in the area in East-West direction, if the field is not present, the value is 1 */
+    kal_uint16                codedLatOfNWCorner;  /* [0..4589], specify the latitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+    kal_uint16                codedLonOfNWCorner;  /* [0..9179], specify the longitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+
+    kal_bool                  rleListValid;
+    //LPP_EXT_OMA_LPPe_RleList  rleList;             /* TBD: redefine internal structure? */  /* This field lists the regions in which the data is valid. If the field is not present, the data is valid in all the regions in the area */
+} gnss_ha_validity_area_struct;
+
+
+typedef struct
+{
+    kal_uint8   regionSizeInv;       /* specify the inverse of the size of each side of the region in degrees, for value N the size is 10/N degrees */
+    kal_bool    areaWidthValid;
+    kal_uint16  areaWidth;           /* specify the number of regions in the area in East-West direction, if the field is not present, the value is 1 */
+    kal_uint16  codedLatOfNWCorner;  /* specify the latitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+    kal_uint16  codedLonOfNWCorner;  /* specify the longitude of the North-West corner of the area, encoded as explained in OMA-TS-LPPe Appendix C.1 */
+} gnss_ha_storm_validity_area_struct;  /* only used in gnss_ha_iono_storm_ind_struct */
+
+
+typedef struct
+{
+    kal_uint8  duration;          /* [1..63], scale factor 15 min, range [15, 945 min], i.e. upto 16 hours */
+    kal_bool   durationLSBValid;
+    kal_uint8  durationLSB;       /* [1..89], finer granularity duration, scale factor is 10 seconds, range [10, 890] seconds */
+} gnss_ha_duration;
+
+
+typedef struct
+{
+    kal_uint8   validityBitmap;  /* bhValid, chValid, awValid, bwValid, cwValid, use GNSS_HA_MAPPING_FUNC_PARAMS_BIT_*_VALID */
+    kal_uint16  ah;  /* [0..16383], the a-coefficient of the hydrostatic mapping function, scale factor 2^-14 */
+    /* optional */
+    kal_uint16  bh;  /* [0..16383], the b-coefficient of the hydrostatic mapping function, scale factor 2^-14 */
+    /* optional */
+    kal_uint16  ch;  /* [0..16383], the c-coefficient of the hydrostatic mapping function, scale factor 2^-14 */
+    /* optional */
+    kal_uint16  aw;  /* [0..16383], the a-coefficient of the wet mapping function, scale factor 2^-14 */
+    /* optional */
+    kal_uint16  bw;  /* [0..16383], the b-coefficient of the wet mapping function, scale factor 2^-14 */
+    /* optional */
+    kal_uint16  cw;  /* [0..16383], the c-coefficient of the wet mapping function, scale factor 2^-14 */
+} gnss_ha_mapping_func_params_struct;
+
+
+typedef struct
+{
+    kal_int32  latitude;            /* [-2147483648..2147483647], latitude based on WGS84 [GPS-ICD-200D] datum, the relation between the latitude X in range [-90', 90'],
+                                       and the coded number N is N = floor((X/90')*2^31), where value N=2^31 is coded as N=2^31-1, resolution 4.7 mm */
+    kal_int32  longitude;           /* [-2147483648..2147483647], longitude based on WGS84 [GPS-ICD-200D] datum, the relation between the longitude X in range [-180', 180'),
+                                       and the coded number N is floor((X/180')*2^31), worst-case resolution (at the Equator) 9.3 mm */
+    kal_bool   cepValid;
+    kal_uint8  cep;                 /* [0..255], horizontal uncertainty expressed as Circular Error Probable expressed as the coded number N,
+                                       the relation between the CEP and the coded number is given by CEP = 0.3*((1+0.02)^N - 1) meters, range [0, 45.6) meters */
+    kal_bool   uncSemiMajorValid;
+    kal_uint8  uncSemiMajor;        /* [0..255], the semi-major axis of the horizontal uncertainty ellipse expressed as the coded number N,
+                                       the relation between the semi-major axis and the coded number is given by semi-major axis = 0.3*( (1+0.02)^N -1) meters, range [0, 45.6) meters */
+    kal_bool   uncSemiMinorValid;
+    kal_uint8  uncSemiMinor;        /* [0..255], the semi-minor axis of the horizontal uncertainty ellipse expressed as the coded number N,
+                                       the relation between the semi-minor axis and the coded number is given by semi-minor axis = 0.3*((1+0.02)^N -1) meters, range [0, 45.6) meters */
+    kal_bool   offsetAngleValid;
+    kal_uint8  offsetAngle;         /* [0..179], the angle of semi-major axis measured clockwise with respect to True North in steps of 1 degree */
+
+    kal_bool   confHorizontalValid;
+    kal_uint8  confHorizontal;      /* [0..99], specify the horizontal confidence percentage associated with the CEP or Uncertainty Ellipse depending upon which is included */
+    kal_int32  altitude;            /* [-64000..1280000], altitude with respect to WGS84 [GPS-ICD-200D] ellipsoid, scale factor 2^(-7) meters, range [-500, 10000] meters */
+    kal_uint8  uncAltitude;         /* [0..255], the altitude uncertainty expressed as the coded number N, the relation between the altitude uncertainty and
+                                       the coded number is given by uncertainty= 0.3*((1+0.02)^N -1) meters, range [0, 45.6) meters */
+    kal_bool   confVerticalValid;
+    kal_uint8  confVertical;        /* [0..99], specify the confidence percentage associated with the altitude uncertainty */
+} gnss_ha_high_accu_3d_position_struct;
+
+/* begin of gnss_ha_ionospheric_model */
+typedef struct
+{
+    gnss_ha_validity_period_struct  validityPeriod;  /* specify the start time and duration of the model validity period */
+    kal_int8                        alfa0;           /* [-128..127], specify the alpha0 parameter of the Klobuchar model, scale factor 2^(-30) seconds */
+    kal_int8                        alfa1;           /* [-128..127], specify the alpha1 parameter of the Klobuchar model, scale factor 2^(-27) seconds/semi-circle */
+    kal_int8                        alfa2;           /* [-128..127], specify the alpha2 parameter of the Klobuchar model, scale factor 2^(-24) seconds/semi-circle^2 */
+    kal_int8                        alfa3;           /* [-128..127], specify the alpha3 parameter of the Klobuchar model, scale factor 2^(-24) seconds/semi-circle^3 */
+    kal_int8                        beta0;           /* [-128..127], specify the beta0 parameter of the Klobuchar model, scale factor 2^11 seconds */
+    kal_int8                        beta1;           /* [-128..127], specify the beta1 parameter of the Klobuchar model, scale factor 2^14 seconds/semi-circle */
+    kal_int8                        beta2;           /* [-128..127], specify the beta2 parameter of the Klobuchar model, scale factor 2^16 seconds/semi-circle^2 */
+    kal_int8                        beta3;           /* [-128..127], specify the beta3 parameter of the Klobuchar model, scale factor 2^16 seconds/semi-circle^3 */
+} gnss_ha_local_klobuchar_model_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_area_struct          validityArea;
+    kal_uint8                             numKlobucharModel;
+    gnss_ha_local_klobuchar_model_struct  klobucharModel[GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL];  /* local klobuchar model per validity period */
+} gnss_ha_local_klobuchar_model_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                                     numKlobucharElement;
+    gnss_ha_local_klobuchar_model_element_struct  klobucharElement[GNSS_HA_MAX_LOCAL_KLOBUCHAR_MODEL_ELEMENT];  /* local klobuchar model per validity area */
+} gnss_ha_local_klobuchar_model_list_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_period_struct      validityPeriod;   /* specify the time interval over which the storm data is valid */
+    //LPP_EXT_OMA_LPPe_AGNSS_RleListIono  rleListIono;      /* TBD: structure is too big, redefine internal structure? */
+} gnss_ha_storm_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                     numStormElement;
+    gnss_ha_storm_element_struct  stormElement[GNSS_HA_MAX_STORM_ELEMENT];  /* storm indication element per validity period */
+} gnss_ha_storm_list_struct;
+
+
+typedef struct
+{
+    gnss_ha_storm_validity_area_struct  area;       /* rlelist is not not included or ignored in IonoStormIndication */
+    gnss_ha_storm_list_struct           stormList;  /* provide information on the ionospheric activity in the area defined by area */
+} gnss_ha_iono_storm_ind_struct;
+
+
+typedef struct
+{
+    kal_bool                                   localKlobucharListValid;
+    gnss_ha_local_klobuchar_model_list_struct  localKlobucharList;  /* localized Klobuchar model */
+
+    kal_bool                                   ionoStormIndValid;
+    gnss_ha_iono_storm_ind_struct              ionoStormInd;        /* information on the ionosphere conditions in the area */
+} gnss_ha_ionospheric_static_model_struct;
+
+
+typedef struct
+{
+    kal_bool                      durationValid;
+    gnss_ha_duration              duration;           /* specify the length of the continuous periodic assistance session */
+
+    kal_bool                      rateValid;
+    kal_uint8                     rate;               /* [1..64], specify the length of the continuous periodic assistance session */
+
+    kal_bool                      refPositionValid;
+    //LPP_EXT_Ellipsoid_Point       referencePosition;  /* TBD: redefine internal structure? */
+
+    kal_bool                      validityAreaValid;
+    gnss_ha_validity_area_struct  validityArea;
+} gnss_ha_wa_iono_control_param_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_period_struct  validityPeriod;  /* define the validity period of the widea area ionosphere correction */
+} gnss_ha_wa_iono_common_param_struct;
+
+
+typedef struct
+{
+    kal_bool                                controlParamsValid;
+    gnss_ha_wa_iono_control_param_struct    controlParams;       /* carry the control parameters of the periodic Wide Area ionosphere surface corrections */
+    kal_bool                                commonParamsValid;
+    gnss_ha_wa_iono_common_param_struct     commonParams;        /* carry the common parameters of the periodic Wide Area ionosphere surface corrections */
+} gnss_ha_ionospheric_periodic_model_struct;
+
+
+typedef struct
+{
+    kal_uint16                                     transactionID;
+    gnss_ha_iono_model_type_enum                   type;
+    union
+    {
+        gnss_ha_ionospheric_static_model_struct    staticModel;
+        gnss_ha_ionospheric_periodic_model_struct  periodicWAIono;  /* based on the real-time GNSS observations and thus updated frequently to the target */
+    } data;
+} gnss_ha_common_ionospheric_model_struct;
+/* end of gnss_ha_ionospheric_model */
+
+
+/* begin of gnss_ha_troposphere_model */
+typedef struct
+{
+    gnss_ha_validity_period_struct      validityPeriod;     /* specify the start time and duration of the local troposphere parameters validity period */
+    kal_uint16                          zh0;                /* [0..4095], the hydrostatic zenith delay (meters), measured at the reference altitude level, scale factor 2^(-10) m */
+
+    kal_uint8                           validityBitmap;     /* ehValid, zw0Valid, ewValid, gNValid, gEValid, use GNSS_HA_LOCAL_TROPO_DELAY_TIME_ELEMENT_BIT_*_VALID */
+    /* optional */
+    kal_uint16                          eh;                 /* [0..4095], the exponential fit parameter (1/m) for scaling zh0 to the target altitude, scale factor 2^(-20) (1/m) */
+    /* optional */
+    kal_uint16                          zw0;                /* [0..4095], the wet zenith delay (meters), measured at the reference altitude level, scale factor 2^(-10) m */
+    /* optional */
+    kal_uint16                          ew;                 /* [0..4095], the exponential fit parameter (1/m) for scaling zw0 to the target altitude, scale factor 2^(-20) (1/m) */
+    /* optional */
+    kal_int16                           gN;                 /* [-8192..8191], the gradient parameter (m) in North direction of the azimuthally asymmetric part of the tropospheric slant delay, scale factor 2^(-7) m */
+    /* optioanl */
+    kal_int16                           gE;                 /* [-8192..8191], the gradient parameter (m) in East direction of the azimuthally asymmetric part of the tropospheric slant delay, scale factor 2^(-7) m */
+
+    gnss_ha_mapping_func_params_struct  mappingFuncParams;  /* coefficients of the mapping functions */
+} gnss_ha_local_tropo_delay_time_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                                      numDelayTimeElement;
+    gnss_ha_local_tropo_delay_time_element_struct  delayTimeElement[GNSS_HA_MAX_LOCAL_TROPO_DELAY_TIME_ELEMENT];
+} gnss_ha_local_tropo_delay_time_list_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_area_struct                validityArea;         /* specify the geographical validity area of the local troposphere model parameters */
+
+    kal_bool                                    refAltitudeValid;
+    kal_int16                                   refAltitude;          /* [-1000..8192], specify the reference altitude (from nominal sea level, EGM96) at which the delay measurements are made, scale factor 1m, if absent, the reference altitude is the zero nominal sea level */
+
+    kal_bool                                    graRefPositionValid;
+    //LPP_EXT_Ellipsoid_Point                     graRefPosition;       /* TBD: redefine internal structure? */  /* specify the origion for the spatial gradients gN and gE, if absent, the origin is taken as the middle point of the validity area */
+
+    gnss_ha_local_tropo_delay_time_list_struct  delayList;            /* specify the troposphere delays */
+} gnss_ha_local_tropo_delay_area_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                                      numDelayAreaElement;
+    gnss_ha_local_tropo_delay_area_element_struct  delayAreaElement[GNSS_HA_MAX_LOCAL_TROPO_DELAY_AREA_ELEMENT];
+} gnss_ha_troposphere_delay_list_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_period_struct      validityPeriod;  /* specify the start time and duration of the surface parameter validity period */
+
+    kal_int16                           pressure;        /* [-1024..1023], local atmospheric pressure measurement (hPa) at the altitude given by refAltitude, scale factor 0.1 hPa, the value is added to the nominal pressure of 1013hPa */
+    kal_int8                            pressureRate;    /* [-128..127], rate of change of pressure, when calculating the pressure, the origin of time is the begin time of the validity period, scale factor 10 Pa/hour */
+
+    kal_uint8                           validityBitmap;  /* gNpressureValid, gEpressureValid, temperatureValid, temperatureRateValid, gNtemperatureValid, gEtemperatureValid, use GNSS_HA_LOCAL_SURF_PARAMS_TIME_ELEMENT_BIT_* */
+    /* optional */
+    kal_int8                            gNpressure;      /* [-128..127], specify the northward gradient of the atmospheric pressure, if this field is present, but gE is not given, the eastward gradient is zero, scale factor 10 Pa/km */
+    /* optional */
+    kal_int8                            gEpressure;      /* [-128..127], specify the eastward gradient of the atmospheric pressure, if this field is present, but gN is not given, the nothward gradient is zero, scale factor 10 Pa/km */
+    /* optional */
+    kal_int8                            temperature;     /* [-64..63], local temperature measurement at the reference altitude refAltitude, scale factor 1K, the value is added to 273K */
+    /* optional */
+    kal_int8                            temperatureRate; /* [-16..16], local temperature change rate, the scale factor 1K/hour */
+    /* optional */
+    kal_int8                            gNtemperature;   /* [-8..7], specify the northward gradient of the temperature, if this field is present, but gE is not given, the eastward gradient is zero, scale factor 1 K/km */
+    /* optional*/
+    kal_int8                            gEtemperature;   /* [-8..7], specify the eastward gradient of the temperature, if this field is present, but gN is not given, the nothward gradient is zero, scale factor 1 K/km */
+
+    gnss_ha_mapping_func_params_struct  mappingFuncParams;  /* coefficients of the mapping functions */
+} gnss_ha_local_surface_params_time_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                                         numParamsTimeElements;
+    gnss_ha_local_surface_params_time_element_struct  paramsTimeElement[GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_TIME_ELEMENT];
+} gnss_ha_local_surface_params_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_area_struct         validityArea;         /* specify the geographical validity area of the local troposphere model parameters */
+
+    kal_bool                             refAltitudeValid;
+    kal_int16                            refAltitude;          /* [-1000..8192], specify the reference altitude (from nominal sea level, EGM96) at which the surface measurements are made, scale factor 1m, if absent, the reference altitude is the zero nominal sea level EGM96 */
+
+    kal_bool                             graRefPositionValid;
+    //LPP_EXT_Ellipsoid_Point              graRefPosition;       /* TBD: redefine internal structure? */  /* specify the origion for the spatial gradients gN and gE, if absent, the origin is taken as the middle point of the validity area */
+
+    gnss_ha_local_surface_params_struct  paramsList;           /* specify the surface parameters */
+} gnss_ha_local_surface_params_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                                    numParamsElements;
+    gnss_ha_local_surface_params_element_struct  paramsElement[GNSS_HA_MAX_LOCAL_SURFACE_PARAMS_ELEMENT];
+} gnss_ha_local_surface_params_list_struct;
+
+
+typedef struct
+{
+    kal_uint16                                transactionID;
+    kal_bool                                  tropoDelayListValid;
+    gnss_ha_troposphere_delay_list_struct     tropoDelayList;         /* provide the zenith troposphere delay components determined in a given location and the needed parameters to adjust the delay to the target's altitude */
+    kal_bool                                  surfaceParamListValid;
+    gnss_ha_local_surface_params_list_struct  surfaceParametersList;  /* provide the surface pressure and optionally temperature that allow the target to compute the tropospheric delay using one of the known atmosphere models, such as the Hopfield or Saastamoinen model */
+} gnss_ha_common_troposphere_model_struct;
+/* end of gnss_ha_troposphere_model */
+
+
+/* begin of gnss_ha_altitude_assist */
+typedef struct
+{
+    gnss_ha_validity_period_struct  validityPeriod;     /* specify the start time and duration of the altitude assistance validity period */
+
+    kal_int16                       pressure;           /* [-1024..1023], local atmospheric pressure measurement (hPa) at the altitude given by refAltitude, scale factor 10 Pa, the value is added to the nominal pressure of 1013hPa */
+    kal_bool                        pressureRateValid;
+    kal_int8                        pressureRate;       /* [-128..127], rate of change of pressure, when calculating the pressure, the origin of time is the begin time of the validity period, scale factor 10 Pa/hour */
+
+    kal_bool                        gNValid;
+    kal_int8                        gN;                 /* [-128..127], specify the northward gradient of the atmospheric pressure, scale factor 10 Pa/km */
+    kal_bool                        gEValid;
+    kal_int8                        gE;                 /* [-128..127], specify the eastward gradient of the atmospheric pressure, scale factor 10 Pa/km */
+} gnss_ha_pressure_assist_element_struct;
+
+
+typedef struct
+{
+   kal_uint8                               numPressureElements;
+   gnss_ha_pressure_assist_element_struct  pressureElement[GNSS_HA_MAX_PRESSURE_ASSIST_ELEMENT];
+} gnss_ha_pressure_assist_list_struct;
+
+
+typedef struct
+{
+   gnss_ha_validity_area_struct         validityArea;            /* specify the geographical validity area of the altitude assistance */
+
+   kal_bool                             gradRefPositionValid;
+   gnss_reference_location_struct       gradRefPosition;         /* specify the origin for the spatial gradients gN and gE, if absent, the origin is taken as the middle point of the validity area */
+
+   kal_bool                             refAltitudeValid;
+   kal_int16                            refAltitude;             /* specify the reference altitude (from nominal sea level, [EGM96]) at which the surface measurements are made, scale factor 1m, if absent, the reference altitude is the zero nominal sea level */
+
+   gnss_ha_pressure_assist_list_struct  pressureAssistanceList;  /* specify the set of pressure assistance elements for different periods of time */
+} gnss_ha_altitude_assist_area_element_struct;
+
+
+typedef struct
+{
+    kal_uint16                                   transactionID;
+    kal_uint8                                    numAltitudeAreaElement;
+    gnss_ha_altitude_assist_area_element_struct  altitudeAreaElement[GNSS_HA_MAX_ALTITUDE_ASSIST_AREA_ELEMENT];
+} gnss_ha_common_altitude_assist_struct;
+/* end of gnss_ha_altitude_assist */
+
+
+/* begin of gnss_ha_altitude_assist */
+typedef struct
+{
+    kal_uint16  transactionID;
+    kal_uint16  solarRad;  /* specifies the solar radiation at one AU from the Sun, scale factor 1 Wm^(-2) */
+} gnss_ha_common_solar_radiation_struct;
+/* end of gnss_ha_altitude_assist */
+
+
+/* begin of gnss_ha_common_ccp_assist */
+typedef struct
+{
+    MTK_GNSS_ID_ENUM  gnssID;       /* specify the GNSS type */
+    kal_uint8     gnssSignals;  /* specify the GNSS signal types for which CCP assistance can be provided in the area, GNSS Signal(s), map to GNSS_SGN_ID_BITMAP_* */
+} gnss_ha_ccp_signal_supp_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                               numSigSuppElement;
+    gnss_ha_ccp_signal_supp_element_struct  sigSuppElement[GNSS_HA_MAX_CCP_SIGNAL_SUPP_ELEMENT];
+} gnss_ha_ccp_signal_supp_struct;
+
+
+typedef struct
+{
+    gnss_ha_validity_area_struct    areaDescr;  /* provide the description of the area */
+    gnss_ha_ccp_signal_supp_struct  sigSupp;    /* provide the GNSS signal support information */
+} gnss_ha_ccp_support_area_struct;
+
+
+typedef struct
+{
+   kal_uint16                                 refStationID;       /* define the ID of the reference station */
+   gnss_ha_high_accu_3d_position_struct       refStationLoc;      /* define the location of the reference station, of which ID is refStationID */
+   kal_bool                                   antennaDescrValid;
+   //LPP_EXT_OMA_LPPe_AGNSS_AntennaDescription  antennaDescr;       /* TBD: redefine internal structure? */ /* specify the antenna type used at the reference station */
+} gnss_ha_ccp_pref_station_list_element_struct;
+
+
+typedef struct
+{
+
+    kal_uint8                                     numPrefStationElement;
+    gnss_ha_ccp_pref_station_list_element_struct  prefStationElement[GNSS_HA_MAX_CCP_PREF_STATION_LIST_ELEMENT];
+} gnss_ha_ccp_pref_station_list_struct;
+
+
+typedef struct
+{
+    kal_bool                              supportAreaValid;
+    gnss_ha_ccp_support_area_struct       supportArea;      /* provide information on the area, in which CCP is supported */
+
+    kal_bool                              nbrListValid;
+    gnss_ha_ccp_pref_station_list_struct  nbrList;          /* provide information on the possible neighbour reference stations */
+
+    kal_bool                              durationValid;
+    gnss_ha_duration                      duration;         /* specify the length of the continuous periodic assistance session */
+
+    kal_bool                              rateValid;
+    kal_uint8                             rate;             /* [1..64], specify the interval between the assistance data deliveries in seconds */
+
+    kal_bool                              refStationListValid;
+    gnss_ha_ccp_pref_station_list_struct  refStationList;   /* provide the locations of the reference stations for which CCP assistance is being provided */
+} gnss_ha_ccp_assist_common_ctrl_params_struct;
+
+
+typedef struct
+{
+    kal_uint16                           transactionID;
+    gnss_ha_ccp_assist_common_type_enum  type;
+    union
+    {
+        gnss_system_time_struct                       commParamsRefSysTime;  /* define the CCP-specific common parameters (reference time) */
+        gnss_ha_ccp_assist_common_ctrl_params_struct  ctrlParams;            /* define the CCP-specific control parameters */
+    } data;
+} gnss_ha_common_ccp_assist_struct;
+/* end of gnss_ha_common_ccp_assist */
+
+
+/* begin of gnss_ha_req_ionospheric_model */
+typedef struct
+{
+    kal_uint8                ionoReq;            /* specify which ionosphere models are being requested for, mapping to GNSS_HA_COMM_AD_REQ_IONO_BIT_* */
+
+    kal_bool                 reqBeginTimeValid;
+    gnss_system_time_struct  reqBeginTime;       /* specify the first time instant when an ionosphere model is needed, if absent, begin time is the current time */
+
+    gnss_ha_duration         duration;           /* specify for how long period the ionospheric model is requested */
+} gnss_ha_req_ionospheric_static_model_struct;
+
+
+typedef struct
+{
+    kal_bool          durationValid;
+    gnss_ha_duration  duration;       /* specify the length of the continuous periodic assistance session */
+
+    kal_bool          rateValid;
+    kal_uint8         rate;           /* [0..64], specify the interval between the assistance data deliveries in seconds */
+} gnss_ha_req_ionospheric_periodic_model_struct;
+
+
+typedef struct
+{
+    gnss_ha_iono_model_type_enum                   type;
+    union
+    {
+        gnss_ha_req_ionospheric_static_model_struct    staticModelReq;     /* request for the one-shot ionosphere models */
+        gnss_ha_req_ionospheric_periodic_model_struct  periodicWAIonoReq;  /* request for periodic ionosphere models */
+    } data;
+} gnss_ha_req_ionospheric_model_struct;
+/* end of gnss_ha_req_ionospheric_model */
+
+
+/* begin of gnss_ha_req_troposphere_model */
+typedef struct
+{
+    kal_uint8                tropoModelReq;           /* specify the desired model or models, mapping to GNSS_HA_COMM_AD_REQ_TROPO_BIT_* */
+
+    kal_bool                 supportMultiGridPoints;  /* indicate if the target is requesting parameter sets originating from multiple locations around it (TRUE)
+                                                         FALSE means that only the nearest grid point parameters are requested */
+
+    kal_bool                 reqBeginTimeValid;
+    gnss_system_time_struct  reqBeginTime;            /* specify the first time instant when a valid troposphere model is needed, if absent, the begin time is the current time */
+
+    gnss_ha_duration         duration;                /* specify how long time the tropospheric model is requested for */
+} gnss_ha_req_troposphere_model_struct;
+/* end of gnss_ha_req_troposphere_model */
+
+
+/* begin of gnss_ha_req_altitude_assist */
+typedef struct
+{
+    kal_bool                 reqBeginTimeValid;
+    gnss_system_time_struct  reqBeginTime;       /* specify the first time instant when altitude assistance is needed, if absent, the begin time is the current time */
+
+    kal_bool                 durationValid;
+    gnss_ha_duration         duration;           /* specify how long time the altitude assistance is requested for, if absent, altitude assistance is requested for the current moment */
+} gnss_ha_req_altitude_assist_struct;
+/* end of gnss_ha_req_altitude_assist */
+
+
+/* begin of gnss_ha_req_ccp_ctrl_params */
+typedef struct
+{
+   gnss_ha_high_accu_3d_position_struct  reqRefStationLoc;  /* request for a new reference station based on the position. The position may or may not be the target position */
+   gnss_ha_agnss_qor_type_enum           qor;               /* QoR (Quality-of-Reference station) defines how close to the requested location the closest reference station must be
+                                                               In case the closest reference station is within the uncertainty area of the target location, the QoR parameter is neglected */
+} gnss_ha_req_ccp_pos_based_ref_station_struct;
+
+
+typedef struct
+{
+    kal_uint8   numRefStationIDElement;
+    kal_uint16  refStationIDElement[GNSS_HA_MAX_CCP_PREF_STATION_LIST_ELEMENT];  /* [0..65535], contain the reference station ID list */
+} gnss_ha_req_ccp_ref_station_list_struct;
+
+
+typedef struct
+{
+    gnss_ha_req_ccp_ref_station_type_enum             type;
+    union
+    {
+        gnss_ha_req_ccp_pos_based_ref_station_struct  posBasedRefStationReq;
+        gnss_ha_req_ccp_ref_station_list_struct       idBasedRefStationReq;    /* request for CCP AD for a new reference station based on the reference station ID */
+        gnss_ha_req_ccp_ref_station_list_struct       refStationKillList;      /* terminate CCP AD deliveries for selected reference stations based on their reference station IDs */
+    } data;
+} gnss_ha_req_ccp_ref_station_struct;
+
+
+typedef struct
+{
+    kal_bool                            durationValid;
+    gnss_ha_duration                    duration;          /* specify the length of the continuous periodic assistance session */
+
+    kal_bool                            rateValid;
+    kal_uint8                           rate;              /* [1..64], specify the interval between the assistance data deliveries in seconds */
+
+    kal_bool                            refStationValid;
+    gnss_ha_req_ccp_ref_station_struct  refStation;        /* specify the request/modification of the active reference station set */
+} gnss_ha_req_ccp_common_req_struct;
+
+
+typedef struct
+{
+    kal_bool                           ccpSuppAreaReq;    /* TRUE if request for the information on the CCP assistance availability in the target area */
+    kal_bool                           ccpNbrListReq;     /* TRUE if request for the information on the reference stations in the vicinity of the target */
+
+    gnss_ha_req_ccp_common_req_struct  ccpCommonRequest;  /* request for a new reference station or stopping CCP AD delivery for a reference station */
+} gnss_ha_req_ccp_ctrl_params_struct;
+/* end of gnss_ha_req_ccp_ctrl_params */
+
+
+/* begin of gnss_ha_degradation_model */
+typedef struct
+{
+    kal_uint8  clockRMS0;       /* specify the constant term of the clock model degradation model by cRMS0 =((1+0.1)^clockRMS0 -1) meters,
+                                   where clockRMS0 = 31 denotes 'Use At Own Risk', the range is [0, 16.45) meters, refer to OMA-TS-LPPe Appendix C.6.1 */
+    kal_bool   clockRMS1Valid;
+    kal_uint8  clockRMS1;       /* specify the first order term of the clock model degradation model, cRMS1, scale factor 2^(-14) m/s,
+                                   range [0, 4.3e-4) m/s, refer to OMA-TS-LPPe Appendix C.6.1 */
+} gnss_ha_clock_model_degrad_model_struct;
+
+
+typedef struct
+{
+    kal_uint8  orbitRMS0;       /* specify the constant term of the orbit model degradation model by oRMS0 =((1+0.1)^orbitRMS0 -1) meters,
+                                   where orbitRMS0 = 31 denotes 'Use At Own Risk', the range is [0, 16.45) meters, refer to OMA-TS-LPPe Appendix C.6.2 */
+    kal_bool   orbitRMS1Valid;
+    kal_uint8  orbitRMS1;       /* specify the first order term of the orbit model degradation model, oRMS1, scale factor 2^(-14) m/s, range [0, 4.3e-4) m/s,
+                                   refer to OMA-TS-LPPe Appendix C.6.2 */
+} gnss_ha_orbit_model_degrad_model_struct;
+
+
+typedef struct
+{
+    kal_uint8                                svID;                   /* [0..63], specify the SV for which degradation models are provided */
+    gnss_ha_clock_model_degrad_model_struct  clockDegradationModel;  /* provide the degradation model for the clock model */
+    gnss_ha_orbit_model_degrad_model_struct  orbitDegradationModel;  /* provide the degradation model for the orbit model */
+} gnss_ha_degrad_model_element_struct;
+
+
+typedef struct
+{
+    kal_uint16                               transactionID;
+    MTK_GNSS_ID_ENUM                             gnssId;
+
+    kal_uint8                                numDegradModelElement;
+    gnss_ha_degrad_model_element_struct      degradModelElement[GNSS_HA_MAX_DEGRAD_MODEL_ELEMENT];
+} gnss_ha_generic_degradation_model_struct;
+/* end of gnss_ha_degradation_model */
+
+
+/* begin of gnss_ha_generic_ccp_assist */
+typedef struct
+{
+    gnss_ha_code_phase_err_type_enum  type;
+    union
+    {
+        kal_uint8  codePhaseRMSError;  /* contain the pseudorange RMS error value, representation refer to TS 36.355 floating-point representation of GNSS-MeasurementList field descriptions */
+        kal_uint8  cnr;                /* carrier-to-noise ratio, scale factor 0.25 dB-Hz, range [0, 63.75] dB-Hz */
+    } data;
+} gnss_ha_code_phase_error_struct;
+
+
+typedef struct
+{
+    kal_uint8                        svID;                      /* [0..63], identify the SV for which CCP assistance is being provided */
+
+    kal_bool                         intCodePhaseValid;
+    kal_uint8                        intCodePhase;              /* [0..255], indicate the integer milli-second part of the code phase */
+
+    kal_uint32                       codePhase;                 /* [0.. 14989622], contain the sub-millisecond part of the code phase observation
+                                                                   for the particular satellite signal at the reference time, scale factor 0.02 meters, range [0, 299792.44] meters */
+
+    kal_bool                         codePhaseErrorValid;
+    gnss_ha_code_phase_error_struct  codePhaseError;            /* code phase error */
+
+    kal_int32                        phaseRangeDelta;           /* [-524288.. 524287], define the (Phase Range ¡V Pseudorange), scale factor 0.5 mm, range [-262.144, 262.1435] meters */
+
+    kal_bool                         phaseRangeRMSErrorValid;
+    kal_uint8                        phaseRangeRMSerror;        /* [0..127], contain the RMS error of the continuous carrier phase, scale factor 2^(-10) meters, in the range [0, 0.12403) meters */
+
+    kal_bool                         lockIndicator;             /* TRUE: if the carrier phase tracking has been continuous between the previous and the current assistance
+                                                                   data delivery. FALSE: a cycle slip has occurred */
+} gnss_ha_ccp_sv_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                      numCCPPerSVElement;
+    gnss_ha_ccp_sv_element_struct  ccpPerSVElement[GNSS_HA_MAX_CCP_PER_SV_ELEMENT];
+} gnss_ha_ccp_per_sv_list_struct;
+
+
+typedef struct
+{
+    kal_uint8                       signalID;      /* indicate the signal id, map to GNSS_SGN_ID_VALUE_* */
+    gnss_ha_ccp_per_sv_list_struct  ccpPerSVlist;
+} gnss_ha_ccp_per_signal_element_struct;
+
+
+typedef struct
+{
+    kal_uint8                              numCCPPerSigElement;
+    gnss_ha_ccp_per_signal_element_struct  ccpPerSigElement[GNSS_HA_MAX_CCP_PER_SIG_ELEMENT];
+} gnss_ha_ccp_per_signal_list_struct;
+
+
+typedef struct
+{
+   kal_uint16                          refStationID;      /* define the ID of the reference station to which the CCP assistance is provided */
+   gnss_ha_ccp_per_signal_list_struct  ccpPerSignalList;
+} gnss_ha_ccp_generic_element_struct;
+
+
+typedef struct
+{
+    kal_uint16                               transactionID;
+    MTK_GNSS_ID_ENUM                             gnssId;
+    kal_uint8                                numCCPGenericElement;
+    gnss_ha_ccp_generic_element_struct       ccpGenericElement[GNSS_HA_MAX_CCP_GENERIC_ELEMENT];
+} gnss_ha_generic_ccp_assist_struct;
+/* end of gnss_ha_generic_ccp_assist */
+
+
+/* begin of gnss_ha_req_ccp_generic_struct */
+typedef struct
+{
+    kal_uint8  ccpGnssSignalsReq;  /* specify the GNSS signal types for which the CCP assistance is requested by the target device, GNSS Signal(s), map to GNSS_SGN_ID_BITMAP_* */
+} gnss_ha_req_ccp_generic_struct;
+/* end of gnss_ha_req_ccp_generic_struct */
+
+typedef struct
+{
+    MTK_GNSS_ID_ENUM                          gnssId;
+    //kal_bool                        waIonoSurfaceReq;     /* TRUE if wide area ionosphere correction surface is requested for the SVs of this GNSS */
+    //gnss_ha_req_mechanics_struct    mechanicsReq;         /* request the SV mechanics information */
+    //gnss_ha_req_dcb_struct          dcbReq;               /* request the differential code biases to gain higher accuracy */
+    kal_bool                              degradModelReq;       /* TRUE if request the accuracy models for the SV orbit and clock models to get a better understanding of the accuracy of the computed position */
+    gnss_ha_req_ccp_generic_struct        ccpAssistGenericReq;  /* request for the CCP reference assistance data for high accuracy */
+    //gnss_ha_req_nav_model_struct    navigationModelReq;   /* TBD. request for the navigation models defined in LPPe */
+
+} gnss_ha_generic_assist_struct;
+
+typedef struct
+{
+    kal_uint16                            transactionID;
+
+    /* Common assistance data*/
+    kal_bool                              ionoModelReqValid;
+    gnss_ha_req_ionospheric_model_struct  ionoModelReq;        /* request for ionosphere models */
+
+    kal_bool                              tropoModelReqValid;
+    gnss_ha_req_troposphere_model_struct  tropoModelReq;       /* request troposphere models */
+
+    kal_bool                              altAssistReqValid;
+    gnss_ha_req_altitude_assist_struct    altAssistReq;        /* request altitude assistance for improved availability */
+
+    kal_bool                              solarRadReq;         /* TRUE if request the solar radiation intensity */
+
+    kal_bool                              ccpCtrlParamsReqValid;
+    gnss_ha_req_ccp_ctrl_params_struct    ccpCtrlParamsReq;    /* request for the control parameters of the CCP AD session.*/
+
+    /* Generic assistance data */
+    kal_uint8                             numGnssSupport;
+    gnss_ha_generic_assist_struct         genericAssistReq[16];
+} gnss_ha_assist_data_request_ind_struct;
+
+typedef struct
+{
+     kal_int32 type; /* refer to agps_md_huge_data_type */
+} gnss_ha_assist_ack_struct;
+
+typedef struct
+{
+    unsigned int u4_lppe_assis_data_bitmap;
+    gnss_ha_ionospheric_static_model_struct *ionospheric_static_model;
+    gnss_ha_ionospheric_periodic_model_struct *ionospheric_periodic_model;
+    gnss_ha_common_troposphere_model_struct *troposphere_model;
+    gnss_ha_common_altitude_assist_struct *altitude_assist;
+    gnss_ha_common_solar_radiation_struct *solar_radiation;
+    gnss_system_time_struct    *ccp_specific_common_para_ref_time;
+    gnss_ha_ccp_assist_common_ctrl_params_struct*  ctrlParams;
+    gnss_ha_generic_ccp_assist_struct *ccp_generic_assist_struct;
+    gnss_ha_generic_degradation_model_struct *generic_degradation_model;
+} gnss_lppe_database;
+typedef struct
+{
+    /*LPPE_enabled is for agent to management lppe assistant data, can be setted by driver*/
+    kal_uint8    LPPE_enabled;
+    /*ionospher must choose one, can't require both according to spec*/
+    kal_bool prefer_ionospheric_static_model;
+    /*common ccp must choose one, can't require both according to spec*/
+    kal_bool prefer_ccp_common_ctrl_params;
+}agent_lppe_config;
+
+
+
+/*for PMTK763*/
+typedef struct
+{
+    kal_uint8 adrRMSerror;
+    kal_bool lockIndicator;
+}gnss_ha_Measure_struct;
+
+
+/*for PMTK761*/
+
+typedef struct
+{
+    kal_uint8 cep; /* [0..255] */
+    kal_uint8 confidenceHorizontal; /* [0..99] */
+    kal_uint8 confidenceVertical; /* [0..99] */
+} gnss_ha_3Dposition_struct;
+typedef struct
+{
+    kal_uint16 eastComponent; /* [0..511] */
+    kal_uint16 northComponent; /* [0..511] */
+    kal_uint16 upComponent; /* [0..511] */
+    kal_uint8 cepV; /* [0..255] */
+    kal_uint8 uncertaintySemiMajor; /* [0..255] */
+    kal_uint8 uncertaintySemiMinor; /* [0..255] */
+    kal_uint8 offsetAngle; /* [0..179] */
+    kal_uint8 confidenceHorizontal; /* [0..99] */
+    kal_uint8 uncertaintyUpComponent; /* [0..255] */
+    kal_uint8 confidenceUp; /* [0..99] */
+} gnss_ha_3Dvelocity_struct;
+
+enum
+{
+    EPO_CUR_FILE_SMPHR = 0,
+    EPO_NEW_FILE_SMPHR,
+    QEPO_CUR_FILE_SMPHR = 2,
+    QEPO_NEW_FILE_SMPHR,
+    QEPO_BD_CUR_FILE_SMPHR = 4,
+    QEPO_BD_NEW_FILE_SMPHR,
+    MTKNAV_CUR_FILE_SMPHR = 6,
+    MTKNAV_NEW_FILE_SMPHR,
+    QEPO_GA_CUR_FILE_SMPHR = 8,
+    QEPO_GA_NEW_FILE_SMPHR,
+    MTK_SYS_SEMAPHORE_NUM_FOR_EPO
+};
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* MTK_GPS_TYPE_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/Android.mk b/src/connectivity/gps/mtk_mnld/mnl/libs/android/Android.mk
new file mode 100644
index 0000000..315db6a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/Android.mk
@@ -0,0 +1,54 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libhotstill
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_SRC_FILES_arm := libhotstill.a
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libsupl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_SRC_FILES_arm := libsupl.a
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libmnl
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libmnl.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libgeofence
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libgeofence.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libDR
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libDR.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MULTILIB := 32
+include $(BUILD_PREBUILT)
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/android/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/README b/src/connectivity/gps/mtk_mnld/mnl/libs/android/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libDR.so b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libDR.so
new file mode 100644
index 0000000..0016358
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libDR.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libgeofence.so b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libgeofence.so
new file mode 100644
index 0000000..8142e82
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libgeofence.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libhotstill.a
new file mode 100644
index 0000000..3dc8e2e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libmnl.so b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libmnl.so
new file mode 100644
index 0000000..9a6e294
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libmnl.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/android/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libsupl.a
new file mode 100644
index 0000000..dd0f5a3
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/android/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libhotstill.a
new file mode 100644
index 0000000..5f3264a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libmnl_gnss.so
new file mode 100644
index 0000000..8d0de94
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libsupl.a
new file mode 100644
index 0000000..0114fed
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/aarch64/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/NOTICE
new file mode 100644
index 0000000..38fb1bb
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/NOTICE
@@ -0,0 +1,34 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/README
new file mode 100644
index 0000000..7936bfb
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to system/xbin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
\ No newline at end of file
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libhotstill.a
new file mode 100644
index 0000000..4cdc5ae
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libmnl_gnss.so
new file mode 100644
index 0000000..2c3b5e1
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libsupl.a
new file mode 100644
index 0000000..6c333ec
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7a-vfp-neon/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libhotstill.a
new file mode 100644
index 0000000..a12db49
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libmnl_gnss.so
new file mode 100644
index 0000000..2c3b5e1
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libsupl.a
new file mode 100644
index 0000000..5c1e86c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/armv7vehf-neon-vfpv4/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libhotstill.a
new file mode 100644
index 0000000..a12db49
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libmnl_gnss.so
new file mode 100644
index 0000000..9c82cce
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libsupl.a
new file mode 100644
index 0000000..5c1e86c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-neon-vfpv4/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/NOTICE b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/NOTICE
new file mode 100644
index 0000000..7868067
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/NOTICE
@@ -0,0 +1,23 @@
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>.

+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>.

+

+Curl License

+Copyright (c) 1996 - 2003, Daniel Stenberg, <daniel@haxx.se>.

+

+All rights reserved.

+

+Permission to use, copy, modify, and distribute this software for any purposewith or without fee is hereby granted,

+provided that the above copyright notice and this permission notice appear in all copies.

+

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT

+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF

+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE

+SOFTWARE.

+

+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to

+promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/README b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/README
new file mode 100644
index 0000000..e18aacc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/README
@@ -0,0 +1,15 @@
+WHAT IT DOES?
+=============
+libhotstill.a,libsupl.a and libmnl.so is the implementation that mediatek navigating technology to work well as three libraries.
+
+HOW IT WAS BUILT?
+==================
+As library files, these are built by arm gcc tool chain.
+
+HOW TO USE IT?
+==============
+The three libraries is linked to vendor/bin/mnld daemon,their API will be called when GPS running.
+
+Source
+==============
+All the source code of these libraries were written by MediaTek co..
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libhotstill.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libhotstill.a
new file mode 100644
index 0000000..a12db49
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libhotstill.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libmnl_gnss.so b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libmnl_gnss.so
new file mode 100644
index 0000000..9c82cce
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libmnl_gnss.so
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libsupl.a b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libsupl.a
new file mode 100644
index 0000000..5c1e86c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/libs/linux/cortexa7hf-vfp-vfpv4-neon/libsupl.a
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnl/src/pseudo_mnl.c b/src/connectivity/gps/mtk_mnld/mnl/src/pseudo_mnl.c
new file mode 100644
index 0000000..a5fd43a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl/src/pseudo_mnl.c
@@ -0,0 +1,301 @@
+#include <errno.h>   /* Error number definitions */
+#include <fcntl.h>
+#include <stdio.h>   /* Standard input/output definitions */
+#include <string.h>  /* String function definitions */
+#include <unistd.h>  /* UNIX standard function definitions */
+#include <sys/ioctl.h>
+#include <time.h>
+#if defined(__ANDROID_OS__)
+#include <private/android_filesystem_config.h>
+#endif
+
+#include "mtk_gps_sys_fp.h"
+#include "nmea_parser.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_agps.h"
+#include "mnld_utile.h"
+#include "mtk_auto_log.h"
+#include "mpe.h"
+
+// for read NVRAM
+#if MTK_GPS_NVRAM
+#include "libnvram.h"
+#include "CFG_GPS_File.h"
+#include "CFG_GPS_Default.h"
+#include "CFG_file_lid.h"
+#include "Custom_NvRam_LID.h"
+#endif
+#include "SUPL_encryption.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "pseudo"
+#endif
+
+#define MAX_RETRY_COUNT       20
+#define PMTK_FS_REQ_MEAS                736
+#define PMTK_FRAME_TIME_ACK             737
+#define PMTK_FS_SLEEPMODE               738
+#define MTK_GPS_HIDE_PRINT_MAX 17
+//#define MTK_GPS_LOG_FULL_PRINT
+
+#if defined(LIB_MQUEU)
+// message queue file descriptor
+static mqd_t mnl_agps_mq_fd = -1;
+struct mq_attr mnl_agps_mq_attr;
+#endif
+
+MTK_GPS_BOOL enable_dbg_log = MTK_GPS_TRUE;
+
+// for read NVRAM
+#if MTK_GPS_NVRAM
+extern ap_nvram_gps_config_struct stGPSReadback;
+extern int gps_nvram_valid;
+#if ANDROID_MNLD_PROP_SUPPORT
+char nvram_init_val[PROPERTY_VALUE_MAX];
+#else
+char nvram_init_val[100];
+#endif
+#endif
+int mtk_gps_sys_init() {
+#if MTK_GPS_NVRAM
+    F_ID gps_nvram_fd;
+    int file_lid = AP_CFG_CUSTOM_FILE_GPS_LID;
+#endif
+    /* create message queue */
+#if defined(LIB_MQUEUE)
+    mnl_agps_mq_attr.mq_maxmsg = 72;
+    mnl_agps_mq_attr.mq_msgsize = sizeof(MTK_GPS_AGPS_AGENT_MSG);
+    mnl_agps_mq_attr.mq_flags   = 0;
+    mnl_agps_mq_fd = mq_open(MNL_AGPS_MQ_NAME, O_CREAT|O_RDWR|O_EXCL, PMODE, &mnl_agps_mq_attr);
+
+    if (mnl_agps_mq_fd == -1) {
+        LOGD("Fail to create mnl_agps_msg_queue, errno=%s\n", strerror(errno));
+        if (errno == EEXIST) {
+            LOGD("mnl_agps_msg_queue already exists, unlink it now ...\n");
+            mq_unlink(MNL_AGPS_MQ_NAME);
+        }
+        return MTK_GPS_ERROR;
+    }
+#else
+#endif
+#if MTK_GPS_NVRAM
+    //LOGD("Start to read nvram");
+    while (read_nvram_ready_retry < MAX_RETRY_COUNT) {
+        read_nvram_ready_retry++;
+        #if ANDROID_MNLD_PROP_SUPPORT
+        property_get("service.nvram_init", nvram_init_val, NULL);
+        if (strcmp(nvram_init_val, "Ready") == 0 || strcmp(nvram_init_val, "Pre_Ready") == 0) {
+            LOGD("nvram_init_val Ready");
+            break;
+        } else {
+            LOGD("nvram_init_val not Ready,sleep 500ms");
+            usleep(500*1000);
+        }
+        #endif
+    }
+    LOGD("Get nvram restore ready retry cc=%d\n", read_nvram_ready_retry);
+    if (read_nvram_ready_retry >= MAX_RETRY_COUNT) {
+        LOGD("Get nvram restore ready faild, return\n");
+        return MTK_GPS_ERROR;
+    }
+
+    memset(&stGPSReadback, 0, sizeof(stGPSReadback));
+
+    gps_nvram_fd = NVM_GetFileDesc(file_lid, &rec_size, &rec_num, ISREAD);
+    if (gps_nvram_fd.iFileDesc >= 0) {
+        read(gps_nvram_fd.iFileDesc, &stGPSReadback , rec_size*rec_num);
+        NVM_CloseFileDesc(gps_nvram_fd);
+
+        if (strlen(stGPSReadback.dsp_dev) != 0) {
+            gps_nvram_valid = 1;
+            // strncpy(mnl_config.dev_dsp, stGPSReadback.dsp_dev, sizeof(mnl_config.dev_dsp));
+
+            LOGD("GPS NVRam :(%d * %d), dsp_dev(/dev/stpgps) : %s\n", rec_size, rec_num, stGPSReadback.dsp_dev);
+            LOGD("gps_tcxo_hz : %d,gps_tcxo_ppb : %d,gps_tcxo_type : %d, gps_lna_mode : %d\n",
+                stGPSReadback.gps_tcxo_hz,
+                stGPSReadback.gps_tcxo_ppb,
+                stGPSReadback.gps_tcxo_type,
+                stGPSReadback.gps_lna_mode);
+        } else {
+            LOGD("GPS NVRam mnl_config.dev_dsp == NULL \n");
+        }
+    }
+    else {
+           LOGD("GPS NVRam gps_nvram_fd == NULL \n");
+    }
+#endif
+    return MTK_GPS_SUCCESS;
+}
+int mtk_gps_sys_uninit() {
+#if defined(LIB_MQUEUE)
+    mq_close(mnl_mq_fd);         /* Close message queue in parent */
+    mq_unlink(MNL_MQ_NAME);      /* Unlink message queue */
+    mq_close(mnl_agps_mq_fd);    /* Close message queue in parent */
+    mq_unlink(MNL_AGPS_MQ_NAME);  /* Unlink message queue */
+#else
+#endif
+    return MTK_GPS_SUCCESS;
+}
+
+int mtk_gps_sys_strncmp(const char * str1,const char * str2){
+    return strncmp(str1,str2,strlen(str2));
+}
+
+//Log filter for NMEA sentence
+MTK_GPS_BOOL mtk_gps_sys_nmea_log_filter(const char * buffer) {
+    MTK_GPS_BOOL ret = MTK_GPS_FALSE;
+
+    if('$' == buffer[0]
+       && ((mtk_gps_sys_strncmp(&buffer[3],"GGA")==0) || (mtk_gps_sys_strncmp(&buffer[3],"RMC")==0))){// NMEA sentence
+        ret = MTK_GPS_TRUE;
+    }else{
+        ret = MTK_GPS_FALSE;
+    }
+
+    return ret;
+}
+//Log filter for Offload printing
+MTK_GPS_BOOL mtk_gps_sys_ofl_log_filter(const char * buffer, UINT32 length) {
+    UNUSED(length);
+    MTK_GPS_BOOL ret = MTK_GPS_FALSE;
+
+    if(mtk_gps_sys_strncmp(buffer,"gfns_tx,dump") == 0){
+        ret = MTK_GPS_TRUE;
+    }else if(mtk_gps_sys_strncmp(buffer,"DUMP,GFNS") == 0){
+        ret = MTK_GPS_TRUE;
+    }else if(mtk_gps_sys_strncmp(buffer,"[FLP]") == 0){// FLP
+        ret = MTK_GPS_TRUE;
+    }else{
+        ret = MTK_GPS_FALSE;
+        //LOGD("len:%d, %s", length, buffer);
+    }
+
+    return ret;
+}
+
+#ifdef CONFIG_GPS_MT3303
+INT32 mtk_gps_sys_nmea_output_to_app(const char * buffer, UINT32 length) {
+    if (enable_dbg_log == MTK_GPS_TRUE) {  // Need to use prop to control debug on/of
+        LOGD("len:%d, %s", length, buffer);
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length) {
+    LOGD("received %d bytes", length);
+#ifdef MTK_ADR_SUPPORT
+    if (mnl2adr_send_nmea_data(buffer, length) == -1) {
+        mtk_mnl_nmea_parser_process(buffer, length);  //Send to nmea parser and HAL directly, if sent to adr fail
+    }else {
+        mtk_mnl_nmea_parser_process(buffer, length);
+    }
+#else
+    mtk_mnl_nmea_parser_process(buffer, length);
+#endif
+    return MTK_GPS_SUCCESS;
+}
+#else
+INT32 mtk_gps_sys_nmea_output_to_app(const char * buffer, UINT32 length) {
+    if (enable_dbg_log == MTK_GPS_TRUE) {  // Need to use prop to control debug on/of
+#ifdef MTK_GPS_LOG_FULL_PRINT
+        LOGD("len:%d, %s", length, buffer);
+#else
+        char buf_print[MTK_GPS_HIDE_PRINT_MAX+1] = {0};
+        if (mtk_gps_sys_nmea_log_filter(buffer) == MTK_GPS_TRUE) {
+            MNLD_STRNCPY(buf_print, buffer, MTK_GPS_HIDE_PRINT_MAX);
+            buf_print[MTK_GPS_HIDE_PRINT_MAX] = '\0';
+            LOGD("len:%d, [NMEA]%s...", length, buf_print);
+        } else if ((mtk_gps_log_is_hide() == 1) &&
+                (mtk_gps_sys_ofl_log_filter(buffer, length) == MTK_GPS_TRUE)) {
+            // Forbit to print location log
+            MNLD_STRNCPY(buf_print, buffer, MTK_GPS_HIDE_PRINT_MAX);
+            buf_print[MTK_GPS_HIDE_PRINT_MAX] = '\0';
+            LOGD("len:%d, [OFL]%s...", length, buf_print);
+        } else {
+            // No limitation, print directly
+            LOGD("len:%d, %s", length, buffer);
+        }
+#endif
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_nmea_output_to_mnld(const char * buffer, UINT32 length) {
+    LOGD("received %d bytes", length);
+#ifdef MTK_ADR_SUPPORT
+    if (mnl2adr_send_nmea_data(buffer, length) == -1) {
+        mtk_mnl_nmea_parser_process(buffer, length);  //Send to nmea parser and HAL directly, if sent to adr fail
+    }else {
+        mtk_mnl_nmea_parser_process(buffer, length);
+    }
+#else
+    mtk_mnl_nmea_parser_process(buffer, length);
+#endif
+    return MTK_GPS_SUCCESS;
+}
+#endif
+static unsigned char calc_nmea_checksum1(const char* sentence) {
+    unsigned char checksum = 0;
+
+    while (*sentence) {
+        checksum ^= (unsigned char)*sentence++;
+    }
+    return  checksum;
+}
+
+INT32 mtk_gps_sys_frame_sync_meas_req(MTK_GPS_FS_WORK_MODE mode) {
+    char szBuf_cipher[64];
+    char sztmp[64];
+    char outbuf[64];
+
+    memset(outbuf, 0, sizeof(outbuf));
+    memset(sztmp, 0, sizeof(sztmp));
+    memset(szBuf_cipher, 0, sizeof(szBuf_cipher));
+    sprintf(sztmp, "PMTK%d,1,%d", PMTK_FS_REQ_MEAS, mode);
+    sprintf(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+    // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+    memcpy(szBuf_cipher, outbuf, strlen(outbuf));
+    mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_SUPL_PMTK, strlen(szBuf_cipher), szBuf_cipher);
+
+    return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_frame_sync_enable_sleep_mode(unsigned char mode) {
+    char szBuf_cipher[64];
+    char sztmp[64];
+    char outbuf[64];
+
+    memset(outbuf, 0, sizeof(outbuf));
+    memset(sztmp, 0, sizeof(sztmp));
+    memset(szBuf_cipher, 0, sizeof(szBuf_cipher));
+    sprintf(sztmp, "PMTK%d,%d", PMTK_FS_SLEEPMODE, mode);
+    sprintf(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+    // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+    memcpy(szBuf_cipher, outbuf, strlen(outbuf));
+    mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_SUPL_PMTK, strlen(szBuf_cipher), szBuf_cipher);
+
+    return MTK_GPS_SUCCESS;
+}
+
+INT32 mtk_gps_sys_frame_sync_meas_req_by_network(void) {
+    char szBuf_cipher[64];
+    char sztmp[64];
+    char outbuf[64];
+
+    memset(outbuf, 0, sizeof(outbuf));
+    memset(sztmp, 0, sizeof(sztmp));
+    memset(szBuf_cipher, 0, sizeof(szBuf_cipher));
+    sprintf(sztmp, "PMTK%d,0,0", PMTK_FS_REQ_MEAS);
+    sprintf(outbuf, "$%s*%02X\r\n", sztmp, calc_nmea_checksum1(sztmp));
+
+    // SUPL_encrypt((unsigned char *)outbuf, (unsigned char *)szBuf_cipher, strlen(outbuf));
+    memcpy(szBuf_cipher, outbuf, strlen(outbuf));
+    mtk_gps_sys_agps_disaptcher_callback(MTK_AGPS_CB_SUPL_PMTK, strlen(szBuf_cipher), szBuf_cipher);
+
+    return MTK_GPS_SUCCESS;
+}
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h
new file mode 100644
index 0000000..3fb31c9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/agps2mnl_interface.h
@@ -0,0 +1,93 @@
+
+#ifndef __AGPS2GPS_INTERFACE_H__
+#define __AGPS2GPS_INTERFACE_H__
+
+#include "mnl_agps_interface.h"
+
+typedef struct {
+    void (*mnl_reboot)();
+
+    void (*open_gps_done)();
+    void (*close_gps_done)();
+    void (*reset_gps_done)();
+
+    void (*gps_init)();
+    void (*gps_cleanup)();
+    void (*set_server)(int type, const char* hostname, int port);
+    void (*delete_aiding_data)(int flags);
+    void (*gps_open)(int assist_req);
+    void (*gps_close)();
+    void (*data_conn_open)(const char* apn);
+    void (*data_conn_failed)();
+    void (*data_conn_closed)();
+
+    void (*ni_message)(const char* msg, int len);
+    void (*ni_respond)(int session_id, int user_response);
+
+    void (*set_ref_loc)(int type, int mcc, int mnc, int lac, int cid);
+    void (*set_set_id)(int type, const char* setid);
+
+    void (*update_network_state)(int connected, int type, int roaming, const char* extra_info);
+    void (*update_network_availability)(int avaiable, const char* apn);
+
+    void (*rcv_pmtk)(const char* pmtk);
+    void (*raw_dbg)(int enabled);
+    void (*reaiding_req)();
+    void (*data_conn_open_ip_type)(const char* apn, int ip_type);
+    void (*install_certificates)(int index, int total, const char* data, int len);
+    void (*revoke_certificates)(const char* data, int len);
+    void (*location_sync)(double lat, double lng, int acc, bool alt_valid, float alt, bool source_valid, bool source_gnss, bool source_nlp, bool source_sensor);
+    void (*agps_settings_ack) (mnl_agps_gnss_settings* settings);
+    void (*vzw_debug_screen_enable) (int enabled);
+    void (*set_server_extension) (int type, const char* hostname, int port, int ssl, int ssl_version, int ssl_type);
+    void (*update_configuration) (const char* config_data, int length);
+    void (*supl_host_ip) (const char* ip);
+    void (*tc10_lpp_support) (int support_bitmask);
+    void (*lppe_assist_data_req) (const char* data, int len);           // refer to gnss_ha_assist_data_req_struct
+    void (*lppe_assist_data_provide_ack) (const char* data, int len);   // refer to gnss_ha_assist_ack_struct
+} mnl2agps_interface;
+
+int agps2mnl_agps_reboot();
+
+int agps2mnl_agps_open_gps_req(int show_gps_icon);
+int agps2mnl_agps_close_gps_req();
+int agps2mnl_agps_reset_gps_req(int flags);
+
+int agps2mnl_agps_session_done();
+
+int agps2mnl_ni_notify(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name);
+int agps2mnl_ni_notify2(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name,
+    mnl_agps_ni_encoding_type requestor_id_encoding, mnl_agps_ni_encoding_type client_name_encoding);
+int agps2mnl_data_conn_req(int ipaddr, int is_emergency);
+int agps2mnl_data_conn_req2(struct sockaddr_storage* addr, int is_emergency);
+int agps2mnl_data_conn_release();
+// flags refer to REQUEST_SETID_IMSI and REQUEST_SETID_MSISDN
+int agps2mnl_set_id_req(int flags);
+// flags refer to REQUEST_REFLOC_CELLID and REQUEST_REFLOC_MAC
+int agps2mnl_ref_loc_req(int flags);
+
+int agps2mnl_pmtk(const char* pmtk);
+int agps2mnl_gpevt(gpevt_type type);
+
+int agps2mnl_agps_location(mnl_agps_agps_location* location);
+int agps2mnl_cell_location(mnl_agps_agps_location* location);
+
+int agps2mnl_agps_settings_sync(mnl_agps_agps_settings* settings);
+int agps2mnl_vzw_debug_screen_output(const char* str);
+int agps2mnl_supl_dns_req(const char* fqdn);
+int agps2mnl_lppe_assist_data_provide_common_iono(const char* data, int len);       // refer to gnss_ha_common_ionospheric_model_struct
+int agps2mnl_lppe_assist_data_provide_common_trop(const char* data, int len);       // refer to gnss_ha_common_troposphere_model_struct
+int agps2mnl_lppe_assist_data_provide_common_alt(const char* data, int len);        // refer to gnss_ha_common_altitude_assist_struct
+int agps2mnl_lppe_assist_data_provide_common_solar(const char* data, int len);      // refer to gnss_ha_common_solar_radiation_struct
+int agps2mnl_lppe_assist_data_provide_common_ccp(const char* data, int len);        // refer to gnss_ha_common_ccp_assist_struct
+int agps2mnl_lppe_assist_data_provide_generic_ccp(const char* data, int len);       // refer to gnss_ha_generic_ccp_assist_struct
+int agps2mnl_lppe_assist_data_provide_generic_dm(const char* data, int len);        // refer to gnss_ha_generic_degradation_model_struct
+void mnl2agps_hdlr(int fd, mnl2agps_interface* agps_interface);
+
+
+int create_mnl2agps_fd();
+// debug purpose
+int create_mnl2agps_fd2(const char* agps2mnl_path);
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h
new file mode 100644
index 0000000..ae5e3ab
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl2agps_interface.h
@@ -0,0 +1,90 @@
+
+#ifndef __GPS2AGPS_INTERFACE_H__
+#define __GPS2AGPS_INTERFACE_H__
+
+#include <sys/socket.h>
+#include "mnl_agps_interface.h"
+
+typedef struct {
+    void (*agps_reboot)();
+
+    void (*agps_open_gps_req)(int show_gps_icon);
+    void (*agps_close_gps_req)();
+    void (*agps_reset_gps_req)(int flags);
+
+    void (*agps_session_done)();
+
+    void (*ni_notify)(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name);
+    void (*data_conn_req)(int ipaddr, int is_emergency);
+    void (*data_conn_release)();
+
+    void (*set_id_req)(int flags);
+    void (*ref_loc_req)(int flags);
+
+    void (*rcv_pmtk)(const char* pmtk);
+    void (*gpevt)(gpevt_type type);
+
+    void (*agps_location)(mnl_agps_agps_location* location);
+    void (*ni_notify2)(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name,
+        mnl_agps_ni_encoding_type requestor_id_encoding, mnl_agps_ni_encoding_type client_name_encoding);
+    void (*data_conn_req2)(struct sockaddr_storage* addr, int is_emergency);
+    void (*agps_settings_sync)(mnl_agps_agps_settings* settings);
+    void (*vzw_debug_screen_output)(const char* str);
+    void (*lppe_assist_common_iono) (const char* data, int len);   // refer to gnss_ha_common_ionospheric_model_struct
+    void (*lppe_assist_common_trop) (const char* data, int len);   // refer to gnss_ha_common_troposphere_model_struct
+    void (*lppe_assist_common_alt) (const char* data, int len);    // refer to gnss_ha_common_altitude_assist_struct
+    void (*lppe_assist_common_solar) (const char* data, int len);  // refer to gnss_ha_common_solar_radiation_struct
+    void (*lppe_assist_common_ccp) (const char* data, int len);    // refer to gnss_ha_common_ccp_assist_struct
+    void (*lppe_assist_generic_ccp) (const char* data, int len);   // refer to gnss_ha_generic_ccp_assist_struct
+    void (*lppe_assist_generic_dm) (const char* data, int len);    // refer to gnss_ha_generic_degradation_model_struct
+} agps2mnl_interface;
+
+// MNL -> AGPS
+int mnl2agps_mnl_reboot();
+
+int mnl2agps_open_gps_done();
+int mnl2agps_close_gps_done();
+int mnl2agps_reset_gps_done();
+
+int mnl2agps_gps_init();
+int mnl2agps_gps_cleanup();
+// type:AGpsType
+int mnl2agps_set_server(int type, const char* hostname, int port);
+// flags:GpsAidingData
+int mnl2agps_delete_aiding_data(int flags);
+int mnl2agps_gps_open(int assist_req);
+int mnl2agps_gps_close();
+int mnl2agps_data_conn_open(const char* apn);
+int mnl2agps_data_conn_open_ip_type(const char* apn, int ip_type);
+int mnl2agps_data_conn_failed();
+int mnl2agps_data_conn_closed();
+int mnl2agps_ni_message(const char* msg, int len);
+int mnl2agps_ni_respond(int session_id, int user_response);
+int mnl2agps_set_ref_loc(int type, int mcc, int mnc, int lac, int cid);
+int mnl2agps_set_set_id(int type, const char* setid);
+int mnl2agps_update_network_state(int connected, int type, int roaming, const char* extra_info);
+int mnl2agps_update_network_availability(int avaiable, const char* apn);
+int mnl2agps_install_certificates(int index, int total, const char* data, int len);
+int mnl2agps_revoke_certificates(const char* data, int len);
+
+int mnl2agps_pmtk(const char* pmtk);
+int mnl2agps_raw_dbg(int enabled);
+int mnl2agps_reaiding_req();
+int mnl2agps_location_sync(double lat, double lng, int acc, bool alt_valid, float alt, bool source_valid, bool source_gnss, bool source_nlp, bool source_sensor);
+int mnl2agps_agps_settings_ack(mnl_agps_gnss_settings* settings);
+int mnl2agps_vzw_debug_screen_enable(int enabled);
+int mnl2agps_set_server_extension(int type, const char* hostname, int port, int ssl, int ssl_version, int ssl_type);
+int mnl2agps_update_configuration(const char* config_data, int length);
+int mnl2agps_supl_host_ip(const char* ip);
+int mnl2agps_tc10_lpp_support(int support_bitmask);
+int mnl2agps_lppe_assist_data_req(const char* data, int len);           // refer to gnss_ha_assist_data_req_struct
+int mnl2agps_lppe_assist_data_provide_ack(const char* data, int len);   // refer to gnss_ha_assist_ack_struct
+
+void agps2mnl_hdlr(int fd, agps2mnl_interface* mnl_interface);
+
+
+int create_agps2mnl_fd();
+int mnl2agps_set_position_mode(int pos_mode);
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h
new file mode 100644
index 0000000..f300c4a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/inc/mnl_agps_interface.h
@@ -0,0 +1,204 @@
+#ifndef __GPS_AGPS_INTERFACE_H__
+#define __GPS_AGPS_INTERFACE_H__
+
+#include <stdbool.h>
+#include "mtk_auto_log.h"
+
+#define AGPS_TO_MNL "/data/agps_supl/agps_to_mnl"
+#define MNL_TO_AGPS "/data/agps_supl/mnl_to_agps"
+
+#define MNL_AGPS_MAX_BUFF_SIZE (64 * 1024)
+
+#define MNL_AGPS_INTERFACE_VERSION 1
+
+#define REQUEST_SETID_IMSI     (1<<0L)
+#define REQUEST_SETID_MSISDN   (1<<1L)
+
+#define REQUEST_REFLOC_CELLID  (1<<0L)
+#define REQUEST_REFLOC_MAC     (1<<1L)   // not ready
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+typedef enum {
+    MNL_AGPS_NI_TYPE_VOICE = 1,
+    MNL_AGPS_NI_TYPE_UMTS_SUPL,
+    MNL_AGPS_NI_TYPE_UMTS_CTRL_PLANE,
+    MNL_AGPS_NI_TYPE_EMERGENCY_SUPL,
+} mnl_agps_ni_type;
+typedef enum {
+    MNL_AGPS_NOTIFY_TYPE_NONE = 0,
+    MNL_AGPS_NOTIFY_TYPE_NOTIFY_ONLY,
+    MNL_AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER,
+    MNL_AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER,
+    MNL_AGPS_NOTIFY_TYPE_PRIVACY,
+} mnl_agps_notify_type;
+
+typedef enum {
+    MNL_AGPS_NI_ENCODING_TYPE_GSM7 = 1,
+    MNL_AGPS_NI_ENCODING_TYPE_UTF8,
+    MNL_AGPS_NI_ENCODING_TYPE_UCS2,
+} mnl_agps_ni_encoding_type;
+
+typedef enum {
+  GPEVT_TYPE_UNKNOWN = 0,                      //  0
+  GPEVT_SUPL_SLP_CONNECT_BEGIN,                //  1
+  GPEVT_SUPL_SLP_CONNECTED,                    //  2
+  GPEVT_SUPL_SSL_CONNECT_BEGIN,                //  3
+  GPEVT_SUPL_SSL_CONNECTED,                    //  4
+  GPEVT_SUPL_ASSIST_DATA_RECEIVED,             //  5
+  GPEVT_SUPL_ASSIST_DATA_VALID,                //  6
+  GPEVT_SUPL_FIRST_POS_FIX,                    //  7
+  GPEVT_SUPL_MEAS_TIME_OUT,                    //  8
+  GPEVT_SUPL_MEAS_RESPONSE_SENT,               //  9
+  GPEVT_SUPL_SSL_CLOSED,                       // 10
+  GPEVT_SUPL_SLP_DISCONNECTED,                 // 11
+
+  GPEVT_CP_MOLR_SENT,                          // 12
+  GPEVT_CP_MTLR_RECEIVED,                      // 13
+  GPEVT_CP_ASSIST_DATA_RECEIVED,               // 14
+  GPEVT_CP_ASSIST_DATA_VALID,                  // 15
+  GPEVT_CP_FIRST_POS_FIX,                      // 16
+  GPEVT_CP_MEAS_TIME_OUT,                      // 17
+  GPEVT_CP_MEAS_RESPONSE_SENT,                 // 18
+
+  GPEVT_GNSS_HW_START,                         // 19
+  GPEVT_GNSS_HW_STOP,                          // 20
+  GPEVT_GNSS_RESET_STORED_SATELLITE_DATA,      // 21
+
+  GPEVT_EPO_SERVER_CONNECT_BEGIN,              // 22
+  GPEVT_EPO_SERVER_CONNECTED,                  // 23
+  GPEVT_EPO_DATA_RECEIVED,                     // 24
+  GPEVT_EPO_SERVER_DISCONNECTED,               // 25
+  GPEVT_EPO_DATA_VALID,                        // 26
+
+  GPEVT_HOT_STILL_DATA_VALID,                  // 27
+
+  GPEVT_TYPE_MAX                               // 28
+}gpevt_type;
+
+typedef enum {
+    //---------------------------------------
+    // MNL -> AGPS
+    MNL_AGPS_TYPE_MNL_REBOOT  = 100,
+
+    MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE = 110,
+    MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE,
+    MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE,
+
+    MNL_AGPS_TYPE_GPS_INIT = 120,
+    MNL_AGPS_TYPE_GPS_CLEANUP,
+    MNL_AGPS_TYPE_DELETE_AIDING_DATA,
+    MNL_AGPS_TYPE_GPS_OPEN,
+    MNL_AGPS_TYPE_GPS_CLOSE,
+    MNL_AGPS_TYPE_DATA_CONN_OPEN,
+    MNL_AGPS_TYPE_DATA_CONN_FAILED,
+    MNL_AGPS_TYPE_DATA_CONN_CLOSED,
+    MNL_AGPS_TYPE_NI_MESSAGE,
+    MNL_AGPS_TYPE_NI_RESPOND,
+    MNL_AGPS_TYPE_SET_REF_LOC,
+    MNL_AGPS_TYPE_SET_SET_ID,
+    MNL_AGPS_TYPE_SET_SERVER,
+    MNL_AGPS_TYPE_UPDATE_NETWORK_STATE,
+    MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY,
+    MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE,
+    MNL_AGPS_TYPE_INSTALL_CERTIFICATES,
+    MNL_AGPS_TYPE_REVOKE_CERTIFICATES,
+
+    MNL_AGPS_TYPE_MNL2AGPS_PMTK = 150,
+    MNL_AGPS_TYPE_RAW_DBG,
+    MNL_AGPS_TYPE_REAIDING,
+    MNL_AGPS_TYPE_LOCATION_SYNC,
+    MNL_AGPS_TYPE_SETTINGS_ACK,
+    MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_ENABLE,
+    MNL_AGPS_TYPE_SET_SERVER_EXTENSION,
+    MNL_AGPS_TYPE_UPDATE_CONFIGURATION,
+    MNL_AGPS_TYPE_SUPL_HOST_IP,
+    MNL_AGPS_TYPE_TC10_LPP_SUPPORT,
+    MNL_AGPS_TYPE_LPPE_ASSIST_DATA_REQ,             // refer to gnss_ha_assist_data_req_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_DATA_PROVIDE_ACK,     // refer to gnss_ha_assist_ack_struct
+    MNL_AGPS_TYPE_SET_POSITION_MODE,
+
+    // ---------------------------------------
+    // AGPS -> MNL
+    MNL_AGPS_TYPE_AGPS_REBOOT    = 200,
+
+    MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ = 210,
+    MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ,
+    MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ,
+
+    MNL_AGPS_TYPE_AGPS_SESSION_DONE = 220,
+
+    MNL_AGPS_TYPE_NI_NOTIFY = 230,
+    MNL_AGPS_TYPE_DATA_CONN_REQ,
+    MNL_AGPS_TYPE_DATA_CONN_RELEASE,
+    MNL_AGPS_TYPE_SET_ID_REQ,
+    MNL_AGPS_TYPE_REF_LOC_REQ,
+    MNL_AGPS_TYPE_AGPS_LOC,
+    MNL_AGPS_TYPE_NI_NOTIFY_2,
+    MNL_AGPS_TYPE_DATA_CONN_REQ2,
+    MNL_AGPS_TYPE_SUPL_DNS_REQ,
+
+    MNL_AGPS_TYPE_AGPS2MNL_PMTK = 250,
+    MNL_AGPS_TYPE_GPEVT,
+    MNL_AGPS_TYPE_SETTINGS_SYNC,
+    MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_OUTPUT,
+    MNL_AGPS_TYPE_CELL_LOCATION,
+    MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_IONO, // refer to gnss_ha_common_ionospheric_model_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_TROP, // refer to gnss_ha_common_troposphere_model_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_ALT,  // refer to gnss_ha_common_altitude_assist_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_SOLAR,// refer to gnss_ha_common_solar_radiation_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_CCP,  // refer to gnss_ha_common_ccp_assist_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_CCP, // refer to gnss_ha_generic_ccp_assist_struct
+    MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_DM,  // refer to gnss_ha_generic_degradation_model_struct
+} mnl_agps_type;
+typedef enum{
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_IONO       = 610,  //MD -> AP  gnss_ha_common_ionospheric_model_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_TROP       = 611,  //MD -> AP  gnss_ha_common_troposphere_model_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_ALT        = 612,  //MD -> AP  gnss_ha_common_altitude_assist_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_SOLAR      = 613,  //MD -> AP  gnss_ha_common_solar_radiation_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_CCP        = 614,  //MD -> AP  gnss_ha_common_ccp_assist_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_CCP       = 630,  //MD -> AP  gnss_ha_generic_ccp_assist_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_DM        = 631,  //MD -> AP  gnss_ha_generic_degradation_model_struct
+    AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_ACK               = 650,  //AP -> MD  lpp_lppe_ha_gn
+}lppe_ack_type;
+typedef struct {
+    double          latitude;           // Represents latitude in degrees
+    double          longitude;          // Represents longitude in degrees
+    char            altitude_used;      // 0=disabled 1=enabled
+    double          altitude;           // Represents altitude in meters above the WGS 84 reference
+    char            speed_used;         // 0=disabled 1=enabled
+    float           speed;              // Represents speed in meters per second
+    char            bearing_used;       // 0=disabled 1=enabled
+    float           bearing;            // Represents heading in degrees
+    char            accuracy_used;      // 0=disabled 1=enabled
+    float           accuracy;           // Represents expected accuracy in meters
+    char            timestamp_used;     // 0=disabled 1=enabled
+    long long       timestamp;          // Milliseconds since January 1, 1970
+} mnl_agps_agps_location;
+
+typedef struct {
+    char            sib8_16_enable;
+    char            gps_satellite_enable;
+    char            glonass_satellite_enable;
+    char            beidou_satellite_enable;
+    char            galileo_satellite_enable;
+    char            a_glonass_satellite_enable;
+    char            a_gps_satellite_enable;
+    char            a_beidou_satellite_enable;
+    char            a_galileo_satellite_enable;
+    char            lppe_enable;
+} mnl_agps_agps_settings;
+
+typedef struct {
+    char            gps_satellite_support;
+    char            glonass_satellite_support;
+    char            beidou_satellite_support;
+    char            galileo_satellite_support;
+} mnl_agps_gnss_settings;
+const char* get_mnl_agps_type_str(mnl_agps_type input);
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c
new file mode 100644
index 0000000..0d3a949
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/agps2mnl_interface.c
@@ -0,0 +1,643 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h>  // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h>  // inet_addr
+#include <sys/un.h>  // struct sockaddr_un
+
+#include "mtk_lbs_utility.h"
+#include "agps2mnl_interface.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#if defined(__ANDROID_OS__)
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "agps"
+#endif
+
+#endif
+
+#define HIDE_LOG_PROP "ro.mtk_log_hide_gps"
+// -1 means failure
+/*static int safe_recvfrom(int sockfd, char* buf, int len) {
+    int ret = 0;
+    int retry = 10;
+
+    while ((ret = recvfrom(sockfd, buf, len, 0,
+         NULL, NULL)) == -1) {
+        LOGW("ret=%d len=%d\n", ret, len);
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto reason=[%s]\n", strerror(errno));
+        break;
+    }
+    return ret;
+}*/
+
+// -1 means failure
+static int set_socket_blocking(int fd, int blocking) {
+    if (fd < 0) {
+        LOGE("set_socket_blocking  invalid fd=%d\n", fd);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags < 0) {
+        LOGE("set_socket_blocking  invalid flags=%d\n", flags);
+        return -1;
+    }
+
+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+static int agps_safe_sendto(int sockfd, const char* dest, const char* buf, int size) {
+    int len = 0;
+    struct sockaddr_un soc_addr;
+    socklen_t addr_len;
+    int retry = 10;
+
+    MNLD_STRNCPY(soc_addr.sun_path, dest,sizeof(soc_addr.sun_path));
+    soc_addr.sun_family = AF_UNIX;
+    addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+    while ((len = sendto(sockfd, buf, size, 0,
+        (const struct sockaddr *)&soc_addr, (socklen_t)addr_len)) == -1) {
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto dest=[%s] len=%d reason=[%s]\n",
+            dest, size, strerror(errno));
+        break;
+    }
+    return len;
+}
+
+static char g_agps2mnl_path[128] = AGPS_TO_MNL;
+
+// -1 means failure
+static int send2mnl(const char* buff, int len) {
+    int ret = 0;
+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+
+    if (agps_safe_sendto(sockfd, g_agps2mnl_path, buff, len) < 0) {
+        LOGE("external_snd_cmd safe_sendto failed\n");
+        ret = -1;
+    }
+    close(sockfd);
+    return ret;
+}
+
+static int bind_udp_socket(char* path) {
+    int sockfd;
+    struct sockaddr_un soc_addr;
+    socklen_t addr_len;
+
+    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+
+    MNLD_STRNCPY(soc_addr.sun_path, path,sizeof(soc_addr.sun_path));
+    soc_addr.sun_family = AF_UNIX;
+    addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+    unlink(soc_addr.sun_path);
+    if (bind(sockfd, (struct sockaddr *)&soc_addr, addr_len) < 0) {
+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));
+        close(sockfd);
+        return -1;
+    }
+
+    if (chmod(path, 0660) < 0) {
+        LOGE("chmod err = [%s]\n", strerror(errno));
+    }
+    return sockfd;
+}
+
+int agps2mnl_agps_reboot() {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  agps_reboot\n");
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_REBOOT);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_agps_open_gps_req(int show_gps_icon) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  agps_open_gps_req  show_gps_icon=%d\n", show_gps_icon);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ);
+    put_int(buff, &offset, show_gps_icon);
+
+    return send2mnl(buff, offset);
+}
+int agps2mnl_agps_close_gps_req() {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  agps_close_gps_req\n");
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ);
+
+    return send2mnl(buff, offset);
+}
+int agps2mnl_agps_reset_gps_req(int flags) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  agps_reset_gps_req  flags=0x%x\n", flags);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ);
+    put_int(buff, &offset, flags);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_agps_session_done() {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  agps_session_done\n");
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_SESSION_DONE);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_ni_notify(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  ni_notify  session_id=%d type=%d requestor_id=[%s] client_name=[%s]\n",
+                 session_id, type, requestor_id, client_name);
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_NI_NOTIFY);
+    put_int(buff, &offset, session_id);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, requestor_id);
+    put_string(buff, &offset, client_name);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_ni_notify2(int session_id, mnl_agps_notify_type type, const char* requestor_id, const char* client_name,
+    mnl_agps_ni_encoding_type requestor_id_encoding, mnl_agps_ni_encoding_type client_name_encoding) {
+
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  ni_notify2  session_id=%d type=%d requestor_id=[%s] type=%d client_name=[%s] type=%d\n",
+        session_id, type, requestor_id, requestor_id_encoding, client_name, client_name_encoding);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_NI_NOTIFY_2);
+    put_int(buff, &offset, session_id);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, requestor_id);
+    put_string(buff, &offset, client_name);
+    put_int(buff, &offset, requestor_id_encoding);
+    put_int(buff, &offset, client_name_encoding);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_req(int ipaddr, int is_emergency) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  data_conn_req  ipaddr=0x%x is_emergency=%d\n", ipaddr, is_emergency);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_REQ);
+    put_int(buff, &offset, ipaddr);
+    put_int(buff, &offset, is_emergency);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_req2(struct sockaddr_storage* addr, int is_emergency) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  data_conn_req2  is_emergency=%d\n", is_emergency);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_REQ2);
+    put_binary(buff, &offset, (const char*)addr, sizeof(*addr));
+    put_int(buff, &offset, is_emergency);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_data_conn_release() {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  data_conn_release\n");
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_RELEASE);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_set_id_req(int flags) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  set_id_req  flags=0x%x\n", flags);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_SET_ID_REQ);
+    put_int(buff, &offset, flags);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_ref_loc_req(int flags) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  ref_loc_req  flags=0x%x\n", flags);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_REF_LOC_REQ);
+    put_int(buff, &offset, flags);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_pmtk(const char* pmtk) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  pmtk  [%s]\n", pmtk);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS2MNL_PMTK);
+    put_string(buff, &offset, pmtk);
+
+    return send2mnl(buff, offset);
+}
+int agps2mnl_gpevt(gpevt_type type) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    LOGD("write  gpevt  type=%d\n", type);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_GPEVT);
+    put_int(buff, &offset, type);
+
+    return send2mnl(buff, offset);
+}
+
+int agps2mnl_agps_location(mnl_agps_agps_location* location) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+#if ANDROID_MNLD_PROP_SUPPORT
+    char result[PROPERTY_VALUE_MAX] = {0};
+
+    property_get(HIDE_LOG_PROP, result, NULL);
+    if (result[0] != '1') {
+        LOGD("write  agps_location  lat=%f lng=%f\n", location->latitude, location->longitude);
+    }
+#endif
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_LOC);
+    put_binary(buff, &offset, (const char*)location, sizeof(mnl_agps_agps_location));
+
+    return send2mnl(buff, offset);
+}
+
+void mnl2agps_hdlr(int fd, mnl2agps_interface* agps_interface) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    int ret;
+
+    ret = safe_recvfrom(fd, buff, sizeof(buff));
+    if (ret <= 0) {
+        LOGE("agps2mnl_handler() safe_recvfrom() failed ret=%d", ret);
+        return;
+    }
+
+    int version = get_int(buff, &offset, sizeof(buff));
+
+    if (version != MNL_AGPS_INTERFACE_VERSION) {
+        LOGE("mnl_ver=%d agps_ver=%d\n",
+            version, MNL_AGPS_INTERFACE_VERSION);
+    }
+
+    mnl_agps_type type = get_int(buff, &offset, sizeof(buff));
+
+    switch (type) {
+    case MNL_AGPS_TYPE_MNL_REBOOT: {
+        if (agps_interface->mnl_reboot) {
+           agps_interface->mnl_reboot();
+        } else {
+            LOGE("mnl_reboot is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE: {
+        if (agps_interface->open_gps_done) {
+           agps_interface->open_gps_done();
+        } else {
+            LOGE("open_gps_done is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE: {
+        if (agps_interface->close_gps_done) {
+           agps_interface->close_gps_done();
+        } else {
+            LOGE("close_gps_done is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE: {
+        if (agps_interface->reset_gps_done) {
+           agps_interface->reset_gps_done();
+        } else {
+            LOGE("reset_gps_done is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_GPS_INIT: {
+        if (agps_interface->gps_init) {
+           agps_interface->gps_init();
+        } else {
+            LOGE("gps_init is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_GPS_CLEANUP: {
+        if (agps_interface->gps_cleanup) {
+           agps_interface->gps_cleanup();
+        } else {
+            LOGE("gps_cleanup is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_SET_SERVER: {
+        int type = get_int(buff, &offset, sizeof(buff));
+        const char* hostname = get_string(buff, &offset, sizeof(buff));
+        int port = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->set_server) {
+           agps_interface->set_server(type, hostname, port);
+        } else {
+            LOGE("set_server is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DELETE_AIDING_DATA: {
+        int flags = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->delete_aiding_data) {
+           agps_interface->delete_aiding_data(flags);
+        } else {
+            LOGE("delete_aiding_data is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_GPS_OPEN: {
+        int assist_req = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->gps_open) {
+           agps_interface->gps_open(assist_req);
+        } else {
+            LOGE("gps_open is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_GPS_CLOSE: {
+        if (agps_interface->gps_close) {
+           agps_interface->gps_close();
+        } else {
+            LOGE("gps_close is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_OPEN: {
+        const char* apn = get_string(buff, &offset, sizeof(buff));
+        if (agps_interface->data_conn_open) {
+           agps_interface->data_conn_open(apn);
+        } else {
+            LOGE("data_conn_open is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE: {
+        const char* apn = get_string(buff, &offset, sizeof(buff));
+        int ip_type = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->data_conn_open_ip_type) {
+           agps_interface->data_conn_open_ip_type(apn, ip_type);
+        } else {
+            LOGE("data_conn_open_ip_type is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_INSTALL_CERTIFICATES: {
+        int index = get_int(buff, &offset, sizeof(buff));
+        int total = get_int(buff, &offset, sizeof(buff));
+        char data[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+        int len = get_binary(buff, &offset, data, sizeof(buff), sizeof(data));
+        if (agps_interface->install_certificates) {
+           agps_interface->install_certificates(index, total, data, len);
+        } else {
+            LOGE("install_certificates is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_REVOKE_CERTIFICATES: {
+        char data[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+        int len = get_binary(buff, &offset, data, sizeof(buff), sizeof(data));
+        if (agps_interface->revoke_certificates) {
+           agps_interface->revoke_certificates(data, len);
+        } else {
+            LOGE("revoke_certificates is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_FAILED: {
+        if (agps_interface->data_conn_failed) {
+           agps_interface->data_conn_failed();
+        } else {
+            LOGE("data_conn_failed is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_CLOSED: {
+        if (agps_interface->data_conn_closed) {
+           agps_interface->data_conn_closed();
+        } else {
+            LOGE("data_conn_closed is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_NI_MESSAGE: {
+        char msg[1024] = {0};
+        int len;
+        len = get_binary(buff, &offset, msg, sizeof(buff), sizeof(msg));
+        if (agps_interface->ni_message) {
+           agps_interface->ni_message(msg, len);
+        } else {
+            LOGE("ni_message is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_NI_RESPOND: {
+        int session_id = get_int(buff, &offset, sizeof(buff));
+        int user_response = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->ni_respond) {
+           agps_interface->ni_respond(session_id, user_response);
+        } else {
+            LOGE("ni_respond is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_SET_REF_LOC: {
+        int type = get_int(buff, &offset, sizeof(buff));
+        int mcc = get_int(buff, &offset, sizeof(buff));
+        int mnc = get_int(buff, &offset, sizeof(buff));
+        int lac = get_int(buff, &offset, sizeof(buff));
+        int cid = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->set_ref_loc) {
+           agps_interface->set_ref_loc(type, mcc, mnc, lac, cid);
+        } else {
+            LOGE("set_ref_loc is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_SET_SET_ID: {
+        int type = get_int(buff, &offset, sizeof(buff));
+        const char* setid = get_string(buff, &offset, sizeof(buff));
+        if (agps_interface->set_set_id) {
+           agps_interface->set_set_id(type, setid);
+        } else {
+            LOGE("set_set_id is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_UPDATE_NETWORK_STATE: {
+        int connected = get_int(buff, &offset, sizeof(buff));
+        int type = get_int(buff, &offset, sizeof(buff));
+        int roaming = get_int(buff, &offset, sizeof(buff));
+        const char* extra_info = get_string(buff, &offset, sizeof(buff));
+        if (agps_interface->update_network_state) {
+           agps_interface->update_network_state(connected, type, roaming, extra_info);
+        } else {
+            LOGE("update_network_state is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY: {
+        int avaiable = get_int(buff, &offset, sizeof(buff));
+        const char* apn = get_string(buff, &offset, sizeof(buff));
+        if (agps_interface->update_network_availability) {
+           agps_interface->update_network_availability(avaiable, apn);
+        } else {
+            LOGE("update_network_availability is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_MNL2AGPS_PMTK: {
+        const char* pmtk = get_string(buff, &offset, sizeof(buff));
+        if (agps_interface->rcv_pmtk) {
+           agps_interface->rcv_pmtk(pmtk);
+        } else {
+            LOGE("rcv_pmtk is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_RAW_DBG: {
+        int enabled = get_int(buff, &offset, sizeof(buff));
+        if (agps_interface->raw_dbg) {
+           agps_interface->raw_dbg(enabled);
+        } else {
+            LOGE("raw_dbg is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_REAIDING: {
+        if (agps_interface->reaiding_req) {
+            agps_interface->reaiding_req();
+        } else {
+            LOGE("reaiding_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_LOCATION_SYNC: {
+        if (agps_interface->location_sync) {
+            double lat = get_double(buff, &offset, sizeof(buff));
+            double lng = get_double(buff, &offset, sizeof(buff));
+            int acc = get_int(buff, &offset, sizeof(buff));
+            bool alt_valid = get_byte(buff, &offset, sizeof(buff));
+            float alt = get_float(buff, &offset, sizeof(buff));
+            bool source_valid = get_byte(buff, &offset, sizeof(buff));
+            bool source_gnss = get_byte(buff, &offset, sizeof(buff));
+            bool source_nlp = get_byte(buff, &offset, sizeof(buff));
+            bool source_sensor = get_byte(buff, &offset, sizeof(buff));
+            agps_interface->location_sync(lat, lng, acc, alt_valid, alt, source_valid, source_gnss, source_nlp, source_sensor);
+        } else {
+            LOGE("location_sync is NULL\n");
+        }
+        break;
+    }
+    default:
+        LOGE("mnl2agps unknown type=%d\n", type);
+        break;
+    }
+}
+
+int create_mnl2agps_fd() {
+    int fd = bind_udp_socket(MNL_TO_AGPS);
+    set_socket_blocking(fd, 0);
+    return fd;
+}
+
+int create_mnl2agps_fd2(const char* agps2mnl_path) {
+    int fd = bind_udp_socket(MNL_TO_AGPS);
+    set_socket_blocking(fd, 0);
+    MNLD_STRNCPY(g_agps2mnl_path, agps2mnl_path,sizeof(g_agps2mnl_path));
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c
new file mode 100644
index 0000000..8556f85
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl2agps_interface.c
@@ -0,0 +1,809 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h>  // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h>  // inet_addr
+#include <sys/un.h>  // struct sockaddr_un
+
+#include "mnl2agps_interface.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MNL2AGPS"
+#endif
+
+// -1 means failure
+static int safe_recvfrom(int sockfd, char* buf, int len) {
+    int ret = 0;
+    int retry = 10;
+
+    while ((ret = recvfrom(sockfd, buf, len, 0,
+         NULL, NULL)) == -1) {
+        LOGW("ret=%d len=%d\n", ret, len);
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto reason=[%s]\n", strerror(errno));
+        break;
+    }
+    return ret;
+}
+
+// -1 means failure
+static int set_socket_blocking(int fd, int blocking) {
+    if (fd < 0) {
+        LOGE("set_socket_blocking  invalid fd=%d\n", fd);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags < 0) {
+        LOGE("set_socket_blocking  invalid flags=%d\n", flags);
+        return -1;
+    }
+
+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+static int safe_sendto(int sockfd, const char* dest, const char* buf, int size) {
+    int len = 0;
+    struct sockaddr_un soc_addr;
+    socklen_t addr_len;
+    int retry = 10;
+
+    MNLD_STRNCPY(soc_addr.sun_path, dest,sizeof(soc_addr.sun_path));
+    soc_addr.sun_family = AF_UNIX;
+    addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+    while ((len = sendto(sockfd, buf, size, 0,
+        (const struct sockaddr *)&soc_addr, (socklen_t)addr_len)) == -1) {
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto dest=[%s] len=%d reason=[%s]\n",
+            dest, size, strerror(errno));
+        break;
+    }
+    return len;
+}
+
+// -1 means failure
+static int send2agps(const char* buff, int len) {
+    int ret = 0;
+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+
+    if (safe_sendto(sockfd, MNL_TO_AGPS, buff, len) < 0) {
+        LOGE("external_snd_cmd safe_sendto failed, path:%s", MNL_TO_AGPS);
+        ret = -1;
+    }
+    close(sockfd);
+    return ret;
+}
+
+int mnl2agps_set_position_mode(int pos_mode) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    LOGD("mnl2agps_set_position_mode, pos_mode = %d", pos_mode);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_SET_POSITION_MODE);
+    put_int(buff, &offset, pos_mode);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_update_configuration(const char* config_data, int length) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_CONFIGURATION);
+    put_string(buff, &offset, config_data);
+    put_int(buff, &offset, length);
+
+    return send2agps(buff, offset);
+}
+
+static int bind_udp_socket(char* path) {
+    int fd;
+    struct sockaddr_un addr;
+    socklen_t addr_len;
+
+    fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("socket_bind_udp() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    MNLD_STRNCPY(addr.sun_path, path,sizeof(addr.sun_path));
+    addr.sun_family = AF_UNIX;
+    addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1);
+    unlink(addr.sun_path);
+    if (bind(fd, (struct sockaddr *)&addr, addr_len) < 0) {
+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));
+        close(fd);
+        return -1;
+    }
+    if (chmod(path, 0660) < 0) {
+        LOGE("chmod err = [%s]\n", strerror(errno));
+    }
+
+    return fd;
+}
+
+int mnl2agps_mnl_reboot() {
+    LOGD("mnl2agps_mnl_reboot");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_MNL_REBOOT);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_open_gps_done() {
+    LOGD("mnl2agps_open_gps_done");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_close_gps_done() {
+    LOGD("mnl2agps_close_gps_done");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_reset_gps_done() {
+    LOGD("mnl2agps_reset_gps_done");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_gps_init() {
+    LOGD("mnl2agps_gps_init");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_GPS_INIT);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_gps_cleanup() {
+    LOGD("mnl2agps_gps_cleanup");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_GPS_CLEANUP);
+
+    return send2agps(buff, offset);
+}
+// type:AGpsType
+int mnl2agps_set_server(int type, const char* hostname, int port) {
+    //LOGD("mnl2agps_set_server, hostname = %s, port = %d\n", hostname, port);
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_SET_SERVER);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, hostname);
+    put_int(buff, &offset, port);
+
+    return send2agps(buff, offset);
+}
+// flags:GpsAidingData
+int mnl2agps_delete_aiding_data(int flags) {
+    //LOGD("mnl2agps_delete_aiding_data");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DELETE_AIDING_DATA);
+    put_int(buff, &offset, flags);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_gps_open(int assist_req) {
+    LOGD("mnl2agps_gps_open");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_GPS_OPEN);
+    put_int(buff, &offset, assist_req);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_gps_close() {
+    LOGD("mnl2agps_gps_close");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_GPS_CLOSE);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_data_conn_open(const char* apn) {
+    //LOGD("mnl2agps_data_conn_open, apn = %s\n", apn);
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_OPEN);
+    put_string(buff, &offset, apn);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_data_conn_open_ip_type(const char* apn, int ip_type) {
+    //LOGD("mnl2agps_data_conn_open  apn=%s ip_type=%d\n", apn, ip_type);
+
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE);
+    put_string(buff, &offset, apn);
+    put_int(buff, &offset, ip_type);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_install_certificates(int index, int total, const char* data, int len) {
+    LOGD("mnl2agps_install_certificates  (%d/%d) len=%d\n", index, total, len);
+
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_INSTALL_CERTIFICATES);
+    put_int(buff, &offset, index);
+    put_int(buff, &offset, total);
+    put_binary(buff, &offset, data, len);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_revoke_certificates(const char* data, int len) {
+    LOGD("mnl2agps_revoke_certificates  len=%d item=%d\n", len, len/20);
+
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_REVOKE_CERTIFICATES);
+    put_binary(buff, &offset, data, len);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_data_conn_failed() {
+    LOGD("mnl2agps_data_conn_failed");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_FAILED);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_data_conn_closed() {
+    //LOGD("mnl2agps_data_conn_closed");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_DATA_CONN_CLOSED);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_ni_message(const char* msg, int len) {
+    //LOGD("mnl2agps_ni_message");
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_NI_MESSAGE);
+    put_binary(buff, &offset, msg, len);
+
+    return send2agps(buff, offset);
+}
+
+/*
+ACCEPT = 1
+DENY = 2
+NO_RSP = 3
+*/
+int mnl2agps_ni_respond(int session_id, int user_response) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    //LOGD("session_id: %d, user_response: %d\n", session_id, user_response);
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_NI_RESPOND);
+    put_int(buff, &offset, session_id);
+    put_int(buff, &offset, user_response);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_set_ref_loc(int type, int mcc, int mnc, int lac, int cid) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    //LOGD("type=%d, mcc=%d, mnc=%d, lac=%d, cid=%d\n", type, mcc, mnc, lac, cid);
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_SET_REF_LOC);
+    put_int(buff, &offset, type);
+    put_int(buff, &offset, mcc);
+    put_int(buff, &offset, mnc);
+    put_int(buff, &offset, lac);
+    put_int(buff, &offset, cid);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_set_set_id(int type, const char* setid) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    //LOGD("type=%d, setid = %s\n", type, setid);
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_SET_SET_ID);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, setid);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_update_network_state(int connected, int type, int roaming, const char* extra_info) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    //LOGD("connected=%d, type = %d, roaming=%d, extra_info=%s\n", connected, type, roaming, extra_info);
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_NETWORK_STATE);
+    put_int(buff, &offset, connected);
+    put_int(buff, &offset, type);
+    put_int(buff, &offset, roaming);
+    put_string(buff, &offset, extra_info);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_update_network_availability(int avaiable, const char* apn) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    //LOGD("avaiable=%d, apn=%s\n", avaiable, apn);
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY);
+    put_int(buff, &offset, avaiable);
+    put_string(buff, &offset, apn);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_pmtk(const char* pmtk) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_MNL2AGPS_PMTK);
+    put_string(buff, &offset, pmtk);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_raw_dbg(int enabled) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_RAW_DBG);
+    put_int(buff, &offset, enabled);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_reaiding_req() {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_REAIDING);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_location_sync(double lat, double lng, int acc, bool alt_valid, float alt, bool source_valid, bool source_gnss, bool source_nlp, bool source_sensor) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_LOCATION_SYNC);
+    put_double(buff, &offset, lat);
+    put_double(buff, &offset, lng);
+    put_int(buff, &offset, acc);
+    put_byte(buff, &offset, alt_valid);
+    put_float(buff, &offset, alt);
+    put_byte(buff, &offset, source_valid);
+    put_byte(buff, &offset, source_gnss);
+    put_byte(buff, &offset, source_nlp);
+    put_byte(buff, &offset, source_sensor);
+
+    //LOGW("LPPe debug:mnl2agps_location_sync: lat:%.3f, lng:%.3f, acc:%d, alt_valid:%d, alt:%.2f, source_valid:%d, gnss:%d, nlp:%d, sensor:%d", \
+    //    lat, lng, acc, alt_valid, alt, source_valid, source_gnss, source_nlp, source_sensor);
+    return send2agps(buff, offset);
+}
+int mnl2agps_agps_settings_ack(mnl_agps_gnss_settings* settings) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_SETTINGS_ACK);
+    put_int(buff, &offset, settings->gps_satellite_support);
+    put_int(buff, &offset, settings->glonass_satellite_support);
+    put_int(buff, &offset, settings->beidou_satellite_support);
+    put_int(buff, &offset, settings->galileo_satellite_support);
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_vzw_debug_screen_enable(int enabled) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_ENABLE);
+    put_int(buff, &offset, enabled);
+
+    return send2agps(buff, offset);
+}
+int mnl2agps_lppe_assist_data_req(const char* data, int len) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_DATA_REQ);
+    put_binary(buff, &offset, data, len);   // refer to gnss_ha_assist_data_req_struct
+
+    return send2agps(buff, offset);
+}
+
+int mnl2agps_lppe_assist_data_provide_ack(const char* data, int len) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_AGPS_INTERFACE_VERSION);
+    put_int(buff, &offset, MNL_AGPS_TYPE_LPPE_ASSIST_DATA_PROVIDE_ACK);
+    put_binary(buff, &offset, data, len);   // refer to gnss_ha_assist_ack_struct
+
+    return send2agps(buff, offset);
+}
+void mnl2fake_agpsd_hdlr(int fd) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    int ret;
+
+    ret = safe_recvfrom(fd, buff, sizeof(buff));
+    if (ret <= 0) {
+        LOGE("mnl2agps_handler() safe_recvfrom() failed ret=%d", ret);
+        return;
+    }
+    int version = get_int(buff, &offset, sizeof(buff));
+
+    if (version != MNL_AGPS_INTERFACE_VERSION) {
+        LOGE("agps_ver=%d mnl_ver=%d\n",
+            version, MNL_AGPS_INTERFACE_VERSION);
+    }
+    mnl_agps_type type = get_int(buff, &offset, sizeof(buff));
+    LOGE("*#*#type:%d\n",type);
+}
+
+void agps2mnl_hdlr(int fd, agps2mnl_interface* mnl_interface) {
+    char buff[MNL_AGPS_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    int ret;
+
+    ret = safe_recvfrom(fd, buff, sizeof(buff));
+    if (ret <= 0) {
+        LOGE("mnl2agps_handler() safe_recvfrom() failed ret=%d", ret);
+        return;
+    }
+    int version = get_int(buff, &offset, sizeof(buff));
+
+    if (version != MNL_AGPS_INTERFACE_VERSION) {
+        LOGE("agps_ver=%d mnl_ver=%d\n",
+            version, MNL_AGPS_INTERFACE_VERSION);
+    }
+
+    mnl_agps_type type = get_int(buff, &offset, sizeof(buff));
+    // LOGD("agps2mnl [%s]\n", get_mnl_agps_type_str(type));
+
+    switch (type) {
+    case MNL_AGPS_TYPE_AGPS_REBOOT: {
+        if (mnl_interface->agps_reboot) {
+            mnl_interface->agps_reboot();
+        } else {
+            LOGE("agps_reboot is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ: {
+        int show_gps_icon = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->agps_open_gps_req) {
+            mnl_interface->agps_open_gps_req(show_gps_icon);
+        } else {
+            LOGE("agps_open_gps_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ: {
+        if (mnl_interface->agps_close_gps_req) {
+            mnl_interface->agps_close_gps_req();
+        } else {
+            LOGE("agps_close_gps_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ: {
+        int flags = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->agps_reset_gps_req) {
+            mnl_interface->agps_reset_gps_req(flags);
+        } else {
+            LOGE("agps_reset_gps_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_SESSION_DONE: {
+        if (mnl_interface->agps_session_done) {
+            mnl_interface->agps_session_done();
+        } else {
+            LOGE("agps_session_done is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_NI_NOTIFY: {
+        int session_id = get_int(buff, &offset, sizeof(buff));
+        mnl_agps_notify_type type = get_int(buff, &offset, sizeof(buff));
+        const char* requestor_id = get_string(buff, &offset, sizeof(buff));
+        const char* client_name = get_string(buff, &offset, sizeof(buff));
+        if (mnl_interface->ni_notify) {
+            mnl_interface->ni_notify(session_id, type, requestor_id, client_name);
+        } else {
+            LOGE("ni_notify is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_NI_NOTIFY_2: {
+        int session_id = get_int(buff, &offset, sizeof(buff));
+        mnl_agps_notify_type type = get_int(buff, &offset, sizeof(buff));
+        const char* requestor_id = get_string(buff, &offset, sizeof(buff));
+        const char* client_name = get_string(buff, &offset, sizeof(buff));
+        int requestor_id_encoding = get_int(buff, &offset, sizeof(buff));
+        int client_name_encoding = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->ni_notify2) {
+            mnl_interface->ni_notify2(session_id, type, requestor_id,
+               client_name, requestor_id_encoding, client_name_encoding);
+        } else {
+            LOGE("ni_notify2 is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_REQ: {
+        int ipaddr = get_int(buff, &offset, sizeof(buff));
+        int is_emergency = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->data_conn_req) {
+            mnl_interface->data_conn_req(ipaddr, is_emergency);
+        } else {
+            LOGE("data_conn_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_REQ2: {
+        struct sockaddr_storage addr;
+        get_binary(buff, &offset, (char*)&addr, sizeof(buff), sizeof(addr));
+        int is_emergency = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->data_conn_req2) {
+            mnl_interface->data_conn_req2(&addr, is_emergency);
+        } else {
+            LOGE("data_conn_req2 is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_DATA_CONN_RELEASE: {
+        if (mnl_interface->data_conn_release) {
+            mnl_interface->data_conn_release();
+        } else {
+            LOGE("data_conn_release is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_SET_ID_REQ: {
+        int flags = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->set_id_req) {
+            mnl_interface->set_id_req(flags);
+        } else {
+            LOGE("set_id_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_REF_LOC_REQ: {
+        int flags = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->ref_loc_req) {
+            mnl_interface->ref_loc_req(flags);
+        } else {
+            LOGE("ref_loc_req is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS2MNL_PMTK: {
+        const char* pmtk = get_string(buff, &offset, sizeof(buff));
+        if (mnl_interface->rcv_pmtk) {
+            mnl_interface->rcv_pmtk(pmtk);
+        } else {
+            LOGE("rcv_pmtk is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_GPEVT: {
+        gpevt_type type = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->gpevt) {
+            mnl_interface->gpevt(type);
+        } else {
+            LOGE("gpevt is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_AGPS_LOC: {
+        mnl_agps_agps_location agps_location;
+        get_binary(buff, &offset, (char*)&agps_location, sizeof(buff), sizeof(mnl_agps_agps_location));
+        if (mnl_interface->agps_location) {
+            mnl_interface->agps_location(&agps_location);
+        } else {
+            LOGE("agps_location is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_SETTINGS_SYNC: {
+        mnl_agps_agps_settings agps_settings;
+        agps_settings.sib8_16_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.gps_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.glonass_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.beidou_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.galileo_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.a_glonass_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.a_gps_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.a_beidou_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.a_galileo_satellite_enable = get_int(buff, &offset, sizeof(buff));
+        agps_settings.lppe_enable = get_int(buff, &offset, sizeof(buff));
+        if (mnl_interface->agps_settings_sync) {
+            mnl_interface->agps_settings_sync(&agps_settings);
+        } else {
+            LOGE("agps_settings_sync is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_VZW_DEBUG_SCREEN_OUTPUT: {
+        const char* str = get_string(buff, &offset, sizeof(buff));
+        if (mnl_interface->vzw_debug_screen_output) {
+            mnl_interface->vzw_debug_screen_output(str);
+        } else {
+            LOGE("vzw_debug_screen_output is NULL\n");
+        }
+        break;
+    }
+
+    case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_IONO: {
+        if(mnl_interface->lppe_assist_common_iono) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+        LOGE("mnld rec lppe data ,len=%d,offset=%d\n",lppe_len,offset);
+            mnl_interface->lppe_assist_common_iono(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_common_iono is NULL\n");
+        }
+        break;
+    }
+        case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_TROP: {
+        if(mnl_interface->lppe_assist_common_trop) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+            mnl_interface->lppe_assist_common_trop(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_common_trop is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_ALT: {
+        if(mnl_interface->lppe_assist_common_alt) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+            mnl_interface->lppe_assist_common_alt(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_common_alt is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_SOLAR: {
+        if(mnl_interface->lppe_assist_common_solar) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+            mnl_interface->lppe_assist_common_solar(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_common_solar is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_LPPE_ASSIST_COMMON_CCP: {
+        if(mnl_interface->lppe_assist_common_ccp) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+            mnl_interface->lppe_assist_common_ccp(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_common_ccp is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_CCP: {
+        if(mnl_interface->lppe_assist_generic_ccp) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+            mnl_interface->lppe_assist_generic_ccp(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_generic_ccp is NULL\n");
+        }
+        break;
+    }
+    case MNL_AGPS_TYPE_LPPE_ASSIST_GENERIC_DM: {
+        if(mnl_interface->lppe_assist_generic_dm) {
+        int lppe_len=get_int(buff, &offset, sizeof(buff));
+            mnl_interface->lppe_assist_generic_dm(buff+offset, lppe_len);
+        } else {
+            LOGE("lppe_assist_data_provide_generic_dm is NULL\n");
+        }
+        break;
+    }
+    default:
+        LOGE("agps2mnl unknown type=%d\n", type);
+        break;
+    }
+}
+
+int create_agps2mnl_fd() {
+    int fd = bind_udp_socket(AGPS_TO_MNL);
+    set_socket_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c
new file mode 100644
index 0000000..e5648e6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_agps_interface/src/mnl_agps_interface.c
@@ -0,0 +1,91 @@
+
+#include "mnl_agps_interface.h"
+
+const char* get_mnl_agps_type_str(mnl_agps_type input) {
+    switch (input) {
+    case MNL_AGPS_TYPE_MNL_REBOOT:
+        return "MNL_REBOOT";
+    case MNL_AGPS_TYPE_AGPS_OPEN_GPS_DONE:
+        return "AGPS_OPEN_GPS_DONE";
+    case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_DONE:
+        return "AGPS_CLOSE_GPS_DONE";
+    case MNL_AGPS_TYPE_AGPS_RESET_GPS_DONE:
+        return "AGPS_RESET_GPS_DONE";
+    case MNL_AGPS_TYPE_GPS_INIT:
+        return "GPS_INIT";
+    case MNL_AGPS_TYPE_GPS_CLEANUP:
+        return "GPS_CLEANUP";
+    case MNL_AGPS_TYPE_SET_SERVER:
+        return "SET_SERVER";
+    case MNL_AGPS_TYPE_DELETE_AIDING_DATA:
+        return "DELETE_AIDING_DATA";
+    case MNL_AGPS_TYPE_GPS_OPEN:
+        return "GPS_OPEN";
+    case MNL_AGPS_TYPE_GPS_CLOSE:
+        return "GPS_CLOSE";
+    case MNL_AGPS_TYPE_DATA_CONN_OPEN:
+        return "DATA_CONN_OPEN";
+    case MNL_AGPS_TYPE_DATA_CONN_FAILED:
+        return "DATA_CONN_FAILED";
+    case MNL_AGPS_TYPE_DATA_CONN_CLOSED:
+        return "DATA_CONN_CLOSED";
+    case MNL_AGPS_TYPE_NI_MESSAGE:
+        return "NI_MESSAGE";
+    case MNL_AGPS_TYPE_NI_RESPOND:
+        return "NI_RESPOND";
+    case MNL_AGPS_TYPE_SET_REF_LOC:
+        return "SET_REF_LOC";
+    case MNL_AGPS_TYPE_SET_SET_ID:
+        return "SET_SET_ID";
+    case MNL_AGPS_TYPE_UPDATE_NETWORK_STATE:
+        return "UPDATE_NETWORK_STATE";
+    case MNL_AGPS_TYPE_UPDATE_NETWORK_AVAILABILITY:
+        return "UPDATE_NETWORK_AVAILABILITY";
+    case MNL_AGPS_TYPE_DATA_CONN_OPEN_IP_TYPE:
+        return "DATA_CONN_OPEN_IP_TYPE";
+    case MNL_AGPS_TYPE_INSTALL_CERTIFICATES:
+        return "INSTALL_CERTIFICATES";
+    case MNL_AGPS_TYPE_REVOKE_CERTIFICATES:
+        return "REVOKE_CERTIFICATES";
+    case MNL_AGPS_TYPE_MNL2AGPS_PMTK:
+        return "MNL2AGPS_PMTK";
+    case MNL_AGPS_TYPE_RAW_DBG:
+        return "RAW_DBG";
+    case MNL_AGPS_TYPE_REAIDING:
+        return "REAIDING_REQ";
+    case MNL_AGPS_TYPE_AGPS_REBOOT:
+        return "AGPS_REBOOT";
+    case MNL_AGPS_TYPE_AGPS_OPEN_GPS_REQ:
+        return "AGPS_OPEN_GPS_REQ";
+    case MNL_AGPS_TYPE_AGPS_CLOSE_GPS_REQ:
+        return "AGPS_CLOSE_GPS_REQ";
+    case MNL_AGPS_TYPE_AGPS_RESET_GPS_REQ:
+        return "AGPS_RESET_GPS_REQ";
+    case MNL_AGPS_TYPE_AGPS_SESSION_DONE:
+        return "AGPS_SESSION_DONE";
+    case MNL_AGPS_TYPE_NI_NOTIFY:
+        return "NI_NOTIFY";
+    case MNL_AGPS_TYPE_NI_NOTIFY_2:
+        return "NI_NOTIFY2";
+    case MNL_AGPS_TYPE_DATA_CONN_REQ:
+        return "DATA_CONN_REQ";
+    case MNL_AGPS_TYPE_DATA_CONN_REQ2:
+        return "DATA_CONN_REQ2";
+    case MNL_AGPS_TYPE_DATA_CONN_RELEASE:
+        return "DATA_CONN_RELEASE";
+    case MNL_AGPS_TYPE_SET_ID_REQ:
+        return "SET_ID_REQ";
+    case MNL_AGPS_TYPE_REF_LOC_REQ:
+        return "REF_LOC_REQ";
+    case MNL_AGPS_TYPE_AGPS2MNL_PMTK:
+        return "AGPS2MNL_PMTK";
+    case MNL_AGPS_TYPE_GPEVT:
+        return "GPEVT";
+    case MNL_AGPS_TYPE_AGPS_LOC:
+        return "AGPS_LOC";
+    default:
+        break;
+    }
+    return "UNKNOWN";
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h
new file mode 100644
index 0000000..e1c4c4e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/inc/mnl_at_interface.h
@@ -0,0 +1,43 @@
+#ifndef __MNL_AT_INTERFACE_H__
+#define __MNL_AT_INTERFACE_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#include "nmea_parser.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//======================================================
+// GPS AT -> MNLD
+//======================================================
+#define GPS_AT_COMMAND_SOCK    "/data/server"                 // For receive AT command
+
+int mnl2at_send_data();
+
+int at_test2mnl_gps_start(void);
+int at_test2mnl_gps_stop(void);
+void at_command_send_cno(char* cmdline);
+int at_command_parse_test_num(char* cmdline);
+void at_command_send_ack(char* ack, int len);
+void at_command_send_test_result();
+void gps_at_command_test_proc(NmeaReader* const r);
+void nmea_parser_at_cmd_pre(void);
+
+void at_cmd2mnl_hdlr(int fd);
+
+// -1 means failure
+int create_at2mnl_fd();
+//======================================================
+// MNLD -> GPS AT CMD
+//======================================================
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c
new file mode 100644
index 0000000..580abbd
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_at_cmd_interface/src/mnl_at_interface.c
@@ -0,0 +1,705 @@
+#include <time.h>

+#include <sys/socket.h>

+#include <sys/un.h>

+#include <arpa/inet.h>

+#include <netinet/in.h>

+#include <math.h>

+#include <stdlib.h>

+#include <errno.h>

+

+#include "mnl_at_interface.h"

+#include "nmea_parser.h"

+#include "mtk_lbs_utility.h"

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "at2mnl"

+#endif

+

+/*AT command test state*/

+#define GPS_TEST_PRN 1

+int MNL_AT_TEST_FLAG = 0;

+int MNL_AT_SIGNAL_MODE = 0;

+static int MNL_AT_SIGNAL_TEST_BEGIN = 0;

+

+int MNL_AT_SET_ALARM       = 0;

+int MNL_AT_CANCEL_ALARM    = 0;

+

+enum {

+    MNL_AT_TEST_UNKNOWN = -1,

+    MNL_AT_TEST_START       = 0x00,

+    MNL_AT_TEST_STOP        = 0x01,

+    MNL_AT_TEST_INPROGRESS   = 0x02,

+    MNL_AT_TEST_DONE       = 0x03,

+    MNL_AT_TEST_RESULT_DONE = 0x04,

+};

+int MNL_AT_TEST_STATE = MNL_AT_TEST_UNKNOWN;

+typedef struct {

+    int test_num;

+    int prn_num;

+    int time_delay;

+}HAL_AT_TEST_T;

+

+static HAL_AT_TEST_T hal_test_data = {

+    .test_num = 0,

+    .prn_num = 0,

+    .time_delay = 0,

+};

+

+int* Dev_CNr = NULL;

+int prn[32] = {0};

+int snr[32] = {0};

+int cn = 0;

+/*

+* Test result array: error_code, theta(0), phi(0), Success_Num,

+* Complete_Num, Avg_CNo, Dev_CNo, Avg_Speed(0)

+*/

+static int result[8] = {1, 0, 0, 0, 0, 0, 0, 0};

+static int test_num = 0;

+static int CNo, DCNo;

+static int Avg_CNo = 0;

+static int Dev_CNo = 0;

+static int Completed_Num = 0;

+static int Success_Num = 0;

+static int Failure_Num = 0;

+static int Wait_Num = 0;

+static int sig_suc_num = 0;

+static int Err_Code = 1;

+#define MAX_VALID_STATUS_WAIT_COUNT 20   // 12

+int test_mode_flag = 1;    // 0: USB mode, 1: SMS mode

+

+static int fd_at_test = 0;

+static struct sockaddr_un remote;

+static socklen_t remotelen;

+static time_t start_time;

+

+#define  GPS_OP   "AT%GPS"

+#define  GNSS_OP  "AT%GNSS"

+#define  GPS_AT_ACK_SIZE        60

+

+

+/*for GPS AT command test*/

+int gpsinf_mtk_gps_test_stop() {

+   int err;

+   test_mode_flag = 1;

+

+   if ((err = at_test2mnl_gps_stop())) {

+       LOGE("at_test2mnl_gps_stop err = %d", err);

+       return -1;

+   }

+

+//   gps_state_test_stop(s);

+

+   hal_test_data.test_num = 0;

+   hal_test_data.prn_num = 0;

+   hal_test_data.time_delay = 0;

+   MNL_AT_TEST_FLAG = 0;

+   MNL_AT_SIGNAL_MODE = 0;

+   MNL_AT_TEST_STATE = MNL_AT_TEST_UNKNOWN;

+

+   MNL_AT_SET_ALARM       = 0;

+   MNL_AT_CANCEL_ALARM    = 0;

+   MNL_AT_SIGNAL_TEST_BEGIN = 0;

+

+   // release the variable

+   Success_Num = 0;

+   Completed_Num = 0;

+   Wait_Num = 0;

+   CNo = 0;

+   DCNo = 0;

+   Dev_CNo = 0;

+   Err_Code = 1;

+   test_num = 0;

+

+   if (NULL != Dev_CNr) {

+       LOGD("Free Dev_CNr");

+       free(Dev_CNr);

+   }

+   return 0;

+}

+

+int gpsinf_mtk_gps_test_start(int test_num, int prn_num, int time_delay, int test_mode) {

+   int err;

+

+   if ((MNL_AT_TEST_STATE != MNL_AT_TEST_UNKNOWN) && test_mode_flag) {

+       LOGD("[SMS test mode] Timeout, test_stop() before test_start()");

+       gpsinf_mtk_gps_test_stop();

+   }

+

+   hal_test_data.test_num = test_num;

+   hal_test_data.prn_num = prn_num;

+   hal_test_data.time_delay = time_delay;

+   time(&start_time);

+

+   //  ithis code is moved from stop function to here to keep avg value for AT%GPS(GNSS) or AT%GPS=?(GNSS=?)

+   Avg_CNo = 0;

+   Dev_CNr = (int*)malloc(sizeof(int)*hal_test_data.test_num);

+   memset(Dev_CNr, 0, test_num*sizeof(int));

+

+   if ((0 == hal_test_data.test_num) && (0 == test_mode)) {

+       LOGE("%s: test number is 0!!", __FUNCTION__);

+       return -1;

+   }

+   if (1 == test_mode) {

+       LOGD("Signal test mode");

+       MNL_AT_SIGNAL_MODE = 1;

+   } else {

+       LOGD("Normal test mode");

+       MNL_AT_TEST_FLAG = 1;

+   }

+

+   MNL_AT_TEST_STATE = MNL_AT_TEST_INPROGRESS;

+

+   if ((err = at_test2mnl_gps_start())) {

+       LOGE("at_test2mnl_gps_start err = %d", err);

+       MNL_AT_TEST_STATE = MNL_AT_TEST_UNKNOWN;

+       MNL_AT_TEST_FLAG = 0;

+       return -1;

+   }

+

+   // gps_state_test_start(s);

+   return 0;

+}

+

+int gpsinf_mtk_gps_test_inprogress() {

+   int ret = -1;

+

+   if ((MNL_AT_TEST_STATE == MNL_AT_TEST_DONE) || (MNL_AT_TEST_STATE == MNL_AT_TEST_RESULT_DONE)) {

+       LOGD("**AT Command test done!!");

+       ret = MNL_AT_TEST_DONE;

+   } else if (MNL_AT_TEST_STATE == MNL_AT_TEST_INPROGRESS) {

+       LOGD("**AT Command test is in progress!!");

+       ret = MNL_AT_TEST_INPROGRESS;

+   } else {

+       LOGD("**AT Command test status unknown!!");

+       ret = MNL_AT_TEST_UNKNOWN;

+   }

+   return ret;

+}

+

+void at_gps_command_parser(char* cmdline) {

+    char* command = cmdline;

+    test_mode_flag = 0;

+

+    if (!memcmp(command+6, "=", 1)) {

+        if ((!memcmp(command+7, "?", 1)) && (!memcmp(command+8, "\0", 1))) {

+               // AT%GPS=?

+            LOGD("** AT Command Parse: AT GPS=?**");

+            at_command_send_cno(command);

+        } else if (((!memcmp(command+7, "E", 1)) ||(!memcmp(command+7, "e", 1))) && (!memcmp(command+8, "\0", 1))) {

+               // AT%GPS=E

+            LOGD("Open AGPS raw data");

+        } else if (((!memcmp(command+7, "D", 1)) ||(!memcmp(command+7, "d", 1))) && (!memcmp(command+8, "\0", 1))) {

+               // AT%GNS=D

+        LOGD("Close AGPS raw data");

+        } else {

+               // AT%GPS=n

+            LOGD("** AT Command Parse: AT GPS=num**");

+            int test_num = at_command_parse_test_num(command);

+            if (test_num >= 0) {

+                int ret = gpsinf_mtk_gps_test_start(test_num, GPS_TEST_PRN, 2, 0);

+                if (0 == ret) {

+                    LOGD("** AT Command gps test start success **");

+                    char buff[] = "GPS TEST START OK";

+                    at_command_send_ack(buff, sizeof(buff));

+                } else {

+                    LOGD("** AT Command gps test start fail **");

+                    char buff[] = "GPS ERROR";

+                    at_command_send_ack(buff, sizeof(buff));

+                }

+            } else {

+                char buff[] = "Invalid Test Num =0";

+                at_command_send_ack(buff, sizeof(buff));

+            }

+        }

+    } else if (!memcmp(command+6, "?", 1) && (!memcmp(command+7, "\0", 1))) {

+           // AT%GPS?

+        LOGD("** AT Command Parse: AT GPS? **");

+        int ret = gpsinf_mtk_gps_test_inprogress();

+

+        if (MNL_AT_TEST_INPROGRESS == ret) {

+            LOGD("** AT Command test is inprogress **");

+            char buff[] = "GPS Test In Progress";

+            at_command_send_ack(buff, sizeof(buff));

+        } else if (MNL_AT_TEST_DONE == ret) {

+            LOGD("** AT Command test done");

+            char buff[GPS_AT_ACK_SIZE];

+            sprintf(buff, "<%d, %d, %d, %d, %d, %d, %d, %d>",

+                result[0], result[1],  result[2], result[3], result[4], result[5], result[6], result[7]);

+            at_command_send_ack(buff, sizeof(buff));

+        } else {

+            LOGD("** AT Command test status unknown");

+            char buff[] = "ERROR";

+            at_command_send_ack(buff, sizeof(buff));

+        }

+    } else if (!memcmp(command+6, "\0", 1)) {

+           // AT%GPS

+        LOGD("** AT Command Parse: AT GPS **");

+        at_command_send_cno(command);

+    } else {

+        LOGD("** AT Command Parse: illegal command **");

+        char buff[] = "GPS ERROR";

+        at_command_send_ack(buff, sizeof(buff));

+    }

+}

+

+void at_gnss_command_parser(char* cmdline) {

+    char* command = cmdline;

+    test_mode_flag = 0;

+

+    if (!memcmp(command+7, "=", 1)) {

+        if ((!memcmp(command+8, "?", 1)) && (!memcmp(command+9, "\0", 1))) {

+               // AT%GNSS=?

+            LOGD("** AT Command Parse: AT GNSS=?**");

+               // at_command_send_cno(command);

+            at_command_send_test_result();

+        } else if (((!memcmp(command+8, "S", 1)) || (!memcmp(command+8, "s", 1))) && (!memcmp(command+9, "\0", 1))) {

+            LOGD("AT GNSS=S is set!!");

+            int ret = 0;

+            if (0 == MNL_AT_TEST_FLAG) {

+                LOGD("Open GPS and set signal test mode");

+                ret = gpsinf_mtk_gps_test_start(0, 1, 2, 1);

+            } else {

+                LOGD("GPS driver is opened, change mode");

+                MNL_AT_SIGNAL_MODE = 1;

+                MNL_AT_TEST_FLAG = 0;

+                   // Cancel alarm if needed

+                if (0 == MNL_AT_CANCEL_ALARM) {

+                    LOGD("Cancel alarm!!");

+                    alarm(0);

+                    MNL_AT_CANCEL_ALARM = 0;

+                    MNL_AT_SET_ALARM = 0;

+                }

+            }

+

+            if (0 == ret) {

+                LOGD("** AT GNSS=S set success ! **");

+                char buff[] = "GNSS START START OK";

+                at_command_send_ack(buff, sizeof(buff));

+            } else {

+                LOGD("** AT GNSS=S set fail **");

+                char buff[] = "GNSS START START FAIL";

+                at_command_send_ack(buff, sizeof(buff));

+            }

+        } else if (((!memcmp(command+8, "E", 1)) || (!memcmp(command+8, "e", 1))) && (!memcmp(command+9, "\0", 1))) {

+            LOGD("AT GNSS=E is set, stop test!!");

+            if (MNL_AT_TEST_STATE == MNL_AT_TEST_UNKNOWN) {

+                LOGD("** MNL_AT_TEST_UNKNOWN **");

+            char buff[] = "GNSS Test is Not In Progress";

+            at_command_send_ack(buff, sizeof(buff));

+            } else {

+                   // if (MNL_AT_TEST_STATE != MNL_AT_TEST_UNKNOWN) {   // To avoid close gps driver many times

+                int ret = gpsinf_mtk_gps_test_stop();

+                if (0 == ret) {

+                    LOGD("** AT GNSS=E set success ! **");

+                    char buff[] = "GNSS TEST END OK";

+                    at_command_send_ack(buff, sizeof(buff));

+                } else {

+                    LOGD("** AT GNSS=E set fail **");

+                    char buff[] = "GNSS TEST END FAIL";

+                    at_command_send_ack(buff, sizeof(buff));

+                }

+                   // }

+            }

+        } else {

+            // AT%GNSS = n

+            LOGD("** AT Command Parse: AT GNSS=n**");

+            int test_num = at_command_parse_test_num(command);

+            // initialzation of result whenever starting test again.

+            memset(result, 0, sizeof(int)*8);

+            result[0] = 1;

+            Avg_CNo = 0;

+            Success_Num = 0;

+            Completed_Num = 0;

+            CNo = 0;

+            DCNo = 0;

+            Dev_CNo = 0;

+            cn = 0;

+            // initialzation of result whenever starting test again.

+

+            if (MNL_AT_SIGNAL_MODE == 1) {   // && (test_num != 0)) {

+                if (test_num <= 0) {

+                    char buff[] = "Invalid Test Num = 0";

+                    at_command_send_ack(buff, sizeof(buff));

+                    if (MNL_AT_TEST_STATE != MNL_AT_TEST_UNKNOWN)

+                        gpsinf_mtk_gps_test_stop();

+                } else {

+                    LOGD("MNL_AT_SIGNAL_MODE_BEGIN");

+                    MNL_AT_SIGNAL_TEST_BEGIN = 1;

+                    MNL_AT_TEST_STATE = MNL_AT_TEST_INPROGRESS;   //  Brian test

+                    char buff[] = "GNSS TEST START OK";

+                    at_command_send_ack(buff, sizeof(buff));

+                    time(&start_time);

+                }

+            } else {

+                if (test_num >= 0) {

+                    int ret = gpsinf_mtk_gps_test_start(test_num, GPS_TEST_PRN, 2, 0);

+                    if (0 == ret) {

+                        LOGD("** AT Command gps test start success **");

+                        char buff[] = "GNSS TEST START OK";

+                        at_command_send_ack(buff, sizeof(buff));

+                    } else {

+                        LOGD("** AT Command gps test start fail **");

+                        char buff[] = "GNSS ERROR";

+                        at_command_send_ack(buff, sizeof(buff));

+                    }

+                } else {

+                    char buff[] = "Invalid Test Num =0";

+                    at_command_send_ack(buff, sizeof(buff));

+                }

+            }

+        }

+    } else if (!memcmp(command+7, "?", 1) && (!memcmp(command+8, "\0", 1))) {

+        // AT%GNSS?

+        LOGD("** AT Command Parse: AT GNSS? **");

+        at_command_send_test_result();

+

+    } else if (!memcmp(command+7, "\0", 1)) {

+        // AT%GNSS

+        LOGD("** AT Command Parse: AT GNSS **");

+        at_command_send_cno(command);

+    } else {

+        LOGD("** AT Command Parse: illegal command **");

+        char buff[] = "GNSS ERROR";

+        at_command_send_ack(buff, sizeof(buff));

+    }

+}

+

+static void at_command_parser(char* cmdline) {

+    char* command = cmdline;

+    LOGD("** AT Command, receive command %s**", command);

+    /* begin to parse the command */

+    if (!memcmp(command, GPS_OP, 6)) {

+        at_gps_command_parser(command);

+    } else if (!memcmp(command, GNSS_OP, 7)) {

+        at_gnss_command_parser(command);

+    } else {

+        LOGD("** AT Command Parse: Not GPS/GNSS AT Command **");

+        char buff[] = "GPS ERROR";

+        at_command_send_ack(buff, sizeof(buff));

+    }

+}

+

+void at_command_send_ack(char* ack, int len) {

+    remotelen = sizeof(remote);

+    if (fd_at_test != 0) {

+        if (sendto(fd_at_test, ack, len, 0, (struct sockaddr*)&remote, remotelen) < 0) {

+            LOGD("** AT Command send ack to USB failed: %s**", strerror(errno));

+        } else {

+            LOGD("** AT Command send ack to USB sucess **");

+        }

+    }

+}

+

+void at_command_send_cno(char* cmdline) {

+    char* command = cmdline;

+

+    int ret = gpsinf_mtk_gps_test_inprogress();

+    if (MNL_AT_TEST_INPROGRESS == ret) {

+        LOGD("** AT Command test is inprogress **");

+        char buff[] = "GNSS Test In Progress";

+        at_command_send_ack(buff, sizeof(buff));

+        return;

+    }

+

+

+    if (MNL_AT_SIGNAL_MODE == 1) {

+        if (0 == cn) {

+        LOGD("** AT Command, cn is invalid **");

+        char buff[] = "0, NA";

+        at_command_send_ack(buff, sizeof(buff));

+        } else {

+        LOGD("** AT Command, CN is valid **");

+        char buff[32];

+           // sprintf(buff, "%d", Avg_CNo/10);    //  unit of AT%GNSS, AT%GNSS=? is 1dB

+        sprintf(buff, "%d", cn/10);

+        if (!memcmp(command, GNSS_OP, 7)) {

+            LOGD("** GNSS test, report CN and NA**");

+            int size = strlen(buff);

+            MNLD_STRNCPY(buff+size, ", NA",sizeof(buff)-size);

+            LOGD("** result = %s**", buff);

+        }

+        at_command_send_ack(buff, sizeof(buff));

+        }

+    } else {

+        if (0 == Avg_CNo) {

+        LOGD("** AT Command, cn is invalid **");

+        char buff[] = "0, NA";

+        at_command_send_ack(buff, sizeof(buff));

+        } else {

+        LOGD("** AT Command, CN is valid **");

+        char buff[32];

+        sprintf(buff, "%d", Avg_CNo/10);    //  unit of AT%GNSS, AT%GNSS=? is 1dB

+           // sprintf(buff, "%d", cn/10);

+                                if (!memcmp(command, GNSS_OP, 7)) {

+            LOGD("** GNSS test, report CN and NA**");

+            int size = strlen(buff);

+            MNLD_STRNCPY(buff+size, ", NA",sizeof(buff)-size);

+            LOGD("** result = %s**", buff);

+        }

+        at_command_send_ack(buff, sizeof(buff));

+        }

+    }

+}

+

+void at_command_send_test_result() {

+    int ret = gpsinf_mtk_gps_test_inprogress();

+    if (MNL_AT_TEST_INPROGRESS == ret) {

+        LOGD("** AT Command test is inprogress **");

+        char buff[] = "GNSS Test In Progress";

+        at_command_send_ack(buff, sizeof(buff));

+    } else if (MNL_AT_TEST_DONE == ret || MNL_AT_TEST_RESULT_DONE == ret) {

+        LOGD("** AT Command test done");

+        char buff[GPS_AT_ACK_SIZE];

+        sprintf(buff, "[%d, %d, %d, %d, %d, %d, %d, %d][0, 0, 0, 0, 0, 0, 0, 0]",

+        result[0], result[1],  result[2], result[3], result[4], result[5], result[6], result[7]);

+        at_command_send_ack(buff, sizeof(buff));

+    } else {

+        LOGD("** AT Command test status unknown");

+        if (result[0] !=0) {   // Brian test

+            char buff[GPS_AT_ACK_SIZE]={0};

+            LOGD("Normal: Return the result");

+            sprintf(buff, "[%d, %d, %d, %d, %d, %d, %d, %d][0, 0, 0, 0, 0, 0, 0, 0]",

+            result[0], result[1],  result[2], result[3], result[4], result[5], result[6], result[7]);

+            LOGD("** result =[%s] **\n", buff);

+            at_command_send_ack(buff, sizeof(buff));

+        } else if ((result[5] != 0) && (!(MNL_AT_SIGNAL_MODE || MNL_AT_SIGNAL_TEST_BEGIN))) {

+            LOGD("Normal: Return the result");

+            char buff[GPS_AT_ACK_SIZE]={0};

+            sprintf(buff, "[%d, %d, %d, %d, %d, %d, %d, %d][0, 0, 0, 0, 0, 0, 0, 0]",

+            result[0], result[1],  result[2], result[3], result[4], result[5], result[6], result[7]);

+            LOGD("** result =[%s] **\n", buff);

+            at_command_send_ack(buff, sizeof(buff));

+        } else {

+            char buff[] = "[0, 0, 0, 0, 0, 0, 0, 0][0, 0, 0, 0, 0, 0, 0, 0]";

+            at_command_send_ack(buff, sizeof(buff));

+        }

+    }

+}

+

+int at_command_parse_test_num(char* cmdline) {

+    unsigned long int res;

+    char* command = cmdline;

+    char** pos = (char**)malloc(sizeof(char)*strlen(command));

+

+    if (!memcmp(command, GNSS_OP, 7)) {

+           // AT%GNSS=n

+        res = strtoul(command+8, pos, 10);

+    } else {

+           // AT%GPS=n

+        res = strtoul(command+7, pos, 10);

+    }

+

+    if ((res != 0) && ((**pos) =='\0')) {

+        LOGD("** AT Command Parse: get test_num = %ld success!**", res);

+    } else {

+        LOGD("** AT Command Parse: the test num may incorrect**");

+        res = -1;

+    }

+

+    if (NULL != pos) {

+        LOGD("free pos!!");

+        free(pos);

+    }

+    return res;

+}

+

+void nmea_parser_at_cmd_pre(void) {

+    int time_diff;

+    time_t current_time;

+    static int prev_success_num = 0;

+

+    if ((1 == MNL_AT_TEST_FLAG) ||(1 == MNL_AT_SIGNAL_TEST_BEGIN)) {

+        // (1 == MNL_AT_SIGNAL_MODE)) {

+        LOGD("MNL_AT_TEST_FLAG = %d, MNL_AT_SIGNAL_TEST_BEGIN = %d", MNL_AT_TEST_FLAG, MNL_AT_SIGNAL_TEST_BEGIN);

+        time(&current_time);

+        time_diff = current_time - start_time;

+        if (time_diff >= hal_test_data.time_delay) {

+            LOGD("MNL_AT_SET_ALARM == 1, gps_nmea_end_tag(%d)", get_gps_nmea_parser_end_status());

+            if (get_gps_nmea_parser_end_status()) {

+                int test_stopped = 0;

+                LOGD("Success_Num = %d, Prev_Success_Num = %d, Wait_Num = %d, \

+                     Failure_Num = %d, Completed_Num = %d, Avg_CNo = %d, \

+                     Dev_CNo = %d, Err_Code = %d, MNL_AT_TEST_STATE = %d",

+                     Success_Num, prev_success_num, Wait_Num, Failure_Num, Completed_Num,

+                     Avg_CNo, Dev_CNo, Err_Code, MNL_AT_TEST_STATE);

+                if (Success_Num > 0) {

+                    if (prev_success_num == Success_Num) {

+                        Failure_Num++;

+                }

+                Completed_Num = Success_Num + Failure_Num;

+                if (Completed_Num == hal_test_data.test_num) {

+                    // 1. Call reportTestResult callback with detected SNR info

+                   // sms_airtest_no_signal_report(Err_Code, Success_Num, Completed_Num, Avg_CNo, Dev_CNo);

+                    // 2. Test Stop

+                    test_stopped = 1;

+                }

+             }

+                else {

+                    Wait_Num++;

+                    if (Wait_Num == MAX_VALID_STATUS_WAIT_COUNT) {

+                           // 1. Call reportTestResult callback with <32, 0, 0, 0, 0, 0>

+                        LOGD("TimeOut!! Wait_Num = %d", Wait_Num);

+                        Completed_Num = hal_test_data.test_num;

+                        Err_Code = (1 << 5);

+                        Completed_Num = 1;

+                       // sms_airtest_no_signal_report(Err_Code, Success_Num, Completed_Num, 0, 0);

+                           // 2. Test Stop

+                        test_stopped = 1;

+                    }

+                }

+                prev_success_num = Success_Num;

+

+                if (test_stopped == 1) {

+                    result[0] = Err_Code;

+                    result[3] = Success_Num;

+                    result[4] = Completed_Num;

+                    result[5] = Avg_CNo;

+                    result[6] = Dev_CNo;

+                    Wait_Num = 0;

+                    MNL_AT_TEST_STATE = MNL_AT_TEST_DONE;

+

+                    LOGD("**AT Command test_start done, Success_Num = %d, Completed_Num = %d, \

+                       Avg_CNo = %d, Dev_CNo = %d, Err_Code = %d, test_num = %d, MNL_AT_TEST_STATE = %d",

+                       Success_Num, Completed_Num, Avg_CNo, Dev_CNo, Err_Code, test_num, MNL_AT_TEST_STATE);

+                    Err_Code = 1;

+                    if ((MNL_AT_TEST_STATE == MNL_AT_TEST_DONE) && (1 == MNL_AT_TEST_FLAG)) {

+                        LOGD("** AT Command test done, stop GPS driver **");

+                        gpsinf_mtk_gps_test_stop();

+                        Failure_Num = 0;

+                        prev_success_num = 0;

+                    }

+                }

+            }

+

+        } else {    //  2sec waiting

+            LOGD("static time, return...");

+            return;

+        }

+    }

+}

+/*****************************************

+AT test -> MNL Testing

+*****************************************/

+// No use now

+static void

+gps_at_command_search_satellite(NmeaReader*  r) {

+    int i = 0, j = 0;

+    for (i = 0; i < r->sv_count; i++) {

+        if (prn[i] == hal_test_data.prn_num) {

+            LOGD("**AT Command test SvID: %d", prn[i]);

+            if (snr[i] != 0) {

+                if (MNL_AT_SIGNAL_MODE && (!MNL_AT_SIGNAL_TEST_BEGIN)) {

+                    LOGD("Set state to MNL_AT_TEST_INPROGRESS for read result");

+                    MNL_AT_TEST_STATE = MNL_AT_TEST_INPROGRESS;

+                }

+

+                if (MNL_AT_SIGNAL_MODE && MNL_AT_SIGNAL_TEST_BEGIN) {

+                    LOGD("Set state to MNL_AT_TEST_RESULT_DONE for read result");

+                    MNL_AT_TEST_STATE = MNL_AT_TEST_RESULT_DONE;

+                    sig_suc_num = 1;

+                       // sig_com_num = 1;

+                }

+

+                if (MNL_AT_TEST_FLAG) {

+                    Err_Code = 0;

+                    LOGD("cn = %d", cn);

+                    CNo += snr[i]*10;

+                    Dev_CNr[Success_Num] = snr[i]*10;

+                    Success_Num++;

+                    Avg_CNo = CNo / Success_Num;

+                       // test_num++;

+                    LOGD("CNo = %d, Avg_CNo /= %d, Success_Num = %d", CNo, Avg_CNo, Success_Num);

+                }

+                cn = snr[i]*10;

+                LOGD("cn = %d", cn);

+            } else {

+                LOGD("**SNR is 0, ignore!!!");

+                if (MNL_AT_CANCEL_ALARM == 1) {    // It's not timeout, just no signal after 12s

+                    if (MNL_AT_TEST_FLAG == 1)

+                        test_num++;

+                }

+                sig_suc_num = 0;

+            }

+

+            if (Success_Num != 0) {

+                for (j = 0; j < Success_Num; j++) {

+                    DCNo += (Dev_CNr[j]-Avg_CNo) * (Dev_CNr[j]-Avg_CNo);

+                    LOGD("Dev_CNr[%d] = %d, Dev_CNo2 += %d", j, Dev_CNr[j], DCNo);

+                }

+                Dev_CNo = DCNo / Success_Num;

+                DCNo = 0;

+                Dev_CNo = sqrt(Dev_CNo);

+            }

+            LOGD("**AT Command find SvID: %d, exit", prn[i]);

+            break;

+        } else {

+            LOGD("**AT Command ignore SvID: %d", prn[i]);

+        }

+    }

+}

+

+void

+gps_at_command_test_proc(NmeaReader* const r) {

+       // For AT command test

+

+    if (MNL_AT_TEST_STATE != MNL_AT_TEST_DONE) {

+        LOGD("**AT Command test mode!!");

+

+        if (MNL_AT_SIGNAL_MODE == 1) {

+            if (MNL_AT_SIGNAL_TEST_BEGIN) {

+                gps_at_command_search_satellite(r);

+                LOGD("Update test result per second");

+                result[0] = 0;

+                result[3] = sig_suc_num;

+                result[4] = 1;

+                result[5]= cn;

+                LOGD("result[5] = %d", result[5]);

+                result[6] = 0;

+            } else {

+                LOGD("Wait AT GNSS=1...");

+                return;

+            }

+        } else {

+            LOGD("Not in MNL_AT_SIGNAL_MODE");

+                LOGD("**AT Command Continue, search satellites...");

+                   // Search satellites

+                gps_at_command_search_satellite(r);

+        }

+

+    } else {

+        LOGD("**AT Command test, test mode is MNL_AT_TEST_DONE");

+    }

+}

+

+void at_cmd2mnl_hdlr(int fd) {

+    char cmd[20];

+

+    fd_at_test = fd;

+    LOGD("** AT Command received **");

+    /* receive and parse ATCM here */

+    for (;;) {

+        int ret;

+

+        remotelen = sizeof(remote);

+        ret = recvfrom(fd, cmd, sizeof(cmd), 0, (struct sockaddr *)&remote, &remotelen);

+        if (ret < 0) {

+            if (errno == EINTR)

+                continue;

+            if (errno != EWOULDBLOCK)

+                LOGE("error while reading AT Command socket: %s: %p", strerror(errno), cmd);

+            break;

+        }

+        LOGD("received %d bytes: %d.%s", ret, ret, cmd);

+        cmd[ret] = 0x00;

+        at_command_parser(cmd);                // need redefine

+    }

+    LOGD("** AT Command event done **");

+}

+

+int create_at2mnl_fd() {

+    int fd = socket_bind_udp(GPS_AT_COMMAND_SOCK);

+    socket_set_blocking(fd, 0);

+    return fd;

+}

diff --git a/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h
new file mode 100644
index 0000000..e51b36c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Debug2MnldInterface.h
@@ -0,0 +1,60 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Debug2MnldInterface_H__
+#define __Debug2MnldInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE 305
+#define DEBUG2MNLD_INTERFACE_BUFF_SIZE 12
+
+/**
+ * The interface from Debug to Mnld
+ */
+typedef enum {
+    DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG = 0,
+} Debug2MnldInterface_message_id;
+
+
+typedef enum {
+    DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG = 0,
+    DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG = 1,
+    DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_END = 2147483647,
+} Debug2MnldInterface_DebugReqStatusCategory;
+
+
+// Debug2MnldInterface_DebugReqStatusCategory
+const char* Debug2MnldInterface_DebugReqStatusCategory_to_string(Debug2MnldInterface_DebugReqStatusCategory data);
+void Debug2MnldInterface_DebugReqStatusCategory_array_dump(Debug2MnldInterface_DebugReqStatusCategory data[], int size);
+
+void Debug2MnldInterface_DebugReqStatusCategory_array_init(Debug2MnldInterface_DebugReqStatusCategory output[], int max_size);
+
+bool Debug2MnldInterface_DebugReqStatusCategory_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1, Debug2MnldInterface_DebugReqStatusCategory data2);
+bool Debug2MnldInterface_DebugReqStatusCategory_array_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1[], int size1, Debug2MnldInterface_DebugReqStatusCategory data2[], int size2);
+
+bool Debug2MnldInterface_DebugReqStatusCategory_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data);
+bool Debug2MnldInterface_DebugReqStatusCategory_array_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data[], int size);
+
+void Debug2MnldInterface_DebugReqStatusCategory_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory* output);
+int Debug2MnldInterface_DebugReqStatusCategory_array_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory output[], int max_size);
+
+// Sender
+bool Debug2MnldInterface_debugReqMnldMsg(mtk_socket_fd* client_fd, Debug2MnldInterface_DebugReqStatusCategory status);
+
+// Receiver
+typedef struct {
+    void (*Debug2MnldInterface_debugReqMnldMsg_handler) (Debug2MnldInterface_DebugReqStatusCategory status);
+} Debug2MnldInterface_callbacks;
+
+bool Debug2MnldInterface_receiver_decode(char* _buff, Debug2MnldInterface_callbacks* callbacks);
+bool Debug2MnldInterface_receiver_read_and_decode(int server_fd, Debug2MnldInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h
new file mode 100644
index 0000000..21acd06
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/inc/Mnld2DebugInterface.h
@@ -0,0 +1,72 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Mnld2DebugInterface_H__
+#define __Mnld2DebugInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE 304
+#define MNLD2DEBUG_INTERFACE_BUFF_SIZE 269
+
+/**
+ * The interface from Mnld to Debug
+ */
+typedef enum {
+    MNLD2DEBUG_INTERFACE_MNLD_ACK_DEBUG_REQ = 0,
+    MNLD2DEBUG_INTERFACE_MNLD_UPDATE_REBOOT = 1,
+    MNLD2DEBUG_INTERFACE_MNLD_UPDATE_GPS_STATUS = 2,
+    MNLD2DEBUG_INTERFACE_MNLD_UPDATE_MESSAGE_INFO = 3,
+} Mnld2DebugInterface_message_id;
+
+
+typedef enum {
+    MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED = 0,
+    MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED = 1,
+    MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_END = 2147483647,
+} Mnld2DebugInterface_MnldGpsStatusCategory;
+
+
+// Mnld2DebugInterface_MnldGpsStatusCategory
+const char* Mnld2DebugInterface_MnldGpsStatusCategory_to_string(Mnld2DebugInterface_MnldGpsStatusCategory data);
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_dump(Mnld2DebugInterface_MnldGpsStatusCategory data[], int size);
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_init(Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size);
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1, Mnld2DebugInterface_MnldGpsStatusCategory data2);
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1[], int size1, Mnld2DebugInterface_MnldGpsStatusCategory data2[], int size2);
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data);
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data[], int size);
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory* output);
+int Mnld2DebugInterface_MnldGpsStatusCategory_array_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size);
+
+// Sender
+bool Mnld2DebugInterface_mnldAckDebugReq(mtk_socket_fd* client_fd);
+
+bool Mnld2DebugInterface_mnldUpdateReboot(mtk_socket_fd* client_fd);
+
+bool Mnld2DebugInterface_mnldUpdateGpsStatus(mtk_socket_fd* client_fd, Mnld2DebugInterface_MnldGpsStatusCategory status);
+
+bool Mnld2DebugInterface_mnldUpdateMessageInfo(mtk_socket_fd* client_fd, char* msg);
+
+// Receiver
+typedef struct {
+    void (*Mnld2DebugInterface_mnldAckDebugReq_handler) ();
+    void (*Mnld2DebugInterface_mnldUpdateReboot_handler) ();
+    void (*Mnld2DebugInterface_mnldUpdateGpsStatus_handler) (Mnld2DebugInterface_MnldGpsStatusCategory status);
+    void (*Mnld2DebugInterface_mnldUpdateMessageInfo_handler) (char* msg);
+} Mnld2DebugInterface_callbacks;
+
+bool Mnld2DebugInterface_receiver_decode(char* _buff, Mnld2DebugInterface_callbacks* callbacks);
+bool Mnld2DebugInterface_receiver_read_and_decode(int server_fd, Mnld2DebugInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c
new file mode 100644
index 0000000..ea8d783
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Debug2MnldInterface.c
@@ -0,0 +1,167 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Debug2MnldInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Debug2MnldInterface_DebugReqStatusCategory
+const char* Debug2MnldInterface_DebugReqStatusCategory_to_string(Debug2MnldInterface_DebugReqStatusCategory data) {
+    switch(data) {
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG:
+        return "stopDebug";
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG:
+        return "startDebug";
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_END:
+        return "end";
+    default:
+        break;
+    }
+    return "UNKNOWN";
+}
+void Debug2MnldInterface_DebugReqStatusCategory_array_dump(Debug2MnldInterface_DebugReqStatusCategory data[], int size) {
+    int i = 0;
+    LOGD("Debug2MnldInterface_DebugReqStatusCategory_array_dump() size=[%d]", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%s]", i, Debug2MnldInterface_DebugReqStatusCategory_to_string(data[i]));
+    }
+}
+
+void Debug2MnldInterface_DebugReqStatusCategory_array_init(Debug2MnldInterface_DebugReqStatusCategory output[], int max_size) {
+    int i = 0;
+    for(i = 0; i < max_size; i++) {
+        output[i] = DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG;
+    }
+}
+
+bool Debug2MnldInterface_DebugReqStatusCategory_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1, Debug2MnldInterface_DebugReqStatusCategory data2) {
+    return (data1 == data2)? true : false;
+}
+bool Debug2MnldInterface_DebugReqStatusCategory_array_is_equal(Debug2MnldInterface_DebugReqStatusCategory data1[], int size1, Debug2MnldInterface_DebugReqStatusCategory data2[], int size2) {
+    int i = 0;
+    if(size1 != size2) return false;
+    for(i = 0; i < size1; i++) {
+        if(data1[i] != data2[i]) return false;
+    }
+    return true;
+}
+
+bool Debug2MnldInterface_DebugReqStatusCategory_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data) {
+    switch(data) {
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG:
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG:
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_END:
+        break;
+    default:
+        LOGE("Debug2MnldInterface_DebugReqStatusCategory_encode() unknown data=%d", data);
+        return false;
+    }
+    mtk_socket_put_int(buff, offset, data);
+    return true;
+}
+bool Debug2MnldInterface_DebugReqStatusCategory_array_encode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory data[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        if(!Debug2MnldInterface_DebugReqStatusCategory_encode(buff, offset, data[i])) {
+            LOGE("Debug2MnldInterface_DebugReqStatusCategory_array_encode() Debug2MnldInterface_DebugReqStatusCategory_encode() failed at i=%d", i);
+            return false;
+        }
+    }
+    return true;
+}
+
+void Debug2MnldInterface_DebugReqStatusCategory_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory* output) {
+    *output = mtk_socket_get_int(buff, offset);
+}
+int Debug2MnldInterface_DebugReqStatusCategory_array_decode(char* buff, int* offset, Debug2MnldInterface_DebugReqStatusCategory output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        if(i < max_size) {
+            Debug2MnldInterface_DebugReqStatusCategory_decode(buff, offset, &output[i]);
+        } else {
+            Debug2MnldInterface_DebugReqStatusCategory data;
+            Debug2MnldInterface_DebugReqStatusCategory_decode(buff, offset, &data);
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+
+// Sender
+bool Debug2MnldInterface_debugReqMnldMsg(mtk_socket_fd* client_fd, Debug2MnldInterface_DebugReqStatusCategory status) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Debug2MnldInterface_debugReqMnldMsg() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[DEBUG2MNLD_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG);
+    if(!Debug2MnldInterface_DebugReqStatusCategory_encode(_buff, &_offset, status)) {
+        LOGE("Debug2MnldInterface_debugReqMnldMsg() Debug2MnldInterface_DebugReqStatusCategory_encode() fail on status");
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Debug2MnldInterface_debugReqMnldMsg() mtk_socket_write() failed, fd=%p err=[%s]%d", 
+            client_fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+// Receiver
+bool Debug2MnldInterface_receiver_decode(char* _buff, Debug2MnldInterface_callbacks* callbacks) {
+    int _ret = 0;
+    int _offset = 0;
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    if(_ret != DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE) {
+        LOGE("Debug2MnldInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+            _ret, DEBUG2MNLD_INTERFACE_PROTOCOL_TYPE);
+        return false;
+    }
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    switch(_ret) {
+    case DEBUG2MNLD_INTERFACE_DEBUG_REQ_MNLD_MSG: {
+        if(callbacks->Debug2MnldInterface_debugReqMnldMsg_handler == NULL) {
+            LOGE("Debug2MnldInterface_receiver_decode() Debug2MnldInterface_debugReqMnldMsg_handler() is NULL");
+            return false;
+        }
+        Debug2MnldInterface_DebugReqStatusCategory status;
+        Debug2MnldInterface_DebugReqStatusCategory_decode(_buff, &_offset, &status);
+        callbacks->Debug2MnldInterface_debugReqMnldMsg_handler(status);
+        break;
+    }
+    default: {
+        LOGE("Debug2MnldInterface_receiver_decode() unknown msgId=[%d]", _ret);
+        return false;
+    }
+    }
+    return true;
+}
+bool Debug2MnldInterface_receiver_read_and_decode(int server_fd, Debug2MnldInterface_callbacks* callbacks) {
+    int _ret;
+    char _buff[DEBUG2MNLD_INTERFACE_BUFF_SIZE] = {0};
+
+    _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+    if(_ret == -1) {
+        LOGE("Debug2MnldInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d", 
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return Debug2MnldInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c
new file mode 100644
index 0000000..e721279
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_debug_interface/src/Mnld2DebugInterface.c
@@ -0,0 +1,276 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Mnld2DebugInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Mnld2DebugInterface_MnldGpsStatusCategory
+const char* Mnld2DebugInterface_MnldGpsStatusCategory_to_string(Mnld2DebugInterface_MnldGpsStatusCategory data) {
+    switch(data) {
+    case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED:
+        return "gpsStopped";
+    case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED:
+        return "gpsStarted";
+    case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_END:
+        return "end";
+    default:
+        break;
+    }
+    return "UNKNOWN";
+}
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_dump(Mnld2DebugInterface_MnldGpsStatusCategory data[], int size) {
+    int i = 0;
+    LOGD("Mnld2DebugInterface_MnldGpsStatusCategory_array_dump() size=[%d]", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%s]", i, Mnld2DebugInterface_MnldGpsStatusCategory_to_string(data[i]));
+    }
+}
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_array_init(Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size) {
+    int i = 0;
+    for(i = 0; i < max_size; i++) {
+        output[i] = MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED;
+    }
+}
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1, Mnld2DebugInterface_MnldGpsStatusCategory data2) {
+    return (data1 == data2)? true : false;
+}
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_is_equal(Mnld2DebugInterface_MnldGpsStatusCategory data1[], int size1, Mnld2DebugInterface_MnldGpsStatusCategory data2[], int size2) {
+    int i = 0;
+    if(size1 != size2) return false;
+    for(i = 0; i < size1; i++) {
+        if(data1[i] != data2[i]) return false;
+    }
+    return true;
+}
+
+bool Mnld2DebugInterface_MnldGpsStatusCategory_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data) {
+    switch(data) {
+    case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED:
+    case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED:
+    case MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_END:
+        break;
+    default:
+        LOGE("Mnld2DebugInterface_MnldGpsStatusCategory_encode() unknown data=%d", data);
+        return false;
+    }
+    mtk_socket_put_int(buff, offset, data);
+    return true;
+}
+bool Mnld2DebugInterface_MnldGpsStatusCategory_array_encode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory data[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        if(!Mnld2DebugInterface_MnldGpsStatusCategory_encode(buff, offset, data[i])) {
+            LOGE("Mnld2DebugInterface_MnldGpsStatusCategory_array_encode() Mnld2DebugInterface_MnldGpsStatusCategory_encode() failed at i=%d", i);
+            return false;
+        }
+    }
+    return true;
+}
+
+void Mnld2DebugInterface_MnldGpsStatusCategory_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory* output) {
+    *output = mtk_socket_get_int(buff, offset);
+}
+int Mnld2DebugInterface_MnldGpsStatusCategory_array_decode(char* buff, int* offset, Mnld2DebugInterface_MnldGpsStatusCategory output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        if(i < max_size) {
+            Mnld2DebugInterface_MnldGpsStatusCategory_decode(buff, offset, &output[i]);
+        } else {
+            Mnld2DebugInterface_MnldGpsStatusCategory data;
+            Mnld2DebugInterface_MnldGpsStatusCategory_decode(buff, offset, &data);
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+
+// Sender
+bool Mnld2DebugInterface_mnldAckDebugReq(mtk_socket_fd* client_fd) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Mnld2DebugInterface_mnldAckDebugReq() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_ACK_DEBUG_REQ);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Mnld2DebugInterface_mnldAckDebugReq() mtk_socket_write() failed, err=[%s]%d", 
+            strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool Mnld2DebugInterface_mnldUpdateReboot(mtk_socket_fd* client_fd) {
+    LOGE("Mnld2DebugInterface_mnldUpdateReboot");
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Mnld2DebugInterface_mnldUpdateReboot() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_UPDATE_REBOOT);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Mnld2DebugInterface_mnldUpdateReboot() mtk_socket_write() failed, err=[%s]%d", 
+            strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool Mnld2DebugInterface_mnldUpdateGpsStatus(mtk_socket_fd* client_fd, Mnld2DebugInterface_MnldGpsStatusCategory status) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_UPDATE_GPS_STATUS);
+    if(!Mnld2DebugInterface_MnldGpsStatusCategory_encode(_buff, &_offset, status)) {
+        LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() Mnld2DebugInterface_MnldGpsStatusCategory_encode() fail on status");
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Mnld2DebugInterface_mnldUpdateGpsStatus() mtk_socket_write() failed, err=[%s]%d", 
+            strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool Mnld2DebugInterface_mnldUpdateMessageInfo(mtk_socket_fd* client_fd, char* msg) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, MNLD2DEBUG_INTERFACE_MNLD_UPDATE_MESSAGE_INFO);
+    if(strlen(msg) > 256) {
+        LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() strlen of msg=[%d] is over 256", strlen(msg));
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_put_string(_buff, &_offset, msg);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Mnld2DebugInterface_mnldUpdateMessageInfo() mtk_socket_write() failed, err=[%s]%d", 
+            strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+// Receiver
+bool Mnld2DebugInterface_receiver_decode(char* _buff, Mnld2DebugInterface_callbacks* callbacks) {
+    int _ret = 0;
+    int _offset = 0;
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    if(_ret != MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE) {
+        LOGE("Mnld2DebugInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+            _ret, MNLD2DEBUG_INTERFACE_PROTOCOL_TYPE);
+        return false;
+    }
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    switch(_ret) {
+    case MNLD2DEBUG_INTERFACE_MNLD_ACK_DEBUG_REQ: {
+        if(callbacks->Mnld2DebugInterface_mnldAckDebugReq_handler == NULL) {
+            LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldAckDebugReq_handler() is NULL");
+            return false;
+        }
+        callbacks->Mnld2DebugInterface_mnldAckDebugReq_handler();
+        break;
+    }
+    case MNLD2DEBUG_INTERFACE_MNLD_UPDATE_REBOOT: {
+        if(callbacks->Mnld2DebugInterface_mnldUpdateReboot_handler == NULL) {
+            LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldUpdateReboot_handler() is NULL");
+            return false;
+        }
+        callbacks->Mnld2DebugInterface_mnldUpdateReboot_handler();
+        break;
+    }
+    case MNLD2DEBUG_INTERFACE_MNLD_UPDATE_GPS_STATUS: {
+        if(callbacks->Mnld2DebugInterface_mnldUpdateGpsStatus_handler == NULL) {
+            LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldUpdateGpsStatus_handler() is NULL");
+            return false;
+        }
+        Mnld2DebugInterface_MnldGpsStatusCategory status;
+        Mnld2DebugInterface_MnldGpsStatusCategory_decode(_buff, &_offset, &status);
+        callbacks->Mnld2DebugInterface_mnldUpdateGpsStatus_handler(status);
+        break;
+    }
+    case MNLD2DEBUG_INTERFACE_MNLD_UPDATE_MESSAGE_INFO: {
+        if(callbacks->Mnld2DebugInterface_mnldUpdateMessageInfo_handler == NULL) {
+            LOGE("Mnld2DebugInterface_receiver_decode() Mnld2DebugInterface_mnldUpdateMessageInfo_handler() is NULL");
+            return false;
+        }
+        char msg[256];
+        mtk_socket_get_string(_buff, &_offset, msg, 256);
+        callbacks->Mnld2DebugInterface_mnldUpdateMessageInfo_handler(msg);
+        break;
+    }
+    default: {
+        LOGE("Mnld2DebugInterface_receiver_decode() unknown msgId=[%d]", _ret);
+        return false;
+    }
+    }
+    return true;
+}
+bool Mnld2DebugInterface_receiver_read_and_decode(int server_fd, Mnld2DebugInterface_callbacks* callbacks) {
+    int _ret;
+    char _buff[MNLD2DEBUG_INTERFACE_BUFF_SIZE] = {0};
+
+    _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+    if(_ret == -1) {
+        LOGE("Mnld2DebugInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d", 
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return Mnld2DebugInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/fused_location.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/fused_location.h
new file mode 100644
index 0000000..a5e59ca
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/fused_location.h
@@ -0,0 +1,826 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H
+#define ANDROID_INCLUDE_HARDWARE_FUSED_LOCATION_H
+
+#if defined(__ANDROID_OS__)
+#include <hardware/hardware.h>
+#include "gnss-base.h"
+#endif
+
+/**
+ * This header file defines the interface of the Fused Location Provider.
+ * Fused Location Provider is designed to fuse data from various sources
+ * like GPS, Wifi, Cell, Sensors, Bluetooth etc to provide a fused location to the
+ * upper layers. The advantage of doing fusion in hardware is power savings.
+ * The goal is to do this without waking up the AP to get additional data.
+ * The software implementation of FLP will decide when to use
+ * the hardware fused location. Other location features like geofencing will
+ * also be implemented using fusion in hardware.
+ */
+__BEGIN_DECLS
+
+#define FLP_HEADER_VERSION          1
+#define FLP_MODULE_API_VERSION_0_1  HARDWARE_MODULE_API_VERSION(0, 1)
+#define FLP_DEVICE_API_VERSION_0_1  HARDWARE_DEVICE_API_VERSION_2(0, 1, FLP_HEADER_VERSION)
+
+/**
+ * The id of this module
+ */
+#define FUSED_LOCATION_HARDWARE_MODULE_ID "flp"
+
+/**
+ * Name for the FLP location interface
+ */
+#define FLP_LOCATION_INTERFACE     "flp_location"
+
+/**
+ * Name for the FLP location interface
+ */
+#define FLP_DIAGNOSTIC_INTERFACE     "flp_diagnostic"
+
+/**
+ * Name for the FLP_Geofencing interface.
+ */
+#define FLP_GEOFENCING_INTERFACE   "flp_geofencing"
+
+/**
+ * Name for the FLP_device context interface.
+ */
+#define FLP_DEVICE_CONTEXT_INTERFACE   "flp_device_context"
+
+/**
+ * Constants to indicate the various subsystems
+ * that will be used.
+ */
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define FLP_TECH_MASK_WIFI      (1U<<1)
+#define FLP_TECH_MASK_SENSORS   (1U<<2)
+#define FLP_TECH_MASK_CELL      (1U<<3)
+#define FLP_TECH_MASK_BLUETOOTH (1U<<4)
+
+/**
+ * Set when your implementation can produce GNNS-derived locations,
+ * for use with flp_capabilities_callback.
+ *
+ * GNNS is a required capability for a particular feature to be used
+ * (batching or geofencing).  If not supported that particular feature
+ * won't be used by the upper layer.
+ */
+#define CAPABILITY_GNSS         (1U<<0)
+/**
+ * Set when your implementation can produce WiFi-derived locations, for
+ * use with flp_capabilities_callback.
+ */
+#define CAPABILITY_WIFI         (1U<<1)
+/**
+ * Set when your implementation can produce cell-derived locations, for
+ * use with flp_capabilities_callback.
+ */
+#define CAPABILITY_CELL         (1U<<3)
+
+/**
+ * Status to return in flp_status_callback when your implementation transitions
+ * from being unsuccessful in determining location to being successful.
+ */
+#define FLP_STATUS_LOCATION_AVAILABLE         0
+/**
+ * Status to return in flp_status_callback when your implementation transitions
+ * from being successful in determining location to being unsuccessful.
+ */
+#define FLP_STATUS_LOCATION_UNAVAILABLE       1
+
+/**
+ * While batching, the implementation should not call the
+ * flp_location_callback on every location fix. However,
+ * sometimes in high power mode, the system might need
+ * a location callback every single time the location
+ * fix has been obtained. This flag controls that option.
+ * Its the responsibility of the upper layers (caller) to switch
+ * it off, if it knows that the AP might go to sleep.
+ * When this bit is on amidst a batching session, batching should
+ * continue while location fixes are reported in real time.
+ */
+#define FLP_BATCH_CALLBACK_ON_LOCATION_FIX   0x0000002
+
+/** Flags to indicate which values are valid in a FlpLocation. */
+typedef uint16_t FlpLocationFlags;
+
+// IMPORTANT: Note that the following values must match
+// constants in the corresponding java file.
+
+/** FlpLocation has valid latitude and longitude. */
+#define FLP_LOCATION_HAS_LAT_LONG   (1U<<0)
+/** FlpLocation has valid altitude. */
+#define FLP_LOCATION_HAS_ALTITUDE   (1U<<1)
+/** FlpLocation has valid speed. */
+#define FLP_LOCATION_HAS_SPEED      (1U<<2)
+/** FlpLocation has valid bearing. */
+#define FLP_LOCATION_HAS_BEARING    (1U<<4)
+/** FlpLocation has valid accuracy. */
+#define FLP_LOCATION_HAS_ACCURACY   (1U<<8)
+
+
+typedef int64_t FlpUtcTime;
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(FlpLocation) */
+    size_t          size;
+
+    /** Flags associated with the location object. */
+    FlpLocationFlags flags;
+
+    /** Represents latitude in degrees. */
+    double          latitude;
+
+    /** Represents longitude in degrees. */
+    double          longitude;
+
+    /**
+     * Represents altitude in meters above the WGS 84 reference
+     * ellipsoid. */
+    double          altitude;
+
+    /** Represents speed in meters per second. */
+    float           speed;
+
+    /** Represents heading in degrees. */
+    float           bearing;
+
+    /** Represents expected accuracy in meters. */
+    float           accuracy;
+
+    /** Timestamp for the location fix. */
+    FlpUtcTime      timestamp;
+
+    /** Sources used, will be Bitwise OR of the FLP_TECH_MASK bits. */
+    uint32_t         sources_used;
+} FlpLocation;
+
+typedef enum {
+    ASSOCIATE_JVM,
+    DISASSOCIATE_JVM,
+} ThreadEvent;
+
+/**
+ *  Callback with location information.
+ *  Can only be called from a thread associated to JVM using set_thread_event_cb.
+ *  Parameters:
+ *     num_locations is the number of batched locations available.
+ *     location is the pointer to an array of pointers to location objects.
+ */
+typedef void (*flp_location_callback)(int32_t num_locations, FlpLocation** location);
+
+/**
+ * Callback utility for acquiring a wakelock.
+ * This can be used to prevent the CPU from suspending while handling FLP events.
+ */
+typedef void (*flp_acquire_wakelock)();
+
+/**
+ * Callback utility for releasing the FLP wakelock.
+ */
+typedef void (*flp_release_wakelock)();
+
+/**
+ * Callback for associating a thread that can call into the Java framework code.
+ * This must be used to initialize any threads that report events up to the framework.
+ * Return value:
+ *      FLP_RESULT_SUCCESS on success.
+ *      FLP_RESULT_ERROR if the association failed in the current thread.
+ */
+typedef int (*flp_set_thread_event)(ThreadEvent event);
+
+/**
+ * Callback for technologies supported by this implementation.
+ *
+ * Parameters: capabilities is a bitmask of FLP_CAPABILITY_* values describing
+ * which features your implementation supports.  You should support
+ * CAPABILITY_GNSS at a minimum for your implementation to be utilized.  You can
+ * return 0 in FlpGeofenceCallbacks to indicate you don't support geofencing,
+ * or 0 in FlpCallbacks to indicate you don't support location batching.
+ */
+typedef void (*flp_capabilities_callback)(int capabilities);
+
+/**
+ * Callback with status information on the ability to compute location.
+ * To avoid waking up the application processor you should only send
+ * changes in status (you shouldn't call this method twice in a row
+ * with the same status value).  As a guideline you should not call this
+ * more frequently then the requested batch period set with period_ns
+ * in FlpBatchOptions.  For example if period_ns is set to 5 minutes and
+ * the status changes many times in that interval, you should only report
+ * one status change every 5 minutes.
+ *
+ * Parameters:
+ *     status is one of FLP_STATUS_LOCATION_AVAILABLE
+ *     or FLP_STATUS_LOCATION_UNAVAILABLE.
+ */
+typedef void (*flp_status_callback)(int32_t status);
+
+/** FLP callback structure. */
+typedef struct {
+    /** set to sizeof(FlpCallbacks) */
+    size_t      size;
+    flp_location_callback location_cb;
+    flp_acquire_wakelock acquire_wakelock_cb;
+    flp_release_wakelock release_wakelock_cb;
+    flp_set_thread_event set_thread_event_cb;
+    flp_capabilities_callback flp_capabilities_cb;
+    flp_status_callback flp_status_cb;
+} FlpCallbacks;
+
+
+/** Options with the batching FLP APIs */
+typedef struct {
+    /**
+     * Maximum power in mW that the underlying implementation
+     * can use for this batching call.
+     * If max_power_allocation_mW is 0, only fixes that are generated
+     * at no additional cost of power shall be reported.
+     */
+    double max_power_allocation_mW;
+
+    /** Bitwise OR of the FLP_TECH_MASKS to use */
+    uint32_t sources_to_use;
+
+    /**
+     * FLP_BATCH_WAKEUP_ON_FIFO_FULL - If set the hardware
+     * will wake up the AP when the buffer is full. If not set, the
+     * hardware will drop the oldest location object.
+     *
+     * FLP_BATCH_CALLBACK_ON_LOCATION_FIX - If set the location
+     * callback will be called every time there is a location fix.
+     * Its the responsibility of the upper layers (caller) to switch
+     * it off, if it knows that the AP might go to sleep. When this
+     * bit is on amidst a batching session, batching should continue
+     * while location fixes are reported in real time.
+     *
+     * Other flags to be bitwised ORed in the future.
+     */
+    uint32_t flags;
+
+    /**
+     * Frequency with which location needs to be batched in nano
+     * seconds.
+     */
+    int64_t period_ns;
+
+    /**
+     * The smallest displacement between reported locations in meters.
+     *
+     * If set to 0, then you should report locations at the requested
+     * interval even if the device is stationary.  If positive, you
+     * can use this parameter as a hint to save power (e.g. throttling
+     * location period if the user hasn't traveled close to the displacement
+     * threshold).  Even small positive values can be interpreted to mean
+     * that you don't have to compute location when the device is stationary.
+     *
+     * There is no need to filter location delivery based on this parameter.
+     * Locations can be delivered even if they have a displacement smaller than
+     * requested. This parameter can safely be ignored at the cost of potential
+     * power savings.
+     */
+    float smallest_displacement_meters;
+} FlpBatchOptions;
+
+#define FLP_RESULT_SUCCESS                       0
+#define FLP_RESULT_ERROR                        -1
+#define FLP_RESULT_INSUFFICIENT_MEMORY          -2
+#define FLP_RESULT_TOO_MANY_GEOFENCES           -3
+#define FLP_RESULT_ID_EXISTS                    -4
+#define FLP_RESULT_ID_UNKNOWN                   -5
+#define FLP_RESULT_INVALID_GEOFENCE_TRANSITION  -6
+
+/**
+ * Represents the standard FLP interface.
+ */
+typedef struct {
+    /**
+     * set to sizeof(FlpLocationInterface)
+     */
+    size_t size;
+
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.  Once called you should respond
+     * by calling the flp_capabilities_callback in FlpCallbacks to
+     * specify the capabilities that your implementation supports.
+     */
+    int (*init)(FlpCallbacks* callbacks );
+
+    /**
+     * Return the batch size (in number of FlpLocation objects)
+     * available in the hardware.  Note, different HW implementations
+     * may have different sample sizes.  This shall return number
+     * of samples defined in the format of FlpLocation.
+     * This will be used by the upper layer, to decide on the batching
+     * interval and whether the AP should be woken up or not.
+     */
+    int (*get_batch_size)();
+
+    /**
+     * Start batching locations. This API is primarily used when the AP is
+     * asleep and the device can batch locations in the hardware.
+     *   flp_location_callback is used to return the locations. When the buffer
+     * is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is used, the AP is woken up.
+     * When the buffer is full and FLP_BATCH_WAKEUP_ON_FIFO_FULL is not set,
+     * the oldest location object is dropped. In this case the  AP will not be
+     * woken up. The upper layer will use get_batched_location
+     * API to explicitly ask for the location.
+     *   If FLP_BATCH_CALLBACK_ON_LOCATION_FIX is set, the implementation
+     * will call the flp_location_callback every single time there is a location
+     * fix. This overrides FLP_BATCH_WAKEUP_ON_FIFO_FULL flag setting.
+     * It's the responsibility of the upper layers (caller) to switch
+     * it off, if it knows that the AP might go to sleep. This is useful
+     * for nagivational applications when the system is in high power mode.
+     * Parameters:
+     *    id - Id for the request.
+     *    options - See FlpBatchOptions struct definition.
+     * Return value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_INSUFFICIENT_MEMORY,
+     *    FLP_RESULT_ID_EXISTS, FLP_RESULT_ERROR on failure.
+     */
+    int (*start_batching)(int id, FlpBatchOptions* options);
+
+    /**
+     * Update FlpBatchOptions associated with a batching request.
+     * When a batching operation is in progress and a batching option
+     * such as FLP_BATCH_WAKEUP_ON_FIFO_FULL needs to be updated, this API
+     * will be used. For instance, this can happen when the AP is awake and
+     * the maps application is being used.
+     * Parameters:
+     *    id - Id of an existing batch request.
+     *    new_options - Updated FlpBatchOptions
+     * Return value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN,
+     *    FLP_RESULT_ERROR on error.
+     */
+    int (*update_batching_options)(int id, FlpBatchOptions* new_options);
+
+    /**
+     * Stop batching.
+     * Parameters:
+     *    id - Id for the request.
+     * Return Value:
+     *    FLP_RESULT_SUCCESS on success, FLP_RESULT_ID_UNKNOWN or
+     *    FLP_RESULT_ERROR on failure.
+     */
+    int (*stop_batching)(int id);
+
+    /**
+     * Closes the interface. If any batch operations are in progress,
+     * they should be stopped.
+     */
+    void (*cleanup)();
+
+    /**
+     * Get the fused location that was batched.
+     *   flp_location_callback is used to return the location. The location object
+     * is dropped from the buffer only when the buffer is full. Do not remove it
+     * from the buffer just because it has been returned using the callback.
+     * In other words, when there is no new location object, two calls to
+     * get_batched_location(1) should return the same location object.
+     * Parameters:
+     *      last_n_locations - Number of locations to get. This can be one or many.
+     *      If the last_n_locations is 1, you get the latest location known to the
+     *      hardware.
+     */
+    void (*get_batched_location)(int last_n_locations);
+
+    /**
+     * Injects current location from another location provider
+     * latitude and longitude are measured in degrees
+     * expected accuracy is measured in meters
+     * Parameters:
+     *      location - The location object being injected.
+     * Return value: FLP_RESULT_SUCCESS or FLP_RESULT_ERROR.
+     */
+    int  (*inject_location)(FlpLocation* location);
+
+    /**
+     * Get a pointer to extension information.
+     */
+    const void* (*get_extension)(const char* name);
+
+    /**
+     * Retrieve all batched locations currently stored and clear the buffer.
+     * flp_location_callback MUST be called in response, even if there are
+     * no locations to flush (in which case num_locations should be 0).
+     * Subsequent calls to get_batched_location or flush_batched_locations
+     * should not return any of the locations returned in this call.
+     */
+    void (*flush_batched_locations)();
+} FlpLocationInterface;
+
+#if defined(__ANDROID_OS__)
+struct flp_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Get a handle to the FLP Interface.
+     */
+    const FlpLocationInterface* (*get_flp_interface)(struct flp_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct flp_device_t {
+    /**
+     * Get a handle to the FLP Interface.
+     */
+    const FlpLocationInterface* (*get_flp_interface)(struct flp_device_t* dev);
+};
+#endif
+
+/**
+ * Callback for reports diagnostic data into the Java framework code.
+*/
+typedef void (*report_data)(char* data, int length);
+
+/**
+ * FLP diagnostic callback structure.
+ * Currently, not used - but this for future extension.
+ */
+typedef struct {
+    /** set to sizeof(FlpDiagnosticCallbacks) */
+    size_t      size;
+
+    flp_set_thread_event set_thread_event_cb;
+
+    /** reports diagnostic data into the Java framework code */
+    report_data data_cb;
+} FlpDiagnosticCallbacks;
+
+/** Extended interface for diagnostic support. */
+typedef struct {
+    /** set to sizeof(FlpDiagnosticInterface) */
+    size_t          size;
+
+    /**
+     * Opens the diagnostic interface and provides the callback routines
+     * to the implemenation of this interface.
+     */
+    void  (*init)(FlpDiagnosticCallbacks* callbacks);
+
+    /**
+     * Injects diagnostic data into the FLP subsystem.
+     * Return 0 on success, -1 on error.
+     **/
+    int  (*inject_data)(char* data, int length );
+} FlpDiagnosticInterface;
+
+/**
+ * Context setting information.
+ * All these settings shall be injected to FLP HAL at FLP init time.
+ * Following that, only the changed setting need to be re-injected
+ * upon changes.
+ */
+
+#define FLP_DEVICE_CONTEXT_GPS_ENABLED                     (1U<<0)
+#define FLP_DEVICE_CONTEXT_AGPS_ENABLED                    (1U<<1)
+#define FLP_DEVICE_CONTEXT_NETWORK_POSITIONING_ENABLED     (1U<<2)
+#define FLP_DEVICE_CONTEXT_WIFI_CONNECTIVITY_ENABLED       (1U<<3)
+#define FLP_DEVICE_CONTEXT_WIFI_POSITIONING_ENABLED        (1U<<4)
+#define FLP_DEVICE_CONTEXT_HW_NETWORK_POSITIONING_ENABLED  (1U<<5)
+#define FLP_DEVICE_CONTEXT_AIRPLANE_MODE_ON                (1U<<6)
+#define FLP_DEVICE_CONTEXT_DATA_ENABLED                    (1U<<7)
+#define FLP_DEVICE_CONTEXT_ROAMING_ENABLED                 (1U<<8)
+#define FLP_DEVICE_CONTEXT_CURRENTLY_ROAMING               (1U<<9)
+#define FLP_DEVICE_CONTEXT_SENSOR_ENABLED                  (1U<<10)
+#define FLP_DEVICE_CONTEXT_BLUETOOTH_ENABLED               (1U<<11)
+#define FLP_DEVICE_CONTEXT_CHARGER_ON                      (1U<<12)
+
+/** Extended interface for device context support. */
+typedef struct {
+    /** set to sizeof(FlpDeviceContextInterface) */
+    size_t          size;
+
+    /**
+     * Injects debug data into the FLP subsystem.
+     * Return 0 on success, -1 on error.
+     **/
+    int  (*inject_device_context)(uint32_t enabledMask);
+} FlpDeviceContextInterface;
+
+
+/**
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the FLP subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ *     In other words, Unknown state can be interpreted as a state in which the
+ * FLP subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the FLP system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate FLP location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the FLP system is unavailable, flp_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ */
+#define FLP_GEOFENCE_TRANSITION_ENTERED     (1L<<0)
+#define FLP_GEOFENCE_TRANSITION_EXITED      (1L<<1)
+#define FLP_GEOFENCE_TRANSITION_UNCERTAIN   (1L<<2)
+
+#define FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE (1L<<0)
+#define FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE   (1L<<1)
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current location as determined by the FLP subsystem.
+ *      transition  - Can be one of FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED,
+ *                    FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected; -1 if not available.
+ *      sources_used - Bitwise OR of FLP_TECH_MASK flags indicating which
+ *                     subsystems were used.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*flp_geofence_transition_callback) (int32_t geofence_id,  FlpLocation* location,
+        int32_t transition, FlpUtcTime timestamp, uint32_t sources_used);
+
+/**
+ * The callback associated with the availablity of one the sources used for geofence
+ * monitoring by the FLP sub-system For example, if the GPS system determines that it cannot
+ * monitor geofences because of lack of reliability or unavailability of the GPS signals,
+ * it will call this callback with FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE parameter and the
+ * source set to FLP_TECH_MASK_GNSS.
+ *
+ * Parameters:
+ *  status - FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE or FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE.
+ *  source - One of the FLP_TECH_MASKS
+ *  last_location - Last known location.
+ */
+typedef void (*flp_geofence_monitor_status_callback) (int32_t status, uint32_t source,
+                                                      FlpLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          FLP_RESULT_ID_EXISTS  - geofence with id already exists
+ *          FLP_RESULT_INVALID_GEOFENCE_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          FLP_RESULT_ERROR - for other errors.
+ */
+typedef void (*flp_geofence_add_callback) (int32_t geofence_id, int32_t result);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_remove_callback) (int32_t geofence_id, int32_t result);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT__ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_pause_callback) (int32_t geofence_id, int32_t result);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * result - FLP_RESULT_SUCCESS
+ *          FLP_RESULT_ID_UNKNOWN - for invalid id
+ *          FLP_RESULT_ERROR for others.
+ */
+typedef void (*flp_geofence_resume_callback) (int32_t geofence_id, int32_t result);
+
+typedef struct {
+    /** set to sizeof(FlpGeofenceCallbacks) */
+    size_t size;
+    flp_geofence_transition_callback geofence_transition_callback;
+    flp_geofence_monitor_status_callback geofence_status_callback;
+    flp_geofence_add_callback geofence_add_callback;
+    flp_geofence_remove_callback geofence_remove_callback;
+    flp_geofence_pause_callback geofence_pause_callback;
+    flp_geofence_resume_callback geofence_resume_callback;
+    flp_set_thread_event set_thread_event_cb;
+    flp_capabilities_callback flp_capabilities_cb;
+} FlpGeofenceCallbacks;
+
+
+/** Type of geofence */
+typedef enum {
+    TYPE_CIRCLE = 0,
+} GeofenceType;
+
+/** Circular geofence is represented by lat / long / radius */
+typedef struct {
+    double latitude;
+    double longitude;
+    double radius_m;
+} GeofenceCircle;
+
+/** Represents the type of geofence and data */
+typedef struct {
+    GeofenceType type;
+    union {
+        GeofenceCircle circle;
+    } geofence;
+} GeofenceData;
+
+/** Geofence Options */
+typedef struct {
+   /**
+    * The current state of the geofence. For example, if
+    * the system already knows that the user is inside the geofence,
+    * this will be set to FLP_GEOFENCE_TRANSITION_ENTERED. In most cases, it
+    * will be FLP_GEOFENCE_TRANSITION_UNCERTAIN. */
+    int last_transition;
+
+   /**
+    * Transitions to monitor. Bitwise OR of
+    * FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and
+    * FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+    */
+    int monitor_transitions;
+
+   /**
+    * Defines the best-effort description
+    * of how soon should the callback be called when the transition
+    * associated with the Geofence is triggered. For instance, if set
+    * to 1000 millseconds with FLP_GEOFENCE_TRANSITION_ENTERED, the callback
+    * should be called 1000 milliseconds within entering the geofence.
+    * This parameter is defined in milliseconds.
+    * NOTE: This is not to be confused with the rate that the GPS is
+    * polled at. It is acceptable to dynamically vary the rate of
+    * sampling the GPS for power-saving reasons; thus the rate of
+    * sampling may be faster or slower than this.
+    */
+    int notification_responsivenes_ms;
+
+   /**
+    * The time limit after which the UNCERTAIN transition
+    * should be triggered. This paramter is defined in milliseconds.
+    */
+    int unknown_timer_ms;
+
+    /**
+     * The sources to use for monitoring geofences. Its a BITWISE-OR
+     * of FLP_TECH_MASK flags.
+     */
+    uint32_t sources_to_use;
+} GeofenceOptions;
+
+/** Geofence struct */
+typedef struct {
+    int32_t geofence_id;
+    GeofenceData* data;
+    GeofenceOptions* options;
+} Geofence;
+
+/** Extended interface for FLP_Geofencing support */
+typedef struct {
+   /** set to sizeof(FlpGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implemenation of this interface.  Once called you should respond
+    * by calling the flp_capabilities_callback in FlpGeofenceCallbacks to
+    * specify the capabilities that your implementation supports.
+    */
+   void  (*init)( FlpGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a list of geofences.
+    * Parameters:
+    *     number_of_geofences - The number of geofences that needed to be added.
+    *     geofences - Pointer to array of pointers to Geofence structure.
+    */
+   void (*add_geofences) (int32_t number_of_geofences, Geofence** geofences);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       FLP_GEOFENCE_TRANSITION_ENTERED, FLP_GEOFENCE_TRANSITION_EXITED and
+    *       FLP_GEOFENCE_TRANSITION_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Modify a particular geofence option.
+    * Parameters:
+    *    geofence_id - The id for the geofence.
+    *    options - Various options associated with the geofence. See
+    *        GeofenceOptions structure for details.
+    */
+   void (*modify_geofence_option) (int32_t geofence_id, GeofenceOptions* options);
+
+   /**
+    * Remove a list of geofences. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *     number_of_geofences - The number of geofences that needed to be added.
+    *     geofence_id - Pointer to array of geofence_ids to be removed.
+    */
+   void (*remove_geofences) (int32_t number_of_geofences, int32_t* geofence_id);
+} FlpGeofencingInterface;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_FLP_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/gnss-base.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/gnss-base.h
new file mode 100644
index 0000000..b7bd503
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/gnss-base.h
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.gnss@1.0
+// Root: android.hardware:hardware/interfaces
+
+#ifndef GNSS_BASE_H
+#define GNSS_BASE_H
+
+enum {
+    GNSS_MAX_SVS_COUNT = 64,
+};
+
+enum {
+    GNSS_CONSTELLATION_UNKNOWN = 0,
+    GNSS_CONSTELLATION_GPS = 1,
+    GNSS_CONSTELLATION_SBAS = 2,
+    GNSS_CONSTELLATION_GLONASS = 3,
+    GNSS_CONSTELLATION_QZSS = 4,
+    GNSS_CONSTELLATION_BEIDOU = 5,
+    GNSS_CONSTELLATION_GALILEO = 6,
+};
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_GNSS_V1_0_EXPORTED_CONSTANTS_H_
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mnl_flp_test_interface.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mnl_flp_test_interface.h
new file mode 100644
index 0000000..1b5f284
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mnl_flp_test_interface.h
@@ -0,0 +1,39 @@
+#ifndef __MNL_FLP_TEST_INTERFACE_H__
+#define __MNL_FLP_TEST_INTERFACE_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IOCTL_MNL_IMAGE_FILE_TO_MEM  1
+#define IOCTL_MNL_NVRAM_FILE_TO_MEM  2
+#define IOCTL_MNL_NVRAM_MEM_TO_FILE  3
+
+
+typedef struct {
+    void (*flp_test_gps_start)();
+    void (*flp_test_gps_stop)();
+    int (*flp_test_lpbk_start)();
+    int (*flp_test_lpbk_stop)();
+} flp_test2mnl_interface;
+
+//======================================================
+// GPS FLP test -> MNLD
+//======================================================
+#define MTK_FLP_TEST2MNL "mtk_flp_test2mnl"
+
+int flp_test2mnl_hdlr(int fd, flp_test2mnl_interface* hdlr);
+int create_flp_test2mnl_fd(void);
+void flp_mnl_emi_download(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_controller.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_controller.h
new file mode 100644
index 0000000..52d0610
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_controller.h
@@ -0,0 +1,30 @@
+#ifndef MTK_FLP_LOWPOWER_H
+#define MTK_FLP_LOWPOWER_H
+
+#include "mtk_flp_main.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define FLP_VERSION_HEAD 'F','L','P','_','V','E','R','_'
+#define FLP_MAJOR_VERSION '1','7','0','6','1','9','0','1'  // y,y,m,m,d,d,rev,rev
+#define FLP_BRANCH_INFO '_','0','.','5','8','_'
+#define FLP_MINER_VERSION 'N','1'
+#define FLP_VER_INFO FLP_VERSION_HEAD,FLP_MAJOR_VERSION,FLP_BRANCH_INFO,FLP_MINER_VERSION
+
+#define MTK_FLP_ZPG_NORMAL_SEC 90
+#define MTK_FLP_ZPG_MAX_TIMEOUT_SEC 600
+
+int64_t mtk_flp_get_timestamp(struct timeval *ptv);
+int mtk_flp_controller_report_loc(MTK_FLP_LOCATION_T outloc);
+int mtk_flp_controller_process(MTK_FLP_MSG_T *prmsg) ;
+int mtk_flp_controller_query_mode ();
+int mtk_flp_controller_reset_status(void);
+
+#ifdef __cplusplus
+   }  /* extern "C" */
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_main.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_main.h
new file mode 100644
index 0000000..d87bdc8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_main.h
@@ -0,0 +1,240 @@
+#ifndef __MNL_FLP_MAIN_H__
+#define __MNL_FLP_MAIN_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#if defined(__ANDROID_OS__)
+#include <hardware/fused_location.h>
+#elif defined(__LINUX_OS__)
+#include "fused_location.h"
+#endif
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FLP_MNL_BUFF_SIZE           (1 * 1024)
+#define FLP_MNL_INTERFACE_VERSION   1
+#define OFFLOAD_PAYLOAD_LEN (600)
+#define OFL_VER "OFL_VER_2016.11.01-01"
+
+//======================================================
+// FLP -> FLP HAL
+//======================================================
+#define FLP_TO_MNL "flp_to_mnl"
+#define MNL_TO_FLP "mnl_to_flp"
+
+#define FLP_MNL_PAYLOAD_LEN 128
+#define MNLD_FLP_CAPABILITY_AP_MODE      1
+#define MNLD_FLP_CAPABILITY_OFL_MODE     2
+#define MNLD_FLP_CAPABILITY_AP_OFL_MODE  3
+
+//FLP source type
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define FLP_TECH_MASK_WIFI      (1U<<1)
+#define FLP_TECH_MASK_SENSORS   (1U<<2)
+#define FLP_TECH_MASK_CELL      (1U<<3)
+#define FLP_TECH_MASK_BLUETOOTH (1U<<4)
+#define FLP_TECH_MASK_PSEUDO    (1U<<5)
+
+#define HAL_FLP_BUFF_SIZE   (1 * 1024)
+#define MTK_FLP_SUCCESS     (0)
+#define MTK_FLP_ERROR       (-1)
+
+typedef struct {
+    UINT32 type;
+    UINT32 session;
+    UINT32 length;
+    UINT8  data[FLP_MNL_PAYLOAD_LEN];
+} MTK_FLP_MNL_MSG_T;
+
+typedef struct {
+    size_t  size;
+    unsigned short  flags;
+    double          latitude;
+    double          longitude;
+    double          altitude;
+    float           speed;
+    float           bearing;
+    float           accuracy;
+    int64_t         timestamp;
+    unsigned int    sources_used;
+} MTK_FLP_LOCATION_T;
+
+typedef struct {
+    double max_power_allocation_mW;
+    UINT32 sources_to_use;
+    INT32 flags;
+    INT64 period_ns;
+} MTK_FLP_BATCH_OPTION_T;
+
+typedef struct {
+    UINT32 type;
+    UINT32 length;
+    UINT8 data[OFFLOAD_PAYLOAD_LEN];
+} MTK_FLP_OFFLOAD_MSG_T;
+
+typedef struct {
+    UINT32 type;
+    UINT32 session;
+    UINT32 length;
+} MTK_FLP_MNL_MSG_HEADER_T;
+
+typedef struct {
+    int (*mnld_flp_attach)();
+    void (*mnld_flp_hbd_gps_open)();
+    void (*mnld_flp_hbd_gps_close)();
+    void (*mnld_flp_ofl_link_open)();
+    void (*mnld_flp_ofl_link_close)();
+    int (*mnld_flp_ofl_link_send)();
+} flp2mnl_interface;
+
+typedef struct {
+    int (*flp_start_batching)(int id, FlpBatchOptions* options);
+    int (*flp_update_batching_option)(int id, FlpBatchOptions* options);
+    int (*flp_stop_batching)(int id);
+    void (*flp_get_batched_location)(int last_n_locations);
+    int (*flp_inject_location)(MTK_FLP_LOCATION_T* location);
+    void (*flp_flush_batched_location)();
+} flphal2flp_interface;
+
+
+typedef struct {
+    UINT32 type;   // 1:AP mode(default)   2: Offload mode  3:AP+Offload mode
+    UINT32 pre_type;
+    UINT32 id;
+} MTK_FLP_Session_T;
+
+typedef struct {
+    int type;
+    int length;
+} MTK_FLP_MSG_T;
+
+
+extern MTK_FLP_Session_T mnld_flp_session;
+
+/*************************************************
+  Message Table from FLP thread to MNL
+*************************************************/
+typedef enum {
+    // MNL -> FLP
+    MNLD_FLP_TYPE_MNL_BOOTUP = 100,
+    MNLD_FLP_TYPE_FLP_ATTACH_DONE,
+    MNLD_FLP_TYPE_SESSION_UPDATE,
+
+    MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE = 110,
+    MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE,
+    MNLD_FLP_TYPE_HBD_GPS_LOCATION,
+
+    MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE = 120,
+    MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE,
+
+    MNLD_FLP_TYPE_OFL_LINK_RECV = 130,
+
+    // FLP -> MNL
+    MNLD_FLP_TYPE_FLP_ATTACH = 200,
+
+    MNLD_FLP_TYPE_HBD_GPS_OPEN = 210,
+    MNLD_FLP_TYPE_HBD_GPS_CLOSE,
+
+    MNLD_FLP_TYPE_OFL_LINK_OPEN = 220,
+    MNLD_FLP_TYPE_OFL_LINK_CLOSE,
+
+    MNLD_FLP_TYPE_OFL_LINK_SEND = 230,
+} mnld_flp_type;
+
+/*************************************************
+  Message Table from FLP HAL to FLP thread
+*************************************************/
+typedef enum {
+    MTK_FLP_MSG_SYS_FLPD_RESET_NTF = 100,
+
+    //HAL messages
+    MTK_FLP_MSG_HAL_INIT_CMD = 200,
+    MTK_FLP_MSG_HAL_START_CMD,
+    MTK_FLP_MSG_HAL_STOP_CMD,
+    MTK_FLP_MSG_HAL_STOP_RSP,
+    MTK_FLP_MSG_HAL_SET_OPTION_CMD,
+    MTK_FLP_MSG_HAL_INJECT_LOC_CMD,
+    MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF,
+    MTK_FLP_MSG_HAL_DIAG_REPORT_DATA_NTF,
+
+    MTK_FLP_MSG_HSB_REPORT_LOC_NTF = 300,
+    MTK_FLP_MSG_OFL_REPORT_LOC_NTF,
+
+    MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF = 400,
+    MTK_FLP_MSG_HAL_REQUEST_LOC_NTF,
+    MTK_FLP_MSG_HAL_FLUSH_LOC_NTF,
+    MTK_FLP_MSG_HAL_REPORT_STATUS_NTF,
+    MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF,
+    MTK_FLP_MSG_OFL_GEOFENCE_CMD,
+
+    MTK_FLP_MSG_DC_START_CMD = 500,
+    MTK_FLP_MSG_DC_STOP_CMD,
+    MTK_FLP_MSG_CONN_SCREEN_STATUS,
+    MTK_FLP_MSG_END,
+}MTK_FLP_MSG_TYPE;
+
+typedef enum {
+    FLP_AP_MODE      = 1,
+    FLP_OFFLOAD_MODE = 2,
+} MTK_FLP_SYS_MODE_T;
+
+typedef enum {
+    MTK_FLP_IDLE_MODE = -1,
+    MTK_FLP_BATCH_SLEEP_ON_FIFO_FULL = 0,
+    MTK_FLP_BATCH_WAKE_ON_FIFO_FULL = 1,
+} MTK_FLP_BATCH_MODE_T;
+
+typedef enum {
+    EARLYSUSPEND_ON,
+    EARLYSUSPEND_MEM,
+} MTK_FLP_SCR_STATE;
+
+enum {
+    MNL_STATUS_NONE,
+    MNL_STATUS_ATTACH,
+    MNL_STATUS_ATTACH_DONE,
+    MNL_STATUS_HBD_GPS_OPEN,
+    MNL_STATUS_HBD_GPS_OPEN_DONE,
+    MNL_STATUS_HBD_GPS_CLOSE,
+    MNL_STATUS_HBD_GPS_CLOSE_DONE,
+    MNL_STATUS_OFL_LINK_OPEN,
+    MNL_STATUS_OFL_LINK_OPEN_DONE,
+    MNL_STATUS_OFL_LINK_CLOSE,
+    MNL_STATUS_OFL_LINK_CLOSE_DONE,
+};
+
+int mnl2flp_mnld_reboot();
+int mnl2flp_data_send(UINT8 *buf, UINT32 len);
+int mnld_flp_attach_done();
+int mnld_flp_hbd_gps_open_done();
+int mnld_flp_hbd_gps_close_done();
+int mnld_flp_ofl_gps_open_done();
+int mnld_flp_ofl_gps_close_done();
+int mnld_flp_session_update();
+int mnld_flp_gen_new_session();
+int mtk_hal2flp_main_hdlr(int fd, flp2mnl_interface* hdlr);
+int flp2mnl_hdlr(MTK_FLP_MNL_MSG_T  *prMsg);
+int mtk_flp2mnl_process(MTK_FLP_MSG_T *prmsg);
+int mnl2flp_hdlr(MTK_FLP_MNL_MSG_T* prmsg);
+int mtk_flp_get_sys_mode();
+void mtk_flp_set_sys_mode (unsigned int sysMode);
+int mnl_send2flp(const char* buff, int len);
+
+
+
+// -1 means failure
+int create_flphal2mnl_fd();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_screen_monitor.h b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_screen_monitor.h
new file mode 100644
index 0000000..be96082
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/inc/mtk_flp_screen_monitor.h
@@ -0,0 +1,21 @@
+#ifndef __MNL_FLP_SCREEN_MONITOR_H__
+#define __MNL_FLP_SCREEN_MONITOR_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void flp_monitor_init();
+void mtk_flp_get_wake_monitor_state(UINT8 *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mnl_flp_test_interface.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mnl_flp_test_interface.c
new file mode 100644
index 0000000..2941718
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mnl_flp_test_interface.c
@@ -0,0 +1,115 @@
+#include <errno.h>
+#include <unistd.h>  // for close
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+
+#include "mnl_flp_test_interface.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_gps_type.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl_flp_test"
+#endif
+
+/*****************************************
+FLP test -> MNL Testing
+*****************************************/
+int flp_test2mnl_hdlr(int fd, flp_test2mnl_interface* hdlr) {
+    int ret;
+    char buff[1024] = {0};
+    ret = safe_recvfrom(fd, buff, sizeof(buff));
+
+    LOGD("[OFL]data from ofl tst: %d\n", (int)buff[0]);
+    switch (buff[0]) {
+    case '1':
+        if (hdlr->flp_test_gps_start) {
+            hdlr->flp_test_gps_start();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_test_gps_start is NULL");
+            ret = -1;
+        }
+        break;
+    case '2':
+        if (hdlr->flp_test_gps_stop) {
+            hdlr->flp_test_gps_stop();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_test_gps_stop is NULL");
+            ret = -1;
+        }
+        break;
+
+    case '3':
+    {
+        // Loopback test start
+        if (hdlr->flp_test_lpbk_start) {
+            hdlr->flp_test_lpbk_start();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_lpbk is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case '4':
+        // Loopback test stop
+        if (hdlr->flp_test_lpbk_stop) {
+            hdlr->flp_test_lpbk_stop();
+        } else {
+            LOGE("flp2mnl_hdlr() flp_lpbk is NULL");
+            ret = -1;
+        }
+        break;
+
+    default:
+        LOGD("[OFL] invalide opid :%d!", buff[0]);
+        break;
+    }
+
+    return MTK_GPS_SUCCESS;
+}
+
+void *thread_emi_download(void* arg) {
+    int emi_fd;
+    LOGD("create: %.8X, arg = %p\r\n", (unsigned int)pthread_self(), arg);
+    pthread_detach(pthread_self());
+
+    LOGD("EMI download thread start arg=%p\n", arg);
+    emi_fd = open("/dev/gps_emi", O_RDWR);
+    if (emi_fd == -1) {
+        LOGD("open_port: Unable to open /dev/gps_emi\n");
+        return 0;
+    } else {
+        LOGD("open gps_emi successfully\n");
+    }
+
+    if (ioctl(emi_fd, IOCTL_MNL_IMAGE_FILE_TO_MEM, NULL) <= 0) {
+        LOGD("set IOCTL_MNL_IMAGE_FILE_TO_MEM failed\n");
+        close(emi_fd);
+        return 0;
+    }
+    usleep(2000000);
+    LOGD("EMI download successful and thread exit done");
+    pthread_exit(NULL);
+    return 0;
+}
+void flp_mnl_emi_download(void) {
+    int ret = -1;
+    pthread_t emi_download_thread;
+
+    ret = pthread_create(&emi_download_thread, NULL, thread_emi_download, NULL);
+    if (0 != ret) {
+        LOGE("emi download thread create fail: %s\n", strerror(errno));
+        exit(1);
+    }
+}
+// -1 means failure
+int create_flp_test2mnl_fd() {
+    int fd = socket_bind_udp(MTK_FLP_TEST2MNL);
+    socket_set_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_controller.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_controller.c
new file mode 100644
index 0000000..ca362bc
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_controller.c
@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <gps_dbg_log.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "mtk_flp_controller.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl2flp"
+#endif
+
+#define ONE_SEC_NS 1000000000
+
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+char pFLPVersion[] = {FLP_VER_INFO,0x00};
+static unsigned int flp_enabled = 0, flp_source_to_use = 0;
+static UINT32 flp_running_source = 0;
+static int flp_batch_mode = MTK_FLP_IDLE_MODE;
+static int g_loc_available = -1;
+static int64_t g_flp_period_ns = 0;
+static int64_t g_flp_update_last_time = 0;
+static float current_gnss_acc = 0;
+
+
+int64_t mtk_flp_get_timestamp(struct timeval *ptv) {
+    struct timeval tv;
+
+    if(ptv) {
+        return ((unsigned long long)ptv->tv_sec*1000ULL+(unsigned long long)ptv->tv_usec/1000ULL);
+    } else {
+        gettimeofday(&tv, NULL);
+        return ((unsigned long long)tv.tv_sec*1000ULL + (unsigned long long)tv.tv_usec/1000ULL);
+    }
+}
+
+unsigned int mtk_flp_sys_get_time_tick() {
+    struct timeval t;
+    gettimeofday(&t, NULL);
+    return t.tv_sec;
+}
+
+int mtk_flp_controller_query_mode () {
+    return flp_batch_mode;
+}
+
+void mtk_flp_controller_check_loc_available_expired() {
+    int current_available;
+    int ret, offset = 0;
+    char buff[HAL_FLP_BUFF_SIZE] = {0};
+    MTK_FLP_MSG_T *flp_header = NULL;
+
+    int64_t current_time = (int64_t)mtk_flp_sys_get_time_tick();
+
+    if (mtk_flp_controller_query_mode() == MTK_FLP_IDLE_MODE) {
+        return;
+    }
+
+    if ((current_time - g_flp_update_last_time) > (g_flp_period_ns/ONE_SEC_NS + 1)) {
+        current_available = 1;
+    } else {
+        current_available = 0;
+    }
+    if (g_loc_available != current_available) {
+        g_loc_available = current_available;
+
+        flp_header = malloc(sizeof(MTK_FLP_MSG_T)+ sizeof(int));
+        if(flp_header==NULL) {
+            LOGE("report status malloc failed");
+            return;
+        }
+        flp_header->type = MTK_FLP_MSG_HAL_REPORT_STATUS_NTF;
+        flp_header->length = sizeof(int);
+        memcpy((char *)flp_header+sizeof(MTK_FLP_MSG_T), &g_loc_available, sizeof(int));
+        put_binary(buff, &offset, (const char*)flp_header, (sizeof(MTK_FLP_MSG_T) + flp_header->length));
+        ret = mnl_send2flp(buff, offset);
+        free(flp_header);
+        if(ret < 0) {
+            LOGE("MTK_FLP2HAL send error return error");
+        }
+    }
+}
+
+int mtk_flp_controller_report_loc(MTK_FLP_LOCATION_T outloc) {
+    unsigned char update_flploc = 0;
+    int64_t current_time = 0;
+
+    // one second timer
+    if (flp_enabled) {
+        mtk_flp_controller_check_loc_available_expired();
+    } else {
+        LOGE("flp bypass, no source open");
+        return MTK_FLP_ERROR;
+    }
+
+    current_gnss_acc = outloc.accuracy;
+    if (outloc.accuracy < 0.001) {
+        LOGE("bypass loc - loc no fix");
+        return MTK_FLP_ERROR;
+    }
+
+    // Location fix
+    if (g_flp_update_last_time == 0) {
+        g_flp_update_last_time = (int64_t)(mtk_flp_sys_get_time_tick());
+        update_flploc = 1;
+    } else {
+        current_time = (int64_t)(mtk_flp_sys_get_time_tick());
+        if(g_flp_update_last_time > current_time) {
+            g_flp_update_last_time = 0;
+        }
+
+        if((current_time - g_flp_update_last_time) >= g_flp_period_ns/ONE_SEC_NS) {
+            update_flploc = 1;
+            g_flp_update_last_time = current_time;
+        }
+    }
+    if (!update_flploc) {
+        LOGE("bypass loc - on period");
+        return MTK_FLP_ERROR;
+    }
+#if 0
+    LOGD("Location,LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+    outloc.longitude, outloc.latitude, outloc.altitude, outloc.accuracy,
+    outloc.speed, outloc.bearing, outloc.flags, outloc.sources_used, outloc.timestamp);
+#endif
+    return MTK_FLP_SUCCESS;
+}
+
+
+void mtk_flp_controller_update_option(FlpBatchOptions *option) {
+    UINT32 local_source = 0;
+    UINT32 new_source = 0;
+    MTK_FLP_MSG_T *flp_cmd;
+    MTK_FLP_BATCH_OPTION_T batch_option;
+
+    //assign stop command;
+    memset(&batch_option,0,sizeof(MTK_FLP_BATCH_OPTION_T));
+    if(option != NULL) {
+        local_source = flp_running_source;
+        new_source = flp_source_to_use;
+        LOGD("local:%d,new:%d",local_source,new_source);
+        if(local_source != new_source) {
+            if((local_source == 0) && (new_source >= 1)) { //new req is open dc_xxx
+                current_gnss_acc = 0;
+                g_flp_update_last_time = 0;
+                flp_cmd = malloc(sizeof(MTK_FLP_BATCH_OPTION_T)+ sizeof(MTK_FLP_MSG_T));
+                if(flp_cmd == NULL) {
+                    LOGE("update opt failed");
+                    return;
+                }
+                flp_cmd->type = MTK_FLP_MSG_DC_START_CMD;
+                flp_cmd->length = sizeof(MTK_FLP_BATCH_OPTION_T);
+                batch_option.flags = flp_batch_mode;
+                batch_option.max_power_allocation_mW = option->max_power_allocation_mW;
+                batch_option.period_ns = g_flp_period_ns;
+                batch_option.sources_to_use = FLP_TECH_MASK_GNSS;
+                memcpy((char *)flp_cmd + sizeof(MTK_FLP_MSG_T), &batch_option, sizeof(MTK_FLP_BATCH_OPTION_T));
+                mtk_flp2mnl_process(flp_cmd);
+                free(flp_cmd);
+            } else if((local_source >= 1) && (new_source == 0)) {//new req is close dc_xxx
+                flp_cmd = malloc(sizeof(MTK_FLP_MSG_T));
+                if(flp_cmd == NULL) {
+                    LOGE("update opt failed");
+                    return;
+                }
+                flp_cmd->type = MTK_FLP_MSG_DC_STOP_CMD;
+                flp_cmd->length = 0;
+                mtk_flp2mnl_process(flp_cmd);
+                free(flp_cmd);
+            }
+        }
+        flp_running_source = flp_source_to_use;
+    }
+}
+
+int mtk_flp_controller_reset_status(void) {
+    LOGD("clear flp ap status");
+    flp_enabled = 0;
+    flp_source_to_use = 0;
+    flp_running_source =0;
+    flp_batch_mode = MTK_FLP_IDLE_MODE;
+    g_flp_period_ns = 0;
+    current_gnss_acc = 0;
+    return MTK_FLP_SUCCESS;
+}
+
+//*****************************************************************************
+//  Low Power Main Function:
+//  1. Obtain Source_to_use(FLP & geofence) from FLP mtk_flp_input
+//  2. Relay command to FLP kernel
+//
+//  AP --> FLP HAL Offload (mtk_flp_input) --> Low power --> FLP kernel --> DC
+//*****************************************************************************
+int mtk_flp_controller_process(MTK_FLP_MSG_T *prmsg) {
+    FlpBatchOptions option;
+
+    memset(&option, 0, sizeof(option));
+
+    if(prmsg == NULL) {
+        LOGE("mtk_flp_controller_process, recv prmsg is null pointer\r\n");
+        return MTK_FLP_ERROR;
+    }
+
+    LOGD("mtk_flp_controller_process, recv prmsg, type: 0x%02x, len:%d\r\n", prmsg->type, prmsg->length);
+
+    switch( prmsg->type ) {
+        case MTK_FLP_MSG_HAL_START_CMD:      //process init request from HAL
+            LOGD("%s", pFLPVersion);
+            if(prmsg->length >= (int)(sizeof(FlpBatchOptions))) {
+                memcpy(&option, (FlpBatchOptions *)( (unsigned char*)prmsg+sizeof(MTK_FLP_MSG_T) ), sizeof(FlpBatchOptions));
+                flp_enabled = 1;
+                flp_batch_mode = option.flags;
+                g_flp_period_ns = option.period_ns;
+                flp_source_to_use = option.sources_to_use; //update flp source
+                mtk_flp_controller_update_option(&option);
+                //LOGD("low power enabled %u %u %"PRId64, flp_source_to_use, flp_enabled, g_flp_period_ns);
+            } else {
+                LOGE("incrorrect size %d",prmsg->length);
+            }
+            break;
+        case MTK_FLP_MSG_HAL_STOP_CMD:
+            LOGD("stop flp");
+            memset(&option, 0, sizeof(FlpBatchOptions));
+            flp_enabled = 0;
+            flp_source_to_use = 0;
+            option.sources_to_use = flp_source_to_use;
+            mtk_flp_controller_update_option(&option);
+            break;
+        case MTK_FLP_MSG_HAL_SET_OPTION_CMD:
+            if(!flp_enabled) {
+                LOGD("hal start");
+            }
+            flp_enabled = 1;
+            if(prmsg->length >= (int)(sizeof(FlpBatchOptions))) {
+                memcpy(&option, (FlpBatchOptions *)( (UINT8*)prmsg+sizeof(MTK_FLP_MSG_T) ), sizeof(FlpBatchOptions));
+
+                if(g_flp_period_ns != option.period_ns) {
+                    if(option.period_ns > 0) {
+                        //LOGD("update period from %lld to %lld",g_flp_period_ns,option.period_ns);
+                        g_flp_period_ns = option.period_ns;
+                    }
+                }
+
+                if(flp_batch_mode != (int)option.flags) {
+                    LOGD("update batch mode from %d to %d",flp_batch_mode,option.flags);
+                    flp_batch_mode = option.flags;
+                }
+
+                if(flp_source_to_use != option.sources_to_use) {
+                    LOGD("update source mode from %d to %d",flp_source_to_use,option.sources_to_use);
+                    flp_source_to_use = option.sources_to_use;
+                }
+                mtk_flp_controller_update_option(&option);
+            } else {
+                LOGE("incrorrect size %d",prmsg->length);
+            }
+            break;
+        default:
+            LOGD("lowpower pass through");
+            break;
+    }
+    return MTK_FLP_SUCCESS;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_main.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_main.c
new file mode 100644
index 0000000..61fcaf0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_main.c
@@ -0,0 +1,573 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "mtk_flp_main.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "mtk_gps.h"
+#include "mnld.h"
+//#include "mtk_flp_wake_monitor.h"
+#include "mtk_flp_controller.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "flpmain"
+#endif
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+flp2mnl_interface* flp2mnl_hdlr_cb;
+static unsigned int gModeFlag = FLP_AP_MODE;
+static char g_mnl2flp_path[128] = MNL_TO_FLP;
+int ofl_lpbk_tst_start = 0;
+int ofl_lpbk_tst_size = 300;
+
+MTK_FLP_Session_T mnld_flp_session = {
+    .type = MNLD_FLP_CAPABILITY_AP_MODE,
+    .pre_type = MNLD_FLP_CAPABILITY_AP_MODE,
+    .id = 1,
+};
+
+/**********************************************************
+ *  Function Declaration                                  *
+ **********************************************************/
+extern int mnl2gfc_data_send(unsigned char *buf, unsigned int len);
+
+/**********************************************************
+ *  Socket Function                                       *
+ **********************************************************/
+static int flp_safe_recvfrom(int sockfd, char* buf, int len) {
+    int ret = 0;
+    int retry = 10;
+
+    while ((ret = recvfrom(sockfd, buf, len, 0,NULL, NULL)) == -1) {
+        //LOGW("ret=%d len=%d\n", ret, len);
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto reason=[%s]\n", strerror(errno));
+        break;
+    }
+    return ret;
+}
+
+// -1 means failure
+static int flp_set_socket_blocking(int fd, int blocking) {
+    if (fd < 0) {
+        LOGE("set_socket_blocking  invalid fd=%d\n", fd);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags < 0) {
+        LOGE("set_socket_blocking  invalid flags=%d\n", flags);
+        return -1;
+    }
+
+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+static int flp_safe_sendto(int sockfd, const char* dest, const char* buf, int size) {
+    int len = 0;
+    struct sockaddr_un soc_addr;
+    int retry = 10;
+
+    memset(&soc_addr, 0, sizeof(soc_addr));
+    soc_addr.sun_path[0] = 0;
+    MNLD_STRNCPY(soc_addr.sun_path + 1, dest,sizeof(soc_addr.sun_path) - 1);
+    soc_addr.sun_family = AF_UNIX;
+    while ((len = sendto(sockfd, buf, size, 0,(const struct sockaddr *)&soc_addr, sizeof(soc_addr))) == -1) {
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto dest=[%s] len=%d reason=[%s]\n", dest, size, strerror(errno));
+        break;
+    }
+    return len;
+}
+
+int mnl_send2flp(const char* buff, int len) {
+    int ret = 0;
+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+
+    if (sockfd < 0) {
+        LOGE("mnl_send2flp() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+
+    if (flp_safe_sendto(sockfd, g_mnl2flp_path, buff, len) < 0) {
+        LOGE("mnl_send2gfc safe_sendto failed\n");
+        ret = -1;
+    }
+    close(sockfd);
+    return ret;
+}
+
+static int flp_bind_udp_socket(char* path) {
+    int sockfd;
+    struct sockaddr_un soc_addr;
+
+    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+        LOGE("socket failed reason=[%s]\n", strerror(errno));
+        return -1;
+    }
+    memset(&soc_addr, 0, sizeof(soc_addr));
+    soc_addr.sun_path[0] = 0;
+    MNLD_STRNCPY(soc_addr.sun_path + 1, path,sizeof(soc_addr.sun_path) - 1);
+    soc_addr.sun_family = AF_UNIX;
+    unlink(soc_addr.sun_path);
+    if (bind(sockfd, (struct sockaddr *)&soc_addr, sizeof(soc_addr)) < 0) {
+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));
+        close(sockfd);
+        return -1;
+    }
+
+    /*if (chmod(path, 0660) < 0) {
+        LOGE("chmod err = [%s]\n", strerror(errno));
+    }*/
+    return sockfd;
+}
+
+
+/**********************************************************
+ *  Response from Offload kernel                          *
+ **********************************************************/
+INT32 mtk_gps_ofl_sys_rst_stpgps_req() {
+    int ret = 0;
+
+    LOGD("");
+    gps_mnld_restart_mnl_process();
+    return ret;
+}
+
+INT32 mtk_gps_ofl_sys_submit_flp_data(UINT8 *buf, UINT32 len) {
+    static UINT8 tmp_buf[1024];
+    static int  tmp_buf_w = 0;
+    UINT8 buff[1024] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = NULL;
+
+    LOGD("[OFL]flp submit to host, buf=%p, len=%d", buf, len);
+    if (ofl_lpbk_tst_start == 1) {
+        memcpy(&tmp_buf[tmp_buf_w], buf, len);
+        tmp_buf_w+=len;
+        if (tmp_buf_w >= ofl_lpbk_tst_size) {
+            LOGD("[OFL] lpbk recv enougth data, actual=%d, except=%d, lpbk restart...",
+            tmp_buf_w, ofl_lpbk_tst_size);
+            mtk_gps_ofl_send_flp_data(&tmp_buf[0], ofl_lpbk_tst_size);
+            tmp_buf_w = 0;
+        }
+    } else if ((buf != NULL) && (len != 0) && (len < 1023)) {
+        //MTK_FLP_OFFLOAD_MSG_T *prMsg = (MTK_FLP_OFFLOAD_MSG_T *)&buff[0];
+        prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+        prMsg->type = MNLD_FLP_TYPE_OFL_LINK_RECV;
+        prMsg->length = len;
+        prMsg->session = mnld_flp_session.id;
+        if (len < sizeof(prMsg->data)) {
+            memcpy(&prMsg->data[0], buf, len);
+        } else {
+            LOGE("memcpy buf to prMsg->data out of bounds");
+        }
+
+        if (-1 == mnl2flp_data_send(buff, sizeof(buff))) {
+            LOGE("[FLP2MNLD]Send to FLP failed, %s\n", strerror(errno));
+        } else {
+            //LOGD("[FLP2MNLD]Send to FLP successfully\n");
+        }
+        ///TODO: single CB func from ofl GPS, add another delicate CB func for geofence
+        if (-1 == mnl2gfc_data_send(buff, sizeof(buff))) {
+            LOGE("[GFC2MNLD]Send to GFC failed, %s\n", strerror(errno));
+        }
+        else {
+            //LOGD("[GFC2MNLD]Send to GFC successfully\n");
+        }
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+
+INT32 mtk_gps_ofl_sys_mnl_offload_callback(MTK_GPS_OFL_CB_TYPE type, UINT16 length, UINT8 *data) {
+    int offset;
+    UINT32 first_heartbeat, heartbeat_idx, ms_to_next;
+    //LOGD("type:%d, length:%d\n", type, length);
+
+    switch (type) {
+        case MTK_GPS_OFL_CB_HEART_BEAT:
+        {
+            if (length >= 12) {
+                offset = 0;
+                first_heartbeat = get_int((char*)data, &offset, length);
+                heartbeat_idx   = get_int((char*)data, &offset, length);
+                ms_to_next      = get_int((char*)data, &offset, length);
+                LOGD("type:%d, heartbeat, is_first:%u, idx:%u, next:%u",
+                type, first_heartbeat, heartbeat_idx, ms_to_next);
+                if (mnl_offload_is_enabled() && (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                    if (first_heartbeat) {
+                        LOGD("mnl offload notify start done (mnl offload thread running)");
+                        // TODO: flp-dedicated timer
+                        mnld_gps_start_done(0);  // notify GPS is start
+                    } else {
+                        // TODO: set flp timer by ms_to_next_heartbeat
+                    }
+                }
+            }
+            else {
+                LOGE("type:0x%02x, error length:%d", type, length);
+            }
+        }
+            break;
+        default:
+            break;
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+/*********************************************************/
+/* Response functions from mnl                           */
+/*********************************************************/
+int mnl2flp_mnld_reboot() {
+    LOGD("mnl2flp_mnld_reboot");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    int * payload = NULL;
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    if (mnld_flp_session_update() == -1) {
+        LOGE("mnld_main_thread() mnld_flp_session_update failed");
+    }
+    prMsg->type = MNLD_FLP_TYPE_MNL_BOOTUP;
+    prMsg->session = mnld_flp_session.id;
+    prMsg->length = sizeof(int);
+    payload = (int *)&prMsg->data[0];
+    *payload = FLP_MNL_INTERFACE_VERSION;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnl2flp_data_send(UINT8 *buf, UINT32 len) {
+    int ret = 0;
+    if(len >0) {
+        ret = mnl2flp_hdlr((MTK_FLP_MNL_MSG_T *)buf);
+    } else {
+        LOGE("len err %d",len);
+    }
+    return ret;
+}
+
+int mnld_flp_attach_done() {
+    LOGD("mnld_flp_attach_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_FLP_ATTACH_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_hbd_gps_open_done() {
+    LOGD("mnld_flp_hbd_gps_open_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_hbd_gps_close_done() {
+    LOGD("mnld_flp_hbd_gps_close_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_ofl_gps_open_done() {
+    LOGD("mnld_flp_ofl_gps_open_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_ofl_gps_close_done() {
+    LOGD("mnld_flp_ofl_gps_close_done");
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE;
+    prMsg->length = 0;
+    prMsg->session = mnld_flp_session.id;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_session_update() {
+    LOGD("mnld_flp_session_update,id=%d,type=%d",mnld_flp_session.id,mnld_flp_session.type);
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    int * payload = NULL;
+    MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+
+    prMsg->type = MNLD_FLP_TYPE_SESSION_UPDATE;
+    prMsg->length = sizeof(int);
+    prMsg->session = mnld_flp_session.id;
+    payload = (int *)&prMsg->data[0];
+    *payload = mnld_flp_session.type;
+    return mnl2flp_hdlr(prMsg);
+}
+
+int mnld_flp_gen_new_session() {
+    mnld_flp_session.id++;
+    if (mnld_flp_session.id >= 0xFFFFFFFF) {
+        mnld_flp_session.id = 0;
+        LOGW("Session id overflow!!");
+    }
+    return mnld_flp_session.id;
+}
+
+// Add for dbg usage
+#define MAX_DUMP_CHAR 128
+void mnl_flp_dump_buf(char *p, int len) {
+    int i, r, n;
+    char str[MAX_DUMP_CHAR] = {0};
+    for (i = 0, n = 0; i < len ; i++) {
+        r = snprintf(&str[n], MAX_DUMP_CHAR - n, "%3d,", p[i]);
+        if (r + n >= MAX_DUMP_CHAR || r <= 0) {
+            LOGE("[FLP2MNLD]data from flp: data=%s, error return", str);
+            return;
+        }
+
+        n += r;
+        if ((i % 8 == 7) || i + 1 == len) {
+            LOGD("[FLP2MNLD]data from flp: data=%s", str);
+            n = 0;
+            str[0] = '0';
+        }
+    }
+}
+
+void mtk_flp_set_sys_mode (unsigned int sysMode) {
+    if(sysMode == FLP_AP_MODE || sysMode == FLP_OFFLOAD_MODE) {
+        gModeFlag = sysMode;
+        LOGD("mtk_flp_set_sys_mode success = %d", gModeFlag);
+    } else {
+        LOGD("mtk_flp_set_sys_mode error = %d", sysMode);
+    }
+}
+
+
+int mtk_flp_get_sys_mode() {
+    return gModeFlag;
+}
+
+//*****************************************************************************
+//
+// mtk_hal2flp_main_hdlr(): FLP main function to process CMD from FLP HAL
+//
+// CMD from FWK: FLP JNI --> FLP HAL --> Mnld main --> mtk_hal2flp_main_hdlr
+// RSP to FWK  : mtk_flp2hal_main_hdlr --> mnl2flphal_hdlr(HAL) --> FLP JNI
+//*****************************************************************************
+int mtk_hal2flp_main_hdlr(int fd, flp2mnl_interface* hdlr) {
+    char buff[FLP_MNL_BUFF_SIZE] = {0};
+    char data_recv[1024] ={0};
+    int ret = MTK_FLP_SUCCESS, read_len, offset = 0, len;
+    MTK_FLP_MSG_T *prmsg = NULL;
+
+    read_len = flp_safe_recvfrom(fd, buff, sizeof(buff));
+    if ((read_len <= 0) || (read_len>FLP_MNL_BUFF_SIZE)) {
+        LOGE("flp2mnl_hdlr_cb() safe_recvfrom() failed read_len=%d", read_len);
+        return MTK_FLP_ERROR;
+    }
+    if(hdlr != NULL) {
+        flp2mnl_hdlr_cb = hdlr;
+    } else {
+        LOGD("flp2mnl_hdlr_cb is null");
+    }
+
+    len = get_binary(buff, &offset, data_recv, sizeof(buff), sizeof(data_recv));
+    if((len > 0) && (len<=FLP_MNL_BUFF_SIZE)) {
+        prmsg = (MTK_FLP_MSG_T *)&data_recv[0];
+    } else {
+        LOGE("len err:%d",len);
+        return ret;
+    }
+
+    switch (prmsg->type) {
+        case MTK_FLP_MSG_HAL_INIT_CMD:                  //process init request from HAL
+            break;
+        case MTK_FLP_MSG_HAL_START_CMD:               //process init request from HAL
+        case MTK_FLP_MSG_HAL_STOP_CMD:                //process init request from HAL
+        case MTK_FLP_MSG_HAL_SET_OPTION_CMD:            //process init request from HAL
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                mtk_flp2mnl_process(prmsg);
+            } else {
+                mtk_flp_controller_process(prmsg);
+            }
+            break;
+        case MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF:      //process init request from HAL
+        case MTK_FLP_MSG_CONN_SCREEN_STATUS:            //process synch screen status from HAL
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                mtk_flp2mnl_process(prmsg);             //send HAL(AP)->Kernel(connsys) msg here
+            }
+            break;
+        case MTK_FLP_MSG_HAL_REQUEST_LOC_NTF:           //message from JNI, need forwarding only.
+        case MTK_FLP_MSG_HAL_FLUSH_LOC_NTF:             //message from JNI, need forwarding only.
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                mtk_flp2mnl_process(prmsg);
+            } else {
+                put_binary(buff, &offset, (const char*)prmsg, sizeof(MTK_FLP_MSG_T)+ sizeof(prmsg->length));
+                ret = mnl_send2flp(buff, offset);
+                if(ret < 0) {
+                    LOGE("MTK_FLP2HAL send error return error");
+                }
+            }
+            break;
+        default:
+            LOGE("FLP HAL: Uknown msessage, type:0x%02x", prmsg->type);
+            break;
+    }
+    return ret;
+}
+
+/************************************************************************/
+//  Handle FLP Request                                                  */
+/************************************************************************/
+int flp2mnl_hdlr(MTK_FLP_MNL_MSG_T  *prMsg) {
+    int ret = MTK_FLP_ERROR, read_len;
+
+    if(prMsg != NULL) {
+        read_len = prMsg->length + sizeof(MTK_FLP_MNL_MSG_HEADER_T);
+        LOGD("[FLP2MNLD]data from flp: type=0x%02x, session_id=%u, len=%d, read_len = %d\n", prMsg->type, prMsg->session, prMsg->length, read_len);
+        //mnl_flp_dump_buf((char*)prMsg, read_len);
+    } else {
+        LOGE("flp2mnl_hdlr recv null msg");
+        return ret;
+    }
+    if(flp2mnl_hdlr_cb == NULL) {
+        LOGE("flp2mnl_hdlr_cb is NULL");
+        return ret;
+    }
+
+    switch (prMsg->type) {
+        case MNLD_FLP_TYPE_FLP_ATTACH: {
+            if (flp2mnl_hdlr_cb->mnld_flp_attach) {
+                flp2mnl_hdlr_cb->mnld_flp_attach();
+                if (mnld_flp_session_update() == -1) {
+                    LOGE("mnld_main_thread() mnld_flp_session_update failed");
+                }
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr_cb() mnld_flp_attach is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_HBD_GPS_OPEN: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_hbd_gps_open) {
+                flp2mnl_hdlr_cb->mnld_flp_hbd_gps_open();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_hbd_gps_open is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_hbd_gps_close) {
+                flp2mnl_hdlr_cb->mnld_flp_hbd_gps_close();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_hbd_gps_close is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_OFL_LINK_OPEN: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_ofl_link_open) {
+                flp2mnl_hdlr_cb->mnld_flp_ofl_link_open();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_ofl_link_open is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_ofl_link_close) {
+                flp2mnl_hdlr_cb->mnld_flp_ofl_link_close();
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_ofl_link_close is NULL");
+            }
+            break;
+        }
+        case MNLD_FLP_TYPE_OFL_LINK_SEND: {
+            if (prMsg->session != mnld_flp_session.id) {
+                LOGE("flp2mnl_hdlr() session_id doesn't match, ignore");
+                break;
+            }
+            if (flp2mnl_hdlr_cb->mnld_flp_ofl_link_send) {
+                flp2mnl_hdlr_cb->mnld_flp_ofl_link_send(prMsg);
+                ret = MTK_FLP_SUCCESS;
+            } else {
+                LOGE("flp2mnl_hdlr() mnld_flp_ofl_link_send is NULL");
+            }
+            break;
+        }
+        default: {
+            LOGE("flp2mnl_hdlr() unknown cmd=0x%02x", prMsg->type);
+            break;
+        }
+    }
+    return ret;
+}
+
+int create_flphal2mnl_fd() {
+    int fd = flp_bind_udp_socket(FLP_TO_MNL);
+    flp_set_socket_blocking(fd, 0);
+    return fd;
+}
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_mnl_interface.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_mnl_interface.c
new file mode 100644
index 0000000..38a042e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_mnl_interface.c
@@ -0,0 +1,473 @@
+/*****************************************************************************
+ * Include
+ *****************************************************************************/
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>  /* UNIX standard function definitions */
+#include <fcntl.h>   /* File control definitions */
+#include <errno.h>   /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <math.h>
+#include "mtk_flp_controller.h"
+#include "data_coder.h"
+//#include "mtk_flp_wake_monitor.h"
+#include "mtk_auto_log.h"
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "flpint"
+#endif
+
+#define MAX_FLP_BATCHING_MSG   10
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+static unsigned int fgMnldStatus = MNL_STATUS_NONE;
+static unsigned int gCurrentSession = 0;
+static unsigned int gCurrentSupport = 0;
+
+static int gFlp2mnl_cnt = 0;
+static MTK_FLP_MNL_MSG_T gFlp2mnl_msg[MAX_FLP_BATCHING_MSG];
+
+enum{
+    CMD_FLP_REPORT_GNSS_LOC = 58,
+};
+
+
+static int mtk_flp_gpsloc2flploc(GpsLocation* gpsloc, FlpLocation *flploc) {
+    if (gpsloc == NULL || flploc == NULL) {
+        return MTK_FLP_ERROR;
+    }
+
+    memset(flploc,0,sizeof(FlpLocation));
+    flploc->size = sizeof(FlpLocation);
+    flploc->sources_used = FLP_TECH_MASK_GNSS;
+    flploc->accuracy = 1.7*(gpsloc->accuracy); //convert accuracy from 67% to 95%
+    flploc->altitude = gpsloc->altitude;
+    flploc->bearing = gpsloc->bearing;
+    flploc->flags =gpsloc->flags;
+    flploc->latitude = gpsloc->latitude;
+    flploc->longitude = gpsloc->longitude;
+    flploc->speed = gpsloc->speed;
+    flploc->timestamp = gpsloc->timestamp;//mtk_flp_get_timestamp(NULL);
+    #if 0
+    LOGD("[DC_GNSS]:dc2gnss: acc:%.4f,alt:%.4f,bearing:%.4f,flag:%d,lat:%.4f,lon:%.4f,spd:%.4f",
+    flploc->accuracy,flploc->altitude,flploc->bearing,flploc->flags,flploc->latitude,
+    flploc->longitude,flploc->speed);
+    #endif
+
+    return MTK_FLP_SUCCESS;
+}
+
+static void mtk_flp_dc_loc_rearrange(MTK_FLP_LOCATION_T *loc_in, MTK_FLP_LOCATION_T *loc_out) {
+    loc_out->size = loc_in->size;
+    loc_out->sources_used = loc_in->sources_used;
+    loc_out->flags = loc_in->flags;
+    loc_out->latitude = loc_in->latitude;
+    loc_out->longitude = loc_in->longitude;
+    loc_out->accuracy = loc_in->accuracy;
+    loc_out->altitude = loc_in->altitude;
+    loc_out->speed = loc_in->speed;
+    loc_out->bearing = loc_in->bearing;
+    loc_out->timestamp = loc_in->timestamp;
+    #if 0
+    LOGD("Loc from CNN:LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+    loc_out->longitude, loc_out->latitude, loc_out->altitude, loc_out->accuracy,
+    loc_out->speed, loc_out->bearing, loc_out->flags, loc_out->sources_used, loc_out->timestamp);
+    LOGD("Loc processed:LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+    loc_in->longitude, loc_in->latitude, loc_in->altitude, loc_in->accuracy,
+    loc_in->speed, loc_in->bearing, loc_in->flags, loc_in->sources_used, loc_in->timestamp);
+    #endif
+}
+
+#if 0
+void mtk_flp2mnl_send_screen_state() {
+    MTK_FLP_MNL_MSG_HEADER_T *flp2mnl_msg;
+    MTK_FLP_MSG_T flp2cnn_msg;
+    unsigned char screen_state = 0;
+    mtk_flp_get_wake_monitor_state(&screen_state);
+    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T) + sizeof(MTK_FLP_MSG_T) + sizeof(unsigned char));
+  if(flp2mnl_msg != NULL) {
+    flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+    flp2mnl_msg->session= gCurrentSession;
+    flp2mnl_msg->length = sizeof(MTK_FLP_MSG_T) + sizeof(UINT8);
+    flp2cnn_msg.type = MTK_FLP_MSG_CONN_SCREEN_STATUS;
+    flp2cnn_msg.length = sizeof(UINT8);
+    memcpy(((char*)flp2mnl_msg) + sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)&flp2cnn_msg), sizeof(MTK_FLP_MSG_T));
+    memcpy(((char*)flp2mnl_msg) + sizeof(MTK_FLP_MNL_MSG_HEADER_T) + sizeof(MTK_FLP_MSG_T), &screen_state, sizeof(unsigned char));
+    LOGD("Send to OFL FLP, screen_state = %u", screen_state);
+    flp2mnl_hdlr(flp2mnl_msg);
+    free(flp2mnl_msg);
+  }
+}
+#endif
+
+/************************************************************************/
+//  Process msgs from FLP HAL and send to offload kernel
+/************************************************************************/
+int mtk_flp2mnl_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_FLP_MNL_MSG_HEADER_T* flp2mnl_msg = NULL;
+    MTK_FLP_MSG_T flp2cnn_msg;
+
+    if(prmsg == NULL) {
+        LOGD("mtk_flp2mnl_process, recv prmsg is null pointer\n");
+        return MTK_FLP_ERROR;
+    }
+
+    LOGD("mtk_flp2mnl_process, recv prmsg, type:%d, len:%d status:%u\r\n", prmsg->type, prmsg->length, fgMnldStatus);
+
+    switch(prmsg->type) {
+        case MTK_FLP_MSG_HAL_START_CMD:
+        case MTK_FLP_MSG_HAL_DIAG_INJECT_DATA_NTF:
+            if (fgMnldStatus != MNL_STATUS_OFL_LINK_OPEN_DONE) {
+                if (gFlp2mnl_cnt == 0) {
+                    //send init message to mnld first
+                    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T)); //send header only, no message body
+                    if(flp2mnl_msg != NULL) {
+                        flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN;
+                        flp2mnl_msg->session = gCurrentSession;
+                        flp2mnl_msg->length = 0;
+                        LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN");
+                        fgMnldStatus = MNL_STATUS_OFL_LINK_OPEN;
+                        flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                        free(flp2mnl_msg);
+                    }
+                }
+                if (gFlp2mnl_cnt < MAX_FLP_BATCHING_MSG) {
+                    gFlp2mnl_msg[gFlp2mnl_cnt].type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                    gFlp2mnl_msg[gFlp2mnl_cnt].length = prmsg->length + sizeof(MTK_FLP_MSG_T);
+                    gFlp2mnl_msg[gFlp2mnl_cnt].session = gCurrentSession;
+                    memcpy(&gFlp2mnl_msg[gFlp2mnl_cnt].data[0], ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ prmsg->length));
+                    gFlp2mnl_cnt++;
+                    LOGD("Keep flp data cnt %d", gFlp2mnl_cnt);
+                } else {
+                    LOGD("Batching size overflow");
+                }
+            }
+            break;
+        case MTK_FLP_MSG_HAL_STOP_CMD:
+            //send msg stop mnl first
+            flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+sizeof(MTK_FLP_MSG_T));
+            if(flp2mnl_msg != NULL) {
+                flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                flp2mnl_msg->session = gCurrentSession;
+                flp2mnl_msg->length = sizeof(MTK_FLP_MSG_T); // data sent structure: [type, length for AP_conn recognition] + [type,length]
+                flp2cnn_msg.type = MTK_FLP_MSG_HAL_STOP_CMD;
+                flp2cnn_msg.length = 0;
+                memcpy(((char*)flp2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)&flp2cnn_msg), sizeof(MTK_FLP_MSG_T));
+                LOGD("Send to OFL FLP,message type:0x%02x, len:%u", flp2cnn_msg.type, (flp2mnl_msg->length + sizeof(MTK_FLP_MNL_MSG_HEADER_T)));
+                flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                free(flp2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_DC_START_CMD: // host-based start gnss
+            //send init message to mnld first
+            flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T)); //send header only, no message body
+            if(flp2mnl_msg != NULL) {
+                flp2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN;
+                flp2mnl_msg->length = 0;
+                flp2mnl_msg->session = gCurrentSession;
+                LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN");
+                fgMnldStatus = MNL_STATUS_HBD_GPS_OPEN;
+                flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                free(flp2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_DC_STOP_CMD:
+            //send stop message to mnld
+            flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T)); //send header only, no message body
+            if(flp2mnl_msg != NULL) {
+                flp2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE;
+                flp2mnl_msg->length = 0;
+                flp2mnl_msg->session = gCurrentSession;
+                LOGD("Send to mnld for deinit,message type:0x%02x, len:%d", flp2mnl_msg->type, flp2mnl_msg->length);
+                fgMnldStatus = MNL_STATUS_HBD_GPS_CLOSE;
+                flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                free(flp2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_CONN_SCREEN_STATUS:
+            if(fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE) {
+                flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+ sizeof(MTK_FLP_MSG_T)+prmsg->length);
+                if(flp2mnl_msg != NULL) {
+                    flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                    flp2mnl_msg->session = gCurrentSession;
+                    flp2mnl_msg->length = (prmsg->length) + sizeof(MTK_FLP_MSG_T);
+                    memcpy(((char*)flp2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ (prmsg->length)));
+                    LOGD("Send to OFL FLP,message type:0x%02x, len:%d", prmsg->type, (flp2mnl_msg->length + sizeof(MTK_FLP_MSG_T)));
+                    flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                    free(flp2mnl_msg);
+                }
+            } else {
+                LOGD("free screen dbg");
+            }
+            break;
+        default:
+            if(mtk_flp_get_sys_mode() == FLP_OFFLOAD_MODE) {
+                if(fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE) {
+                    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+ sizeof(MTK_FLP_MSG_T)+prmsg->length);
+                    if(flp2mnl_msg != NULL) {
+                        flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;  //for loopback test between mnld & FLP AP  use FLP_MNL_CMD_LOOPBACK
+                        flp2mnl_msg->session = gCurrentSession;
+                        flp2mnl_msg->length = (prmsg->length) + sizeof(MTK_FLP_MSG_T); // data sent structure: [type, length for AP_conn recognition] + [type,length+buff for flp recognition]
+                        memcpy(((INT8*)flp2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((INT8*)prmsg), (sizeof(MTK_FLP_MSG_T)+ (prmsg->length)));
+                        flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                        free(flp2mnl_msg);
+                    }
+                } else {
+                    LOGD("mnld_ret=%u", fgMnldStatus);
+                }
+            }
+            break;
+    }
+    return MTK_FLP_SUCCESS;
+}
+
+/************************************************************************/
+//  Handle MNL Response                                                 */
+/************************************************************************/
+int mnl2flp_hdlr(MTK_FLP_MNL_MSG_T* prmsg) {
+    char buff[HAL_FLP_BUFF_SIZE] = {0};
+    int ret, i;
+    int offset = 0;
+    MTK_FLP_MNL_MSG_HEADER_T *flp2mnl_msg = NULL;
+    MTK_FLP_MSG_T *flp2hal_msg = NULL;
+    MTK_FLP_MSG_T *cnn2flp_msg = NULL;
+    MTK_FLP_LOCATION_T  loc_in, loc_out;
+    GpsLocation  *gps_loc;
+    MTK_FLP_LOCATION_T  flp_loc;
+
+    if(prmsg == NULL) {
+        LOGD("mnl2flp_hdlr recv null msg");
+        return MTK_FLP_ERROR;
+        }
+
+    LOGD("mtk_mnl2flp_recv_msg type = 0x%02x, session = %u, len = %u, state = %u\n",  prmsg->type, prmsg->session, prmsg->length, fgMnldStatus);
+
+    switch(prmsg->type) {
+        case MNLD_FLP_TYPE_MNL_BOOTUP:
+            fgMnldStatus = MNL_STATUS_ATTACH_DONE;
+            flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+            if(flp2hal_msg == NULL) {
+                LOGE("reset ntf malloc failed");
+                return MTK_FLP_ERROR;
+            }
+            flp2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+            flp2hal_msg->length = 0;
+            put_binary(buff, &offset, (const char*)flp2hal_msg, sizeof(MTK_FLP_MSG_T));
+            ret = mnl_send2flp(buff, offset);
+            free(flp2hal_msg);
+            if(ret < 0) {
+                LOGD("MTK_FLP2HAL send error return error");
+            }
+            break;
+        case MNLD_FLP_TYPE_SESSION_UPDATE:
+            gCurrentSession = prmsg->session;
+            memcpy(&gCurrentSupport, ((char*)prmsg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), sizeof(gCurrentSupport));
+            LOGD("SESSION_UPDATE %u support %u mode %u", gCurrentSession, gCurrentSupport, fgMnldStatus);
+            if (fgMnldStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && gCurrentSupport == FLP_AP_MODE) {
+                LOGD("SESSION_UPDATE: already run on host");
+            } else if (fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport & FLP_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: already run on offlaod");
+            } else if (fgMnldStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && (gCurrentSupport & FLP_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ofl mode");
+                mtk_flp_controller_reset_status();
+                mtk_flp_set_sys_mode(FLP_OFFLOAD_MODE);
+
+                flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(flp2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                flp2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                flp2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)flp2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2flp(buff, offset);
+                free(flp2hal_msg);
+                if(ret < 0) {
+                    LOGD("mnl2flp_hdlr send error return error");
+                }
+            } else if (fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport == FLP_AP_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ap mode");
+                mtk_flp_set_sys_mode(FLP_AP_MODE);
+                flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(flp2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                flp2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                flp2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)flp2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2flp(buff, offset);
+                free(flp2hal_msg);
+                if(ret < 0) {
+                    LOGD("mnl2flp_hdlr send error return error");
+                }
+            } else {
+                if (gCurrentSupport & FLP_OFFLOAD_MODE) {
+                    mtk_flp_set_sys_mode(FLP_OFFLOAD_MODE);
+                    LOGD("SESSION_UPDATE: set offload mode");
+                } else if (gCurrentSupport == FLP_AP_MODE) {
+                    mtk_flp_set_sys_mode(FLP_AP_MODE);
+                    LOGD("SESSION_UPDATE: set ap mode");
+                }
+            }
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_LOCATION:
+            gps_loc = (GpsLocation *)(((char*)prmsg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T));
+            //LOGD("GNSS LOC DBG: %f, %lf, %lf, %d", gps_loc->accuracy, gps_loc->latitude, gps_loc->longitude, gps_loc->size);
+
+            if(mtk_flp_gpsloc2flploc(gps_loc, (FlpLocation *)&flp_loc) != MTK_FLP_SUCCESS) {
+                LOGD("Incorrect data received");
+            } else {
+                if (mtk_flp_controller_report_loc(flp_loc) == -1) {
+                    break;
+                }
+                //send loc to FLP HAL
+                if(mtk_flp_controller_query_mode() > MTK_FLP_IDLE_MODE) {
+                    flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(MTK_FLP_LOCATION_T));
+                    if(flp2hal_msg == NULL) {
+                        LOGE("report loc malloc failed");
+                        return MTK_FLP_ERROR;
+                    }
+                    flp2hal_msg->type = MTK_FLP_MSG_HSB_REPORT_LOC_NTF;
+                    flp2hal_msg->length = sizeof(MTK_FLP_LOCATION_T);
+                    memcpy((char *)flp2hal_msg + sizeof(MTK_FLP_MSG_T),&flp_loc, sizeof(MTK_FLP_LOCATION_T) );
+                    put_binary(buff, &offset, (const char*)flp2hal_msg, (sizeof(MTK_FLP_MSG_T)+flp2hal_msg->length));
+                    ret = mnl_send2flp(buff, offset);
+                    free(flp2hal_msg);
+                    if(ret < 0) {
+                        LOGD("MTK_FLP2HAL send error return error");
+                    }
+                }
+#if 0 // android o no diag CB
+                //send location diag ntf
+                if(mtk_flp_controller_query_mode() > MTK_FLP_IDLE_MODE) {
+                sprintf(localbuf,"FLP_NTF=LNG:%f LAT:%f ALT:%f", flp_loc.longitude, flp_loc.latitude, flp_loc.altitude);
+                LOGD("%s",localbuf);
+                flp2hal_diag = malloc(sizeof(MTK_FLP_MSG_T)+strlen(localbuf));
+                if(flp2hal_diag == NULL) {
+                LOGE("diag report malloc failed");
+                return MTK_FLP_ERROR;
+                }
+                memset(buff,0,HAL_FLP_BUFF_SIZE*sizeof(char));
+                offset = 0;
+                flp2hal_diag->type = MTK_FLP_MSG_HAL_DIAG_REPORT_DATA_NTF;
+                flp2hal_diag->length = strlen(localbuf);
+                memcpy((char *)flp2hal_diag + sizeof(MTK_FLP_MSG_T),&localbuf[0], strlen(localbuf) );
+                put_binary(buff, &offset, (const char*)flp2hal_diag, (sizeof(MTK_FLP_MSG_T)+flp2hal_diag->length));
+                ret = mnl_send2flp(buff, offset);
+                free(flp2hal_diag);
+                if(ret < 0) {
+                LOGD("MTK_FLP2HAL send error return error");
+                }
+                }
+#endif
+            }
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_RECV:
+            cnn2flp_msg = malloc(prmsg->length);
+            if(cnn2flp_msg == NULL) {
+                return MTK_FLP_ERROR;
+            }
+            memcpy((char*)cnn2flp_msg, ((char*)prmsg)+ sizeof(MTK_FLP_MNL_MSG_HEADER_T), prmsg->length);
+            LOGD("Received OFFLOAD message type: 0x%02x, len = %u", cnn2flp_msg->type, cnn2flp_msg->length);
+            switch(cnn2flp_msg->type) {
+                case MTK_FLP_MSG_HAL_STOP_RSP:
+                    //send stop message to mnld
+                    flp2mnl_msg = (MTK_FLP_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_FLP_MNL_MSG_HEADER_T));
+                    if(flp2mnl_msg!= NULL) {
+                        flp2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE;
+                        flp2mnl_msg->session= gCurrentSession;
+                        flp2mnl_msg->length = 0;
+                        //LOGD("Send to mnld for deinit,message type:%u, len:%u", flp2mnl_msg->type, flp2mnl_msg->length);
+                        flp2mnl_hdlr((MTK_FLP_MNL_MSG_T *)flp2mnl_msg);
+                        fgMnldStatus = MNL_STATUS_OFL_LINK_CLOSE;
+                        free(flp2mnl_msg);
+                        LOGD("mnld deinit success");
+                    }
+                    break;
+                case MTK_FLP_MSG_OFL_REPORT_LOC_NTF:
+                    //check location size
+                    if(cnn2flp_msg->length >= (int)sizeof(MTK_FLP_LOCATION_T)) {
+                        //LOGD("size check: %d %d \n", (cnn2flp_msg->length), sizeof(MTK_FLP_LOCATION_T));
+                        memcpy(&loc_in, ((char*)cnn2flp_msg)+sizeof(MTK_FLP_MSG_T), sizeof(MTK_FLP_LOCATION_T));
+                        mtk_flp_dc_loc_rearrange(&loc_in, &loc_out);
+
+                        //send loc to FLP HAL
+                        flp2hal_msg = malloc(sizeof(MTK_FLP_MSG_T)+sizeof(MTK_FLP_LOCATION_T));
+                        if(flp2hal_msg == NULL) {
+                            LOGE("report loc malloc failed");
+                            free(cnn2flp_msg);
+                            return MTK_FLP_ERROR;
+                        }
+                        flp2hal_msg->type = cnn2flp_msg->type;
+                        flp2hal_msg->length = sizeof(MTK_FLP_LOCATION_T);
+                        memcpy((char *)flp2hal_msg + sizeof(MTK_FLP_MSG_T),&loc_out, sizeof(MTK_FLP_LOCATION_T) );
+                        put_binary(buff, &offset, (const char*)flp2hal_msg, (sizeof(MTK_FLP_MSG_T)+flp2hal_msg->length));
+                        ret = mnl_send2flp(buff, offset);
+                        free(flp2hal_msg);
+                        if(ret < 0) {
+                            LOGD("MTK_FLP2HAL send error return error");
+                        }
+                    }
+                    break;
+                default:
+                    if(cnn2flp_msg->type < MTK_FLP_MSG_END) {
+                        put_binary(buff, &offset, (const char*)cnn2flp_msg, sizeof(MTK_FLP_MSG_T)+cnn2flp_msg->length);
+                        ret = mnl_send2flp(buff, offset);
+                        if(ret < 0) {
+                            LOGD("MTK_FLP2HAL send error return error");
+                        }
+                    }
+                    break;
+            }
+            free(cnn2flp_msg);
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE:
+            fgMnldStatus = MNL_STATUS_HBD_GPS_OPEN_DONE;
+            LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE:
+            fgMnldStatus = MNL_STATUS_HBD_GPS_CLOSE_DONE;
+            LOGD("MNL_STATUS_HBD_GPS_CLOSE_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE:
+            if (fgMnldStatus == MNL_STATUS_OFL_LINK_OPEN) {
+                fgMnldStatus = MNL_STATUS_OFL_LINK_OPEN_DONE;
+                LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE flush %d", gFlp2mnl_cnt);
+                for (i = 0; i < gFlp2mnl_cnt; i++) {
+                    flp2mnl_hdlr(&gFlp2mnl_msg[i]);
+                }
+                gFlp2mnl_cnt = 0;
+            } else {
+                LOGD("FLP_DBG: mnld state expect 7, get %u", fgMnldStatus);
+            }
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE:
+            fgMnldStatus = MNL_STATUS_OFL_LINK_CLOSE_DONE;
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE");
+            break;
+        default:
+            LOGE("undefined cmd:0x%02x",prmsg->type);
+            break;
+    }
+    return MTK_FLP_SUCCESS;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_screen_monitor.c b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_screen_monitor.c
new file mode 100644
index 0000000..a6c6b77
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_flp_interface/src/mtk_flp_screen_monitor.c
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/inotify.h>
+#include "data_coder.h"
+#include "mtk_gps.h"
+#include "mnld.h"
+#include "mtk_flp_screen_monitor.h"
+#include "mtk_flp_main.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "flpscreen"
+#endif
+
+#define MNLD_STRNCPY(dst,src,size) do{\
+                                       strncpy((char *)(dst), (src), (size - 1));\
+                                      (dst)[size - 1] = '\0';\
+                                     }while(0)
+
+/**********************************************************
+ *  Global vars                                           *
+ **********************************************************/
+static UINT8 earlysuspend_state = EARLYSUSPEND_ON;
+static pthread_mutex_t earlysuspend_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t earlysuspend_cond = PTHREAD_COND_INITIALIZER;
+
+/**********************************************************
+ *  Function Declaration                                  *
+ **********************************************************/
+static int wait_for_fb_wake(void) {
+    int ino_len;
+    int ino_fd;
+    int ino_wd;
+    char ino_buf[1024];
+    char buf[100];
+    FILE *fd;
+    while(1) {
+        ino_fd = inotify_init();
+        if(ino_fd < 0) {
+            LOGE("inotify_init error");
+            return 1;
+        }
+        ino_wd = inotify_add_watch(ino_fd, "/sys/power/wake_lock", IN_MODIFY);
+        if (ino_wd == -1) {
+            LOGE("inotify add fail: %s(%d)\n", strerror(errno), errno);
+            return 1;
+        }
+        ino_len = read(ino_fd, ino_buf, 1024);
+        if(ino_len < 0) {
+            LOGE("inotify read error");
+            return 1;
+        }
+        (void)inotify_rm_watch(ino_fd, ino_wd);
+        (void)close(ino_fd);
+
+        fd = fopen("/sys/power/wake_lock" , "r");
+        if(fd) {
+            while(fscanf(fd, "%99s", buf) != EOF) {
+                if(strstr(buf, "Display") != NULL) {
+                    fclose(fd);
+                    return 0;
+                }
+            }
+        }
+        else {
+            LOGE("fopen error\n");
+            return 1;
+        }
+        fclose(fd);
+    }
+}
+
+static int wait_for_fb_sleep(void)
+{
+    int ino_len;
+    int ino_fd;
+    int ino_wd;
+    char ino_buf[1024];
+    char buf[100];
+    FILE *fd;
+    while(1) {
+        ino_fd = inotify_init();
+        if (ino_fd < 0) {
+            LOGE("inotify_init error");
+            return 1;
+        }
+        ino_wd = inotify_add_watch(ino_fd, "/sys/power/wake_unlock", IN_MODIFY);
+        if (ino_wd == -1) {
+            LOGE("inotify add fail: %s(%d)\n", strerror(errno), errno);
+            return 1;
+        }
+        ino_len = read(ino_fd, ino_buf, 1024);
+        if (ino_len < 0) {
+            LOGE("inotify read error");
+            return 1;
+        }
+        (void)inotify_rm_watch(ino_fd, ino_wd);
+        (void)close(ino_fd);
+
+        fd = fopen("/sys/power/wake_unlock" , "r");
+        if(fd) {
+            while(fscanf(fd, "%99s", buf) != EOF) {
+                if (strstr(buf, "Display") != NULL) {
+                    fclose(fd);
+                    return 0;
+                }
+            }
+        } else {
+            LOGE("fopen error\n");
+            return 1;
+        }
+        fclose(fd);
+    }
+}
+
+static int flp_screen_send2mnl(const char* buff, int len) {
+    int ret = 0;
+    if (safe_sendto("flp_to_mnl", buff, len) < 0) {
+        LOGE("flp_screen_send2mnl safe_sendto flp failed\n");
+        ret = -1;
+    }
+    if (safe_sendto("gfc_to_mnl", buff, len) < 0) {
+        LOGE("flp_screen_send2mnl safe_sendto gfc failed\n");
+        ret = -1;
+    }
+    return ret;
+}
+
+static void* flp_screen_monitor_thread(void *arg) {
+    MTK_FLP_MSG_T *flp_header;
+    int ret, offset = 0;
+    char buff[HAL_FLP_BUFF_SIZE] = {0};
+    UNUSED(arg);
+
+    LOGE("Create\n");
+    while (1) {
+        LOGE("Wake Monitor Restart");
+        if (wait_for_fb_sleep()) {
+            LOGE("Failed reading wait_for_fb_sleep");
+            break;
+        }
+        pthread_mutex_lock(&earlysuspend_mutex);
+        earlysuspend_state = EARLYSUSPEND_MEM;
+        pthread_cond_signal(&earlysuspend_cond);
+        pthread_mutex_unlock(&earlysuspend_mutex);
+        LOGE("Screen off");
+
+        //Send NTF to CONNsys
+        offset = 0;
+        flp_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(UINT8));
+        if (flp_header) {
+            flp_header->type = MTK_FLP_MSG_CONN_SCREEN_STATUS;
+            flp_header->length = sizeof(UINT8);
+            memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&earlysuspend_state, sizeof(UINT8));
+            put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));
+            ret = flp_screen_send2mnl(buff, offset);
+            free(flp_header);
+        }
+
+        if (wait_for_fb_wake()) {
+            LOGE("Failed reading wait_for_fb_wake");
+            break;
+        }
+        pthread_mutex_lock(&earlysuspend_mutex);
+        earlysuspend_state = EARLYSUSPEND_ON;
+        pthread_cond_signal(&earlysuspend_cond);
+        pthread_mutex_unlock(&earlysuspend_mutex);
+        LOGE("Screen on");
+
+        offset = 0;
+        flp_header = malloc(sizeof(MTK_FLP_MSG_T) + sizeof(UINT8));
+        if (flp_header) {
+            flp_header->type = MTK_FLP_MSG_CONN_SCREEN_STATUS;
+            flp_header->length = sizeof(UINT8);
+            memcpy((char *)flp_header +sizeof(MTK_FLP_MSG_T),&earlysuspend_state, sizeof(UINT8));
+            put_binary(buff, &offset, (const char*)flp_header, (flp_header->length+sizeof(MTK_FLP_MSG_T)));
+            ret = flp_screen_send2mnl(buff, offset);
+            free(flp_header);
+        }
+    }
+
+    LOGE("exit\n");
+    pthread_exit(NULL);
+    return 0;
+}
+
+void mtk_flp_get_wake_monitor_state(UINT8 *state) {
+    if(state) {
+        memcpy(state, &earlysuspend_state, sizeof(UINT8));
+    }
+}
+
+void flp_monitor_init() {
+    pthread_t pthread_wakelock;
+    pthread_create(&pthread_wakelock, NULL, flp_screen_monitor_thread, NULL);
+}
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/Geofence.h b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/Geofence.h
new file mode 100644
index 0000000..d7bcb06
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/Geofence.h
@@ -0,0 +1,134 @@
+#ifndef _GEOFENCE_H_
+#define _GEOFENCE_H_
+
+#include <time.h>
+#include <stdint.h>
+
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#include <hardware/fused_location.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#include "fused_location.h"
+#endif
+
+#define GEO_CONFIG_MASK_DISABLE_SMD     (1U<<0)
+
+typedef enum {
+    inside,
+    outside,
+    uncertain
+} SET_STATE;
+
+typedef enum {
+    INIT_GEOFENCE,
+    ADD_GEOFENCE_AREA,
+    PAUSE_GEOFENCE,
+    RESUME_GEOFENCE,
+    REMOVE_GEOFENCE,
+    RECOVER_GEOFENCE,
+    CLEAR_GEOFENCE,
+} MTK_GFC_COMMAND_T;
+
+typedef enum {
+    SMART_NO_TRIGGER       = 0,
+    SMART_ACC_TRIGGER      = 1,
+    SMART_TIMEOUT_TRIGGER  = 2,
+} MTK_SMART_GEOFENCE_T;
+
+typedef enum {
+    MTK_GEOFENCE_IDLE_MODE = -1,
+    MTK_BATCH_GEOFENCE_ONLY = 3,
+    MTK_SMART_GEOFENCE_MODE = 4,
+} MTK_GFC_MODE_T;
+
+typedef enum {
+    GFC_AP_MODE      = 1,
+    GFC_OFFLOAD_MODE = 2,
+} MTK_GFC_SYS_MODE_T;
+
+typedef struct {
+    unsigned int type;
+    unsigned int session;
+    unsigned int length;
+} MTK_GFC_MNL_MSG_HEADER_T;
+
+typedef struct {
+    unsigned int type;   // 1:AP mode(default)   2: Offload mode  3:AP+Offload mode
+    unsigned int pre_type;
+    unsigned int id;
+} MTK_GFC_Session_T;
+
+typedef enum {
+    GEOFENCE_ADD_CALLBACK,
+    GEOFENCE_REMOVE_CALLBACK,
+    GEOFENCE_PAUSE_CALLBACK,
+    GEOFENCE_RESUME_CALLBACK
+} GEOFENCE_CALLBACK_T;
+
+typedef struct mtk_geofence_callback {
+    int32_t cb_id;
+    int32_t geofence_id;
+    int32_t result;
+} MTK_GEOFENCE_CALLBACK_T;
+
+typedef struct mtk_geofence_area {
+    int32_t geofence_id;
+    double latitude;
+    double longitude;
+    double radius;
+    float coordinate_dn;
+    float coordinate_de;
+    int last_transition; /*current state, most cases is GPS_GEOFENCE_UNCERTAIN*/
+    int monitor_transition; /*bitwise or of  entered/exited/uncertain*/
+    int notification_period;/*timer  interval, period of report transition status*/
+    int unknown_timer;/*continue positioning time limitied while positioning*/
+    int alive;/*geofence status, 1 alive, 0 sleep*/
+    SET_STATE latest_state;/*latest status: outside, inside, uncertain*/
+    uint32_t config;
+} MTK_GEOFENCE_PROPERTY_T;
+
+typedef struct mtk_pause_geofence {
+    int32_t geofence_id;
+} MTK_PAUSE_GEOFENCE_T;
+
+typedef struct mtk_resume_geofence {
+    int32_t geofence_id;
+    int transition;
+} MTK_RESUME_GEOFENCE_T;
+
+typedef struct mtk_remove_geofence {
+    int32_t geofence_id;
+} MTK_REMOVE_GEOFENCE_T;
+
+typedef struct mtk_modify_geofence {
+    int32_t geofence_id;
+    uint32_t source_to_use; /* source to use for geofence */
+    int last_transition; /*current state, most cases is GPS_GEOFENCE_UNCERTAIN*/
+    int monitor_transition; /*bitwise or of  entered/exited/uncertain*/
+    int notification_period;/*timer  interval, period of report transition status*/
+    int unknown_timer;/*continue positioning time limitied while positioning*/
+} MTK_MODIFY_GEOFENCE;
+
+typedef float          R4;      // 4 byte floating point
+typedef double         R8;      // 8 byte floating point
+
+typedef struct geofence_new_alarm {
+    unsigned int unknown_init_ttick;  //record the ttick of fence starting time
+    int unknown_elapsed_ttick;  //update the ttick elapsed time since the starting time
+    int geofence_operating_mode; //[start, stop/ pause] = [0,1]
+} GEOFENCE_NEW_ALARM_T;
+
+typedef enum {
+    START,
+    STOP,
+    UNKNOW
+} MTK_GEOFENCE_ACTION;
+
+//static int start_unknown_monitor(const int item);
+unsigned int update_fence_source();
+void mtk_flp_geofence_clear_geofences();
+void  mtk_set_geofence_location(const FlpLocation* location);
+
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h
new file mode 100644
index 0000000..e39cea0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/inc/mtk_geofence_main.h
@@ -0,0 +1,90 @@
+#ifndef MTK_GEOFENCE_H

+#define MTK_GEOFENCE_H

+

+#include <stdint.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <stdbool.h>

+#include <time.h>

+#include <sys/socket.h>

+#include "mtk_gps_type.h"

+#include "Geofence.h"

+#include "mtk_flp_main.h"

+#include "mtk_auto_log.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define GEOFENCE_VERSION_HEAD 'G','F','C','_','V','E','R','_'

+#define GEOFENCE_MAJOR_VERSION '1','7','0','6','1','9','0','1'  // y,y,m,m,d,d,rev,rev

+#define GEOFENCE_BRANCH_INFO '_','0','.','5','8','_'

+#define GEOFENCE_MINER_VERSION 'N','1'

+#define GEOFENCE_VER_INFO GEOFENCE_VERSION_HEAD,GEOFENCE_MAJOR_VERSION,GEOFENCE_BRANCH_INFO,GEOFENCE_MINER_VERSION

+

+

+//======================================================

+// GEOFENCE -> GPS/GEOFENCE HAL

+//======================================================

+#define GEOFENCE_TO_MNL "gfc_to_mnl"

+#define MNL_TO_GEOFENCE "mnl_to_gfc"

+

+#define MTK_GFC_SUCCESS     (0)

+#define MTK_GFC_ERROR       (-1)

+#define MTK_GFC_TIMEOUT     (-2)

+

+#define MNLD_GFC_CAPABILITY_AP_MODE      1

+#define MNLD_GFC_CAPABILITY_OFL_MODE     2

+#define MNLD_GFC_CAPABILITY_AP_OFL_MODE  3

+

+#define GFC_MNL_BUFF_SIZE   (1 * 1024)

+#define GFC_MNL_PAYLOAD_LEN 256

+

+typedef struct {

+    unsigned int type;

+    unsigned int session;

+    unsigned int length;

+    unsigned char  data[GFC_MNL_PAYLOAD_LEN];

+} MTK_GFC_MNL_MSG_T;

+

+typedef struct {

+    int (*mnld_gfc_attach)();

+    void (*mnld_gfc_hbd_gps_open)();

+    void (*mnld_gfc_hbd_gps_close)();

+    void (*mnld_gfc_ofl_link_open)();

+    void (*mnld_gfc_ofl_link_close)();

+    int (*mnld_gfc_ofl_link_send)();

+} gfc2mnl_interface;

+

+

+//Function Declarations

+extern MTK_GFC_Session_T mnld_gfc_session;

+

+int create_gfchal2mnl_fd();

+int mtk_hal2gfc_main_hdlr(int fd, gfc2mnl_interface* hdlr);

+int mnld_gfc_gen_new_session();

+int mnl2gfc_mnld_reboot();

+int mnl2gfc_data_send(unsigned char *buf, unsigned int len);

+int mnld_gfc_attach_done();

+int mnld_gfc_session_update();

+int mnld_gfc_ofl_gps_open_done();

+int mnld_gfc_hbd_gps_open_done();

+int mnld_gfc_ofl_gps_close_done();

+int mnld_gfc_hbd_gps_close_done();

+void mtk_gfc_set_sys_mode (unsigned int sysMode);

+int mtk_gfc_get_sys_mode ();

+int mnl2gfc_hdlr(MTK_GFC_MNL_MSG_T* prmsg);

+int gfc_kernel_2gfc_hdlr(MTK_FLP_MSG_T* prmsg);

+void mtk_gfc_ofl2mnl_process(MTK_FLP_MSG_T *prmsg);

+int mtk_gfc_controller_reset_status(void);

+int mtk_gfc_controller_process(MTK_FLP_MSG_T *prmsg);

+int gfc2mnl_hdlr(MTK_GFC_MNL_MSG_T  *prMsg);

+int mnl_send2gfc(const char* buff, int len);

+

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

+

diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c
new file mode 100644
index 0000000..c5c1895
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_controller.c
@@ -0,0 +1,500 @@
+#include "mtk_geofence_main.h"
+#include "mtk_flp_main.h"
+#include "data_coder.h"
+#include "mtk_auto_log.h"
+
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gps_dbg_log"
+#endif
+
+#define ONE_SEC_NS 1000000000
+#define FLP_TECH_MASK_GNSS      (1U<<0)
+#define MAX_GFC_BATCHING_MSG   100
+
+/**********************************************************
+*  Global vars                                           *
+**********************************************************/
+static unsigned int fgMnldGfcStatus = MNL_STATUS_NONE;
+static unsigned int gCurrentSession = 0;
+static unsigned int gCurrentSupport = 0;
+static unsigned int geofence_enabled = 0;
+static unsigned int flp_geofence_source = 0;
+static int gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+static int32_t geofence_in_use = 0;
+static uint32_t geofence_source_to_use = 0;
+static float current_gnss_acc = 0;
+char pGFCVersion[] = {GEOFENCE_VER_INFO,0x00};
+static MTK_GFC_MNL_MSG_T gGfc2mnl_msg[MAX_GFC_BATCHING_MSG];
+static int gGfc2mnl_cnt = 0;
+
+/**********************************************************
+*  Function Declaration                                  *
+**********************************************************/
+extern void mtk_geofence_offload_main(MTK_FLP_MSG_T *prmsg);
+extern void mtk_flp_geofence_expire();
+
+/************************************************************************/
+//  Process msgs from GPS/GFC HAL and send to offload kernel
+/************************************************************************/
+void mtk_gfc_ofl2mnl_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_GFC_MNL_MSG_HEADER_T* gfc2mnl_msg = NULL;
+    if (prmsg->type == MTK_FLP_MSG_CONN_SCREEN_STATUS) {
+        if(fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN_DONE) {
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_FLP_MNL_MSG_HEADER_T)+ sizeof(MTK_FLP_MSG_T)+prmsg->length);
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+                gfc2mnl_msg->session = gCurrentSession;
+                gfc2mnl_msg->length = (prmsg->length) + sizeof(MTK_FLP_MSG_T);
+                memcpy(((char*)gfc2mnl_msg)+sizeof(MTK_FLP_MNL_MSG_HEADER_T), ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ (prmsg->length)));
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+        } else {
+            LOGD("free screen dbg");
+        }
+        return;
+    }
+    if (fgMnldGfcStatus != MNL_STATUS_OFL_LINK_OPEN_DONE) {
+        if (gGfc2mnl_cnt == 0) {
+            //send init message to mnld first
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //send header only, no message body
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN;
+                gfc2mnl_msg->session = gCurrentSession;
+                gfc2mnl_msg->length = 0;
+                LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN");
+                fgMnldGfcStatus = MNL_STATUS_OFL_LINK_OPEN;
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+        }
+        if (gGfc2mnl_cnt < MAX_GFC_BATCHING_MSG) {
+            gGfc2mnl_msg[gGfc2mnl_cnt].type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+            gGfc2mnl_msg[gGfc2mnl_cnt].length = prmsg->length + sizeof(MTK_FLP_MSG_T);
+            gGfc2mnl_msg[gGfc2mnl_cnt].session = gCurrentSession;
+            memcpy(&gGfc2mnl_msg[gGfc2mnl_cnt].data[0], ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ prmsg->length));
+            gGfc2mnl_cnt++;
+            LOGD("Keep gfc data cnt %d", gGfc2mnl_cnt);
+        } else {
+            LOGD("Batching size overflow");
+        }
+    } else {
+        //send flp message to ofl gfc
+        gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc( sizeof(MTK_GFC_MNL_MSG_HEADER_T)+sizeof(MTK_FLP_MSG_T)+prmsg->length);
+        if(gfc2mnl_msg != NULL) {
+            gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_SEND;
+            gfc2mnl_msg->session = gCurrentSession;
+            gfc2mnl_msg->length = prmsg->length + sizeof(MTK_FLP_MSG_T);
+            memcpy( ((char*)gfc2mnl_msg)+sizeof(MTK_GFC_MNL_MSG_HEADER_T), ((char*)prmsg), (sizeof(MTK_FLP_MSG_T)+ prmsg->length));
+            LOGD("Send to OFL GFC,message type:0x%02x, len:%u", prmsg->type, (gfc2mnl_msg->length + sizeof(MTK_GFC_MNL_MSG_HEADER_T)));
+            gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+            free(gfc2mnl_msg);
+        }
+    }
+    return;
+}
+
+int mtk_gfc_controller_query_mode () {
+    return gfc_mode;
+}
+
+float mtk_flp_controller_get_current_acc() {
+    return current_gnss_acc;
+}
+
+void mtk_smart_geofence_entry(int mode, unsigned int duration_sec) {
+    LOGD("Smart geofence entry mode:%d timeout:%u", mode, duration_sec);
+    gfc_mode = mode;
+}
+
+void mtk_smart_geofence_exit() {
+    gfc_mode = MTK_BATCH_GEOFENCE_ONLY;
+}
+
+static int mtk_loc_check(GpsLocation* gpsloc, MTK_FLP_LOCATION_T *flploc) {
+    if (gpsloc == NULL || flploc == NULL) {
+        return MTK_GFC_ERROR;
+    }
+    memcpy(flploc, gpsloc, sizeof(GpsLocation));
+    flploc->size = sizeof(MTK_FLP_LOCATION_T);
+    flploc->sources_used = FLP_TECH_MASK_GNSS;
+    flploc->accuracy = 1.7*(gpsloc->accuracy); //convert accuracy from 67% to 95%
+    flploc->altitude = gpsloc->altitude;
+    flploc->bearing = gpsloc->bearing;
+    flploc->flags =gpsloc->flags;
+    flploc->latitude = gpsloc->latitude;
+    flploc->longitude = gpsloc->longitude;
+    flploc->speed = gpsloc->speed;
+    flploc->timestamp = gpsloc->timestamp;//mtk_flp_get_timestamp(NULL);
+#if 0
+    LOGD("[DC_GNSS]:dc2gnss: acc:%.4f,alt:%.4f,bearing:%.4f,flag:%d,lat:%.4f,lon:%.4f,spd:%.4f",
+    flploc->accuracy,flploc->altitude,flploc->bearing,flploc->flags,flploc->latitude,
+    flploc->longitude,flploc->speed);
+#endif
+    return MTK_GFC_SUCCESS;
+}
+
+/************************************************************************/
+//  Process msgs from GFC HAL and send to offload kernel
+/************************************************************************/
+int mtk_gfc2mnl_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_GFC_MNL_MSG_HEADER_T* gfc2mnl_msg = NULL;
+    if(prmsg == NULL) {
+        LOGE("mtk_gfc2mnl_process, recv prmsg is null pointer\n");
+        return MTK_GFC_ERROR;
+    }
+    //LOGD("mtk_gfc2mnl_process, recv prmsg, type: 0x%02x, len:%u status:%u\r\n", prmsg->type, prmsg->length, fgMnldGfcStatus);
+    switch(prmsg->type) {
+        case MTK_FLP_MSG_DC_START_CMD: // host-based start gnss
+            //send init message to mnld first
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //send header only, no message body
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN;
+                gfc2mnl_msg->length = 0;
+                gfc2mnl_msg->session = gCurrentSession;
+                LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN");
+                fgMnldGfcStatus = MNL_STATUS_HBD_GPS_OPEN;
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+            break;
+        case MTK_FLP_MSG_DC_STOP_CMD:
+            //send stop message to mnld
+            gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //send header only, no message body
+            if(gfc2mnl_msg != NULL) {
+                gfc2mnl_msg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE;
+                gfc2mnl_msg->length = 0;
+                gfc2mnl_msg->session = gCurrentSession;
+                //LOGD("Send to mnld for deinit,message type:0x%02x, len:%d", gfc2mnl_msg->type, gfc2mnl_msg->length);
+                fgMnldGfcStatus = MNL_STATUS_HBD_GPS_CLOSE;
+                gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                free(gfc2mnl_msg);
+            }
+            break;
+    }
+    return MTK_GFC_SUCCESS;
+}
+
+void mtk_gfc_controller_update_option() {
+    unsigned int local_source = 0;
+    unsigned int new_source = 0;
+    MTK_FLP_MSG_T *flp_cmd;
+    MTK_FLP_BATCH_OPTION_T batch_option;
+    //assign stop command;
+    memset(&batch_option,0,sizeof(MTK_FLP_BATCH_OPTION_T));
+    local_source = flp_geofence_source;
+    new_source = geofence_source_to_use;
+    if(local_source != new_source) {
+        if((local_source == 0) && (new_source == 1)) {
+            //new req is open dc_xxx
+            current_gnss_acc = 0;
+            flp_cmd = malloc(sizeof(MTK_FLP_BATCH_OPTION_T)+ sizeof(MTK_FLP_MSG_T));
+            if(flp_cmd != NULL) {
+                flp_cmd->type = MTK_FLP_MSG_DC_START_CMD;
+                flp_cmd->length = sizeof(MTK_FLP_BATCH_OPTION_T);
+                batch_option.flags = gfc_mode;
+                batch_option.max_power_allocation_mW = 0;
+                batch_option.period_ns = ONE_SEC_NS;
+                batch_option.sources_to_use = FLP_TECH_MASK_GNSS;
+                memcpy((INT8 *)flp_cmd + sizeof(MTK_FLP_MSG_T), &batch_option, sizeof(MTK_FLP_BATCH_OPTION_T));
+                mtk_gfc2mnl_process(flp_cmd);
+                free(flp_cmd);
+            } else {
+                LOGE("open DC: malloc failed");
+            }
+        } else if((local_source == 1) && (new_source == 0)) {
+            //new req is close dc_xxx
+            flp_cmd = malloc(sizeof(MTK_FLP_MSG_T));
+            if(flp_cmd != NULL) {
+                flp_cmd->type = MTK_FLP_MSG_DC_STOP_CMD;
+                flp_cmd->length = 0;
+                mtk_gfc2mnl_process(flp_cmd);
+                free(flp_cmd);
+            } else {
+                LOGE("close DC malloc failed");
+            }
+        }
+    }
+    flp_geofence_source = geofence_source_to_use;
+}
+
+int mtk_gfc_controller_reset_status(void) {
+    geofence_enabled = 0;
+    gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+    geofence_in_use = 0;
+    geofence_source_to_use = 0;
+    current_gnss_acc = 0;
+    flp_geofence_source = 0;
+#if defined(__ANDROID_OS__)
+    mtk_flp_geofence_clear_geofences();
+#endif
+    return MTK_GFC_SUCCESS;
+}
+
+int mtk_gfc_controller_process(MTK_FLP_MSG_T *prmsg) {
+    MTK_FLP_MSG_T *geofence_msg = NULL;
+    MTK_GEOFENCE_PROPERTY_T geofence_input;
+    int32_t fence_num;
+    if(prmsg == NULL) {
+        LOGE("mtk_gfc_controller_process, recv prmsg is null pointer\r\n");
+        return MTK_GFC_ERROR;
+    }
+    LOGD("mtk_gfc_controller_process, recv prmsg, type:%d, len:%d\r\n", prmsg->type, prmsg->length);
+    switch( prmsg->type ) {
+        case MTK_FLP_MSG_OFL_GEOFENCE_CMD:
+            geofence_msg = malloc((prmsg->length)-sizeof(MTK_FLP_MSG_T));
+            if(geofence_msg != NULL ) {
+                memcpy( geofence_msg, ((char*)prmsg)+sizeof(MTK_FLP_MSG_T), ((prmsg->length)-sizeof(MTK_FLP_MSG_T)));
+                if(geofence_enabled) {
+                    if (mtk_gfc_controller_query_mode() > MTK_BATCH_GEOFENCE_ONLY) {
+                        LOGD("DEV_GEO: Smart geofence exit from geofence");
+                        mtk_smart_geofence_exit();
+                    }
+                }
+#if defined(__ANDROID_OS__)
+                mtk_geofence_offload_main(geofence_msg);
+#endif
+                if( (geofence_msg->type == ADD_GEOFENCE_AREA) || (geofence_msg->type == RECOVER_GEOFENCE) ) {
+                    LOGD("%s", pGFCVersion);
+                    memcpy(&fence_num, ((char *)geofence_msg + sizeof(MTK_FLP_MSG_T)), sizeof(int32_t));
+                    memcpy(&geofence_input, ((char *)geofence_msg + sizeof(MTK_FLP_MSG_T)+sizeof(int32_t)),sizeof(MTK_GEOFENCE_PROPERTY_T));
+                    if (geofence_in_use > 0) {
+#if defined(__ANDROID_OS__)
+                        geofence_source_to_use = update_fence_source();
+#endif
+                    } else {
+                        // first fence
+                        geofence_source_to_use = 1;
+                    }
+                    if (geofence_in_use == 0) {
+                        gfc_mode = MTK_BATCH_GEOFENCE_ONLY;
+                    }
+                    mtk_gfc_controller_update_option();
+                    geofence_enabled = 1;
+                    geofence_in_use++;
+                } else if(geofence_msg->type == REMOVE_GEOFENCE ) {
+                    memcpy( &fence_num, ((char *)geofence_msg + sizeof(MTK_FLP_MSG_T)), sizeof(int32_t));
+                    if(geofence_in_use > 0) {
+                        geofence_in_use -= 1;
+                    }
+#if defined(__ANDROID_OS__)
+                    geofence_source_to_use = update_fence_source();
+#endif
+                    mtk_gfc_controller_update_option();
+                    if( geofence_in_use == 0 ) {
+                        geofence_enabled = 0;
+                        gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+                    }
+                } else if(geofence_msg->type == CLEAR_GEOFENCE) {
+                    geofence_in_use = 0;
+                    geofence_enabled = 0;
+                    geofence_source_to_use = 0;
+                    mtk_gfc_controller_update_option();
+                    gfc_mode = MTK_GEOFENCE_IDLE_MODE;
+                }
+                free(geofence_msg);
+            }
+            break;
+        default:
+            LOGE("unknown cmd:0x%02x",prmsg->type);
+            break;
+    }
+    return MTK_GFC_SUCCESS;
+}
+
+/************************************************************************/
+//  Handle MNL Response                                                 */
+/************************************************************************/
+int mnl2gfc_hdlr(MTK_GFC_MNL_MSG_T* prmsg) {
+    char buff[GFC_MNL_BUFF_SIZE] = {0};
+    int ret, i;
+    int offset = 0;
+    MTK_GFC_MNL_MSG_HEADER_T *gfc2mnl_msg;
+    MTK_FLP_MSG_T *gfc2hal_msg;
+    MTK_FLP_MSG_T *cnn2gfc_msg;
+    GpsLocation  *gps_loc;
+    FlpLocation  flp_loc;
+
+    if(prmsg == NULL) {
+        LOGE("mnl2gfc_hdlr recv null msg");
+        return MTK_GFC_ERROR;
+    }
+    LOGD("mtk_mnl2gfc_recv_msg type = %u, session = %u, len = %u, state = %u\n",  prmsg->type, prmsg->session, prmsg->length, fgMnldGfcStatus);
+    switch(prmsg->type) {
+        case MNLD_FLP_TYPE_MNL_BOOTUP:
+            fgMnldGfcStatus = MNL_STATUS_ATTACH_DONE;
+            gfc2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+            if(gfc2hal_msg == NULL) {
+                LOGE("reset ntf malloc failed");
+                return MTK_FLP_ERROR;
+            }
+            gfc2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+            gfc2hal_msg->length = 0;
+            put_binary(buff, &offset, (const char*)gfc2hal_msg, sizeof(MTK_FLP_MSG_T));
+            ret = mnl_send2gfc(buff, offset);
+            free(gfc2hal_msg);
+            if(ret < 0) {
+                LOGD("mnl2gfc_hdlr send error return error");
+            }
+            break;
+        case MNLD_FLP_TYPE_SESSION_UPDATE:
+            gCurrentSession = prmsg->session;
+            memcpy(&gCurrentSupport, ((char*)prmsg)+sizeof(MTK_GFC_MNL_MSG_HEADER_T), sizeof(gCurrentSupport));
+            LOGD("SESSION_UPDATE %u support %u mode %u", gCurrentSession, gCurrentSupport, fgMnldGfcStatus);
+            if (fgMnldGfcStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && gCurrentSupport == GFC_AP_MODE) {
+                LOGD("SESSION_UPDATE: already run on host");
+            } else if (fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport & GFC_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: already run on offlaod");
+            } else if (fgMnldGfcStatus == MNL_STATUS_HBD_GPS_OPEN_DONE && (gCurrentSupport & GFC_OFFLOAD_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ofl mode");
+                mtk_gfc_controller_reset_status();
+                mtk_gfc_set_sys_mode(GFC_OFFLOAD_MODE);
+                gfc2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(gfc2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                gfc2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                gfc2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)gfc2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2gfc(buff, offset);
+                free(gfc2hal_msg);
+                if(ret < 0) {
+                    LOGE("mnl2gfc_hdlr send error return error");
+                }
+            } else if (fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN_DONE && (gCurrentSupport == GFC_AP_MODE)) {
+                LOGD("SESSION_UPDATE: switch to ap mode");
+                mtk_gfc_set_sys_mode(GFC_AP_MODE);
+                gfc2hal_msg = malloc(sizeof(MTK_FLP_MSG_T));
+                if(gfc2hal_msg == NULL) {
+                    LOGE("reset ntf malloc failed");
+                    return MTK_FLP_ERROR;
+                }
+                gfc2hal_msg->type = MTK_FLP_MSG_SYS_FLPD_RESET_NTF;
+                gfc2hal_msg->length = 0;
+                put_binary(buff, &offset, (const char*)gfc2hal_msg, sizeof(MTK_FLP_MSG_T));
+                ret = mnl_send2gfc(buff, offset);
+                free(gfc2hal_msg);
+                if(ret < 0) {
+                    LOGE("mnl2gfc_hdlr send error return error");
+                }
+            } else {
+                if (gCurrentSupport & GFC_OFFLOAD_MODE) {
+                    mtk_gfc_set_sys_mode(GFC_OFFLOAD_MODE);
+                    LOGD("SESSION_UPDATE: set offload mode");
+                } else if (gCurrentSupport == GFC_AP_MODE) {
+                    mtk_gfc_set_sys_mode(GFC_AP_MODE);
+                    LOGD("SESSION_UPDATE: set ap mode");
+                }
+            }
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_LOCATION:
+            if (!flp_geofence_source) {
+                LOGE("bypass loc - no source open");
+                return MTK_GFC_ERROR;
+            }
+            gps_loc = (GpsLocation *)(((char*)prmsg)+sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+            //LOGD("GNSS LOC DBG: %f, %lf, %lf, %d", gps_loc->accuracy, gps_loc->latitude, gps_loc->longitude, gps_loc->size);
+            if(mtk_loc_check(gps_loc, (MTK_FLP_LOCATION_T *)&flp_loc) != MTK_GFC_SUCCESS) {
+                LOGE("Incorrect data received");
+            } else {
+                if (geofence_enabled) {
+#if defined(__ANDROID_OS__)
+                    mtk_flp_geofence_expire();
+#endif
+                    current_gnss_acc = flp_loc.accuracy;
+                    if (flp_loc.accuracy < 0.001) {
+                        LOGE("bypass loc - loc no fix");
+                        return MTK_GFC_ERROR;
+                    }
+#if defined(__ANDROID_OS__)
+                    mtk_set_geofence_location(&flp_loc);
+#endif
+                    //LOGD("Location,LNG:%f LAT:%f ALT:%f ACC:%f SPD:%f BEARING:%f, FLAGS:%04X SOURCES:%08X Timestamp:%lld",
+                    //    flp_loc.longitude, flp_loc.latitude, flp_loc.altitude, flp_loc.accuracy,
+                    //    flp_loc.speed, flp_loc.bearing, flp_loc.flags, flp_loc.sources_used, flp_loc.timestamp);
+                }
+            }
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_RECV:
+            cnn2gfc_msg = malloc(prmsg->length);
+            if(cnn2gfc_msg == NULL) {
+                LOGE("cnn2gfc_msg malloc failed");
+                return MTK_GFC_ERROR;
+            }
+            memcpy((char*)cnn2gfc_msg, ((char*)prmsg)+ sizeof(MTK_GFC_MNL_MSG_HEADER_T), prmsg->length);
+            //LOGD("Received OFFLOAD message type: 0x%02x, len = %u", cnn2gfc_msg->type, cnn2gfc_msg->length);
+            switch(cnn2gfc_msg->type) {
+                case MTK_FLP_MSG_HAL_STOP_RSP:
+                    //send stop message to mnld
+                    gfc2mnl_msg = (MTK_GFC_MNL_MSG_HEADER_T *)malloc(sizeof(MTK_GFC_MNL_MSG_HEADER_T));
+                    if(gfc2mnl_msg!= NULL) {
+                        gfc2mnl_msg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE;
+                        gfc2mnl_msg->session= gCurrentSession;
+                        gfc2mnl_msg->length = 0;
+                        LOGD("Send to mnld for deinit,message type:%u, len:%u", gfc2mnl_msg->type, gfc2mnl_msg->length);
+                        gfc2mnl_hdlr((MTK_GFC_MNL_MSG_T *)gfc2mnl_msg);
+                        fgMnldGfcStatus = MNL_STATUS_OFL_LINK_CLOSE;
+                        LOGD("mnld deinit success");
+                        free(gfc2mnl_msg);
+                    }
+                    break;
+                case MTK_FLP_MSG_HAL_GEOFENCE_CALLBACK_NTF:
+                case MTK_FLP_MSG_OFL_GEOFENCE_CALLBACK_NTF:
+                    put_binary(buff, &offset, (const char*)cnn2gfc_msg, sizeof(MTK_FLP_MSG_T)+cnn2gfc_msg->length);
+                    ret = mnl_send2gfc(buff, offset);
+                    if(ret < 0) {
+                        LOGE("MTK_GFC2HAL send error return error");
+                    }
+                    break;
+                default:
+                    LOGE("mnl2gfc_hdlr unrecognize msg 0x%02x",cnn2gfc_msg->type);
+                    break;
+            }
+            free(cnn2gfc_msg);
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE:
+            fgMnldGfcStatus = MNL_STATUS_HBD_GPS_OPEN_DONE;
+            LOGD("MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE:
+            fgMnldGfcStatus = MNL_STATUS_HBD_GPS_CLOSE_DONE;
+            LOGD("MNL_STATUS_HBD_GPS_CLOSE_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE:
+            if (fgMnldGfcStatus == MNL_STATUS_OFL_LINK_OPEN) {
+                fgMnldGfcStatus = MNL_STATUS_OFL_LINK_OPEN_DONE;
+                LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE flush %d", gGfc2mnl_cnt);
+                for (i = 0; i < gGfc2mnl_cnt; i++) {
+                    gfc2mnl_hdlr(&gGfc2mnl_msg[i]);
+                }
+                gGfc2mnl_cnt = 0;
+            } else {
+                LOGD("GFC_DBG: mnld state expect 7, get %u", fgMnldGfcStatus);
+            }
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE");
+            break;
+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE:
+            fgMnldGfcStatus = MNL_STATUS_OFL_LINK_CLOSE_DONE;
+            LOGD("MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE");
+            break;
+        case MNLD_FLP_TYPE_FLP_ATTACH_DONE:
+            fgMnldGfcStatus = MNL_STATUS_ATTACH_DONE;
+            LOGD("MNL_STATUS_ATTACH_DONE");
+            break;
+        default:
+            LOGE("undefined cmd:0x%02x",prmsg->type);
+            break;
+    }
+    return MTK_GFC_SUCCESS;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c
new file mode 100644
index 0000000..5e2ddd8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_geofence_interface/src/mtk_geofence_main.c
@@ -0,0 +1,500 @@
+#include <string.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <errno.h>

+#include <unistd.h>

+#include <fcntl.h>

+#include <sys/socket.h>

+#include <sys/types.h>

+#include <sys/stat.h>

+#include <sys/un.h>

+

+#include "mtk_geofence_main.h"

+#include "data_coder.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "gps_dbg_log"

+#endif

+

+/**********************************************************

+ *  Define                                                *

+ **********************************************************/

+#define GEOFENCE_INJECT_LOC_ENUM 600

+#define MNLD_STRNCPY(dst,src,size) do{\

+                                       strncpy((char *)(dst), (src), (size - 1));\

+                                      (dst)[size - 1] = '\0';\

+                                     }while(0)

+

+

+/**********************************************************

+ *  Global vars                                           *

+ **********************************************************/

+gfc2mnl_interface* gfc2mnl_hdlr_cb;

+static unsigned int gModeFlag = GFC_AP_MODE;

+static char g_mnl2gfc_path[128] = MNL_TO_GEOFENCE;

+//static char g_gfc2mnl_path[128] = GEOFENCE_TO_MNL;

+

+

+MTK_GFC_Session_T mnld_gfc_session = {

+    .type = MNLD_GFC_CAPABILITY_AP_MODE,

+    .pre_type = MNLD_GFC_CAPABILITY_AP_MODE,

+    .id = 1,

+};

+

+/**********************************************************

+ *  Socket Function                                       *

+ **********************************************************/

+static int safe_recvfrom(int sockfd, char* buf, int len) {

+    int ret = 0;

+    int retry = 10;

+

+    while ((ret = recvfrom(sockfd, buf, len, 0,NULL, NULL)) == -1) {

+        LOGW("ret=%d len=%d\n", ret, len);

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("sendto reason=[%s]\n", strerror(errno));

+        break;

+    }

+    return ret;

+}

+

+// -1 means failure

+static int set_socket_blocking(int fd, int blocking) {

+    if (fd < 0) {

+        LOGE("set_socket_blocking  invalid fd=%d\n", fd);

+        return -1;

+    }

+

+    int flags = fcntl(fd, F_GETFL, 0);

+    if (flags < 0) {

+        LOGE("set_socket_blocking  invalid flags=%d\n", flags);

+        return -1;

+    }

+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);

+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;

+}

+

+// -1 means failure

+static int safe_sendto(int sockfd, const char* dest, const char* buf, int size)

+{

+    int len = 0;

+    struct sockaddr_un soc_addr;

+    int retry = 10;

+

+    memset(&soc_addr, 0, sizeof(soc_addr));

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, dest,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+

+    while ((len = sendto(sockfd, buf, size, 0,(const struct sockaddr *)&soc_addr,sizeof(soc_addr))) == -1) {

+        if (errno == EINTR) continue;

+        if (errno == EAGAIN) {

+            if (retry-- > 0) {

+                usleep(100 * 1000);

+                continue;

+            }

+        }

+        LOGE("sendto dest=[%s] len=%d reason=[%s]\n",

+            dest, size, strerror(errno));

+        break;

+    }

+    return len;

+}

+

+int mnl_send2gfc(const char* buff, int len) {

+    int ret = 0;

+    int sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+

+    if (sockfd < 0) {

+        LOGE("mnl_send2gfc() socket() failed reason=[%s]%d",

+            strerror(errno), errno);

+        return -1;

+    }

+

+    if (safe_sendto(sockfd, g_mnl2gfc_path, buff, len) < 0) {

+        LOGE("mnl_send2gfc safe_sendto failed\n");

+        ret = -1;

+    }

+    close(sockfd);

+    return ret;

+}

+

+static int bind_udp_socket(char* path) {

+    int sockfd;

+    struct sockaddr_un soc_addr;

+

+    sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0);

+    if (sockfd < 0) {

+        LOGE("socket failed reason=[%s]\n", strerror(errno));

+        return -1;

+    }

+    memset(&soc_addr, 0, sizeof(soc_addr));

+    soc_addr.sun_path[0] = 0;

+    MNLD_STRNCPY(soc_addr.sun_path + 1, path,sizeof(soc_addr.sun_path) - 1);

+    soc_addr.sun_family = AF_UNIX;

+    unlink(soc_addr.sun_path);

+    if (bind(sockfd, (struct sockaddr *)&soc_addr, sizeof(soc_addr)) < 0) {

+        LOGE("bind failed path=[%s] reason=[%s]\n", path, strerror(errno));

+        close(sockfd);

+        return -1;

+    }

+

+    return sockfd;

+}

+

+

+/*********************************************************/

+/* GPS HAL to mnl_geofence socket                        */

+/*********************************************************/

+int create_gfchal2mnl_fd() {

+    int fd = bind_udp_socket(GEOFENCE_TO_MNL);

+    set_socket_blocking(fd, 0);

+    return fd;

+}

+

+/*********************************************************/

+/* MNLD Response                                         */

+/*********************************************************/

+int mnld_gfc_ofl_gps_open_done() {

+    LOGD("mnld_gfc_ofl_gps_open_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_OPEN_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_hbd_gps_open_done() {

+    LOGD("mnld_gfc_hbd_gps_open_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_OPEN_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_ofl_gps_close_done() {

+    LOGD("mnld_gfc_ofl_gps_close_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_OFL_LINK_CLOSE_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_hbd_gps_close_done() {

+    LOGD("mnld_gfc_hbd_gps_close_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_HBD_GPS_CLOSE_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_attach_done() {

+    LOGD("mnld_gfc_attach_done");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_FLP_ATTACH_DONE;

+    prMsg->length = 0;

+    prMsg->session = mnld_gfc_session.id;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+

+int mnld_gfc_session_update() {

+    LOGD("mnld_gfc_session_update,id=%d,type=%d",mnld_gfc_session.id,mnld_gfc_session.type);

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    int * payload = NULL;

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    prMsg->type = MNLD_FLP_TYPE_SESSION_UPDATE;

+    prMsg->length = sizeof(int);

+    prMsg->session = mnld_gfc_session.id;

+    payload = (int *)&prMsg->data[0];

+    *payload = mnld_gfc_session.type;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnld_gfc_gen_new_session() {

+    mnld_gfc_session.id++;

+    if (mnld_gfc_session.id >= 0xFFFFFFFF) {

+        mnld_gfc_session.id = 0;

+        LOGW("Session id overflow!!");

+    }

+    return mnld_gfc_session.id;

+}

+

+int mnl2gfc_mnld_reboot() {

+    LOGD("mnl2gfc_mnld_reboot");

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    int * payload = NULL;

+    MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];

+

+    if (mnld_gfc_session_update() == -1) {

+        LOGE("mnld_main_thread() mnld_gfc_session_update failed");

+    }

+    prMsg->type = MNLD_FLP_TYPE_MNL_BOOTUP;

+    prMsg->session = mnld_gfc_session.id;

+    prMsg->length = sizeof(int);

+    payload = (int *)&prMsg->data[0];

+    *payload = FLP_MNL_INTERFACE_VERSION;

+    return mnl2gfc_hdlr(prMsg);

+}

+

+int mnl2gfc_data_send(unsigned char *buf, unsigned int len) {

+    int ret = MTK_GFC_ERROR;

+    if(len >0) {

+        ret = mnl2gfc_hdlr((MTK_GFC_MNL_MSG_T *)buf);

+    } else {

+        LOGE("len err %d",len);

+    }

+    return ret;

+}

+

+void mtk_gfc_set_sys_mode (unsigned int sysMode) {

+    if(sysMode == GFC_AP_MODE || sysMode == GFC_OFFLOAD_MODE)

+    {

+        gModeFlag = sysMode;

+        LOGD("mtk_gfc_set_sys_mode success = %d", gModeFlag);

+    } else {

+        LOGE("mtk_gfc_set_sys_mode error = %d", sysMode);

+    }

+}

+

+

+int mtk_gfc_get_sys_mode () {

+    return gModeFlag;

+}

+

+#define MAX_DUMP_CHAR 128

+/*********************************************************/

+/* Geofence Debug Function                               */

+/*********************************************************/

+void mnl_gfc_dump_buf(char *p, int len) {

+    int i, r, n;

+    char str[MAX_DUMP_CHAR] = {0};

+    for (i = 0, n = 0; i < len ; i++) {

+        r = snprintf(&str[n], MAX_DUMP_CHAR - n, "%3d,", p[i]);

+        if (r + n >= MAX_DUMP_CHAR || r <= 0) {

+            LOGE("[GFC2MNLD]data from gfc: data=%s, error return", str);

+            return;

+        }

+

+        n += r;

+        if ((i % 8 == 7) || i + 1 == len) {

+            LOGD("[GFC2MNLD]data from gfc: data=%s", str);

+            n = 0;

+            str[0] = '0';

+        }

+    }

+}

+

+//********************************************************************************

+//

+// mtk_hal2gfc_main_hdlr(): Geofence main function to process CMD from GPS/GFC HAL

+//

+// CMD from FWK: GPS JNI --> GFC HAL --> Mnld main --> mtk_hal2gfc_main_hdlr

+//********************************************************************************

+int mtk_hal2gfc_main_hdlr(int fd, gfc2mnl_interface* hdlr) {

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    char buff_send[GFC_MNL_BUFF_SIZE] = {0};

+    char data[GFC_MNL_BUFF_SIZE] = {0};

+    int ret = MTK_GFC_ERROR, read_len, offset = 0, len;

+    MTK_FLP_MSG_T *prmsg = NULL;

+

+    read_len = safe_recvfrom(fd, buff, sizeof(buff));

+    if ((read_len <= 0) || (read_len>GFC_MNL_BUFF_SIZE)) {

+        LOGE("hal2gfc_main_hdlr() safe_recvfrom() failed read_len=%d",read_len);

+        return ret;

+    }

+    if(hdlr != NULL) {

+        gfc2mnl_hdlr_cb = hdlr;

+    } else {

+        LOGE("gfc2mnl_hdlr_cb = NULL");

+        return ret;

+    }

+

+    len = get_binary(buff, &offset, data, sizeof(buff), sizeof(data));

+    if((len > 0) && (len<=GFC_MNL_BUFF_SIZE)) {

+        prmsg = (MTK_FLP_MSG_T *)&data[0];

+    } else {

+        LOGE("len err:%d",len);

+        return ret;

+    }

+#if 0

+    LOGD("mtk_hal2gfc_main_hdlr:%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x",

+    data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],

+    data[8],data[9],data[10],data[11],data[12],data[13],data[14],data[15]);

+#endif

+    if(prmsg->type == GEOFENCE_INJECT_LOC_ENUM) {

+        //relay from flpHAL to geofenceHAL

+        offset = 0;

+        put_binary(buff_send, &offset, (const char*)data,read_len);

+        ret = mnl_send2gfc(buff_send, offset);

+        if(ret < 0) {

+            LOGD("GFC2FLP send error return error");

+        }

+        return ret;

+    }

+    if (prmsg->type == MTK_FLP_MSG_HAL_INIT_CMD) {

+    } else if (prmsg->type == MTK_FLP_MSG_CONN_SCREEN_STATUS) {

+        if (mtk_gfc_get_sys_mode() == GFC_OFFLOAD_MODE) {

+            mtk_gfc_ofl2mnl_process(prmsg);

+        }

+    } else {

+        if (mtk_gfc_get_sys_mode() == GFC_OFFLOAD_MODE) {

+            mtk_gfc_ofl2mnl_process(prmsg);

+        } else {

+            mtk_gfc_controller_process(prmsg);

+        }

+    }

+    ret = MTK_GFC_SUCCESS;

+

+    return ret;

+}

+

+/************************************************************************/

+//  Handle Geofence Kernel Response                                     */

+/************************************************************************/

+int gfc_kernel_2gfc_hdlr(MTK_FLP_MSG_T* prmsg) {

+    char buff[GFC_MNL_BUFF_SIZE] = {0};

+    int ret, offset = 0;

+

+    if(prmsg == NULL) {

+        LOGE("gfc_kernel_2gfc_hdlr = NULL");

+        return MTK_GFC_ERROR;

+    }

+    put_binary(buff, &offset, (const char*)prmsg,sizeof(MTK_FLP_MSG_T)+prmsg->length);

+    ret = mnl_send2gfc(buff, offset);

+    if(ret < 0) {

+        LOGE("MTK_GFC2HAL send error return error");

+    } else {

+        LOGD("gfc_kernel_2gfc_hdlr success");

+    }

+    return MTK_GFC_SUCCESS;

+}

+

+

+/************************************************************************/

+//  Handle GFC Request                                                  */

+/************************************************************************/

+int gfc2mnl_hdlr(MTK_GFC_MNL_MSG_T  *prMsg) {

+    int ret = MTK_GFC_ERROR, read_len;

+

+    if(prMsg != NULL) {

+        read_len = prMsg->length + sizeof(MTK_GFC_MNL_MSG_HEADER_T);

+        LOGD("[GFC2MNLD]data from gfc: type=0x%02x, session_id=%u, len=%d,read_len = %d\n", prMsg->type, prMsg->session, prMsg->length, read_len);

+        //mnl_gfc_dump_buf((char*)prMsg, read_len);

+    } else {

+        LOGE("gfc2mnl_hdlr recv null msg");

+        return ret;

+    }

+    if(gfc2mnl_hdlr_cb == NULL) {

+        LOGE("gfc2mnl_hdlr_cb is NULL");

+        return ret;

+    }

+

+    switch (prMsg->type) {

+        case MNLD_FLP_TYPE_FLP_ATTACH: {

+            if (gfc2mnl_hdlr_cb->mnld_gfc_attach) {

+                gfc2mnl_hdlr_cb->mnld_gfc_attach();

+                if (mnld_gfc_session_update() == -1) {

+                    LOGE("mnld_main_thread() mnld_gfc_session_update failed");

+                } else {

+                    ret = MTK_GFC_SUCCESS;

+                }

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_flp_attach is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_HBD_GPS_OPEN: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_open) {

+                gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_open();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_hbd_gps_open is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_HBD_GPS_CLOSE: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_close) {

+                gfc2mnl_hdlr_cb->mnld_gfc_hbd_gps_close();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_hbd_gps_close is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_OFL_LINK_OPEN: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_open) {

+                gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_open();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_ofl_link_open is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_OFL_LINK_CLOSE: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_close) {

+                gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_close();

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_gfc_ofl_link_close is NULL");

+            }

+            break;

+        }

+        case MNLD_FLP_TYPE_OFL_LINK_SEND: {

+            if (prMsg->session != mnld_gfc_session.id) {

+                LOGE("gfc2mnl_hdlr() session_id doesn't match, ignore");

+                break;

+            }

+            if (gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_send) {

+                gfc2mnl_hdlr_cb->mnld_gfc_ofl_link_send(prMsg);

+                ret = MTK_GFC_SUCCESS;

+            } else {

+                LOGE("gfc2mnl_hdlr() mnld_flp_ofl_link_send is NULL");

+            }

+            break;

+        }

+        default: {

+            LOGE("gfc2mnl_hdlr() unknown cmd=0x%02x", prMsg->type);

+            break;

+        }

+    }

+    return ret;

+}

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h b/src/connectivity/gps/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h
new file mode 100644
index 0000000..0f111d5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_log_interface/inc/LbsLogInterface.h
@@ -0,0 +1,68 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __LbsLogInterface_H__
+#define __LbsLogInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LBS_LOG_INTERFACE_PROTOCOL_TYPE 307
+#define LBS_LOG_INTERFACE_BUFF_SIZE 15376
+
+/**
+ * The LBS log interface from vendor to system
+ */
+typedef enum {
+    LBS_LOG_INTERFACE_OPEN_LOG = 0,
+    LBS_LOG_INTERFACE_CLOSE_LOG = 1,
+    LBS_LOG_INTERFACE_WRITE_LOG = 2,
+} LbsLogInterface_message_id;
+
+
+typedef enum {
+    LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG = 0,
+    LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG = 1,
+    LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG = 2,
+} LbsLogInterface_LogCategory;
+
+
+// LbsLogInterface_LogCategory
+const char* LbsLogInterface_LogCategory_to_string(LbsLogInterface_LogCategory data);
+void LbsLogInterface_LogCategory_array_dump(LbsLogInterface_LogCategory data[], int size);
+
+void LbsLogInterface_LogCategory_array_init(LbsLogInterface_LogCategory output[], int max_size);
+
+bool LbsLogInterface_LogCategory_is_equal(LbsLogInterface_LogCategory data1, LbsLogInterface_LogCategory data2);
+bool LbsLogInterface_LogCategory_array_is_equal(LbsLogInterface_LogCategory data1[], int size1, LbsLogInterface_LogCategory data2[], int size2);
+
+bool LbsLogInterface_LogCategory_encode(char* buff, int* offset, LbsLogInterface_LogCategory data);
+bool LbsLogInterface_LogCategory_array_encode(char* buff, int* offset, LbsLogInterface_LogCategory data[], int size);
+
+void LbsLogInterface_LogCategory_decode(char* buff, int* offset, LbsLogInterface_LogCategory* output);
+int LbsLogInterface_LogCategory_array_decode(char* buff, int* offset, LbsLogInterface_LogCategory output[], int max_size);
+
+// Sender
+bool LbsLogInterface_openLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, char* filePath);
+
+bool LbsLogInterface_closeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type);
+
+bool LbsLogInterface_writeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, char log[], int log_size);
+
+// Receiver
+typedef struct {
+    void (*LbsLogInterface_openLog_handler) (LbsLogInterface_LogCategory type, char* filePath);
+    void (*LbsLogInterface_closeLog_handler) (LbsLogInterface_LogCategory type);
+    void (*LbsLogInterface_writeLog_handler) (LbsLogInterface_LogCategory type, char log[], int log_size);
+} LbsLogInterface_callbacks;
+
+bool LbsLogInterface_receiver_decode(char* _buff, LbsLogInterface_callbacks* callbacks);
+bool LbsLogInterface_receiver_read_and_decode(int server_fd, LbsLogInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c b/src/connectivity/gps/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c
new file mode 100644
index 0000000..0238e35
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_log_interface/src/LbsLogInterface.c
@@ -0,0 +1,262 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "LbsLogInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// LbsLogInterface_LogCategory
+const char* LbsLogInterface_LogCategory_to_string(LbsLogInterface_LogCategory data) {
+    switch(data) {
+    case LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG:
+        return "gpsLog";
+    case LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG:
+        return "mpeLog";
+    case LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG:
+        return "dumpLog";
+    default:
+        break;
+    }
+    return "UNKNOWN";
+}
+void LbsLogInterface_LogCategory_array_dump(LbsLogInterface_LogCategory data[], int size) {
+    int i = 0;
+    SOCK_LOGD("LbsLogInterface_LogCategory_array_dump() size=[%d]", size);
+    for(i = 0; i < size; i++) {
+        SOCK_LOGD("  i=[%d] data=[%s]", i, LbsLogInterface_LogCategory_to_string(data[i]));
+    }
+}
+
+void LbsLogInterface_LogCategory_array_init(LbsLogInterface_LogCategory output[], int max_size) {
+    int i = 0;
+    for(i = 0; i < max_size; i++) {
+        output[i] = LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG;
+    }
+}
+
+bool LbsLogInterface_LogCategory_is_equal(LbsLogInterface_LogCategory data1, LbsLogInterface_LogCategory data2) {
+    return (data1 == data2)? true : false;
+}
+bool LbsLogInterface_LogCategory_array_is_equal(LbsLogInterface_LogCategory data1[], int size1, LbsLogInterface_LogCategory data2[], int size2) {
+    int i = 0;
+    if(size1 != size2) return false;
+    for(i = 0; i < size1; i++) {
+        if(data1[i] != data2[i]) return false;
+    }
+    return true;
+}
+
+bool LbsLogInterface_LogCategory_encode(char* buff, int* offset, LbsLogInterface_LogCategory data) {
+    switch(data) {
+    case LBS_LOG_INTERFACE_LOG_CATEGORY_GPS_LOG:
+    case LBS_LOG_INTERFACE_LOG_CATEGORY_MPE_LOG:
+    case LBS_LOG_INTERFACE_LOG_CATEGORY_DUMP_LOG:
+        break;
+    default:
+        SOCK_LOGE("LbsLogInterface_LogCategory_encode() unknown data=%d", data);
+        return false;
+    }
+    mtk_socket_put_int(buff, offset, data);
+    return true;
+}
+bool LbsLogInterface_LogCategory_array_encode(char* buff, int* offset, LbsLogInterface_LogCategory data[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        if(!LbsLogInterface_LogCategory_encode(buff, offset, data[i])) {
+            SOCK_LOGE("LbsLogInterface_LogCategory_array_encode() LbsLogInterface_LogCategory_encode() failed at i=%d", i);
+            return false;
+        }
+    }
+    return true;
+}
+
+void LbsLogInterface_LogCategory_decode(char* buff, int* offset, LbsLogInterface_LogCategory* output) {
+    *output = mtk_socket_get_int(buff, offset);
+}
+int LbsLogInterface_LogCategory_array_decode(char* buff, int* offset, LbsLogInterface_LogCategory output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        if(i < max_size) {
+            LbsLogInterface_LogCategory_decode(buff, offset, &output[i]);
+        } else {
+            LbsLogInterface_LogCategory data;
+            LbsLogInterface_LogCategory_decode(buff, offset, &data);
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+
+// Sender
+bool LbsLogInterface_openLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, char* filePath) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        SOCK_LOGE("LbsLogInterface_openLog() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_OPEN_LOG);
+    if(!LbsLogInterface_LogCategory_encode(_buff, &_offset, type)) {
+        SOCK_LOGE("LbsLogInterface_openLog() LbsLogInterface_LogCategory_encode() fail on type");
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    if(strlen(filePath) > 256) {
+        SOCK_LOGE("LbsLogInterface_openLog() strlen of filePath=[%d] is over 256", strlen(filePath));
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_put_string(_buff, &_offset, filePath);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        SOCK_LOGE("LbsLogInterface_openLog() mtk_socket_write() failed, fd=%d err=[%s]%d",
+            client_fd->fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool LbsLogInterface_closeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        SOCK_LOGE("LbsLogInterface_closeLog() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_CLOSE_LOG);
+    if(!LbsLogInterface_LogCategory_encode(_buff, &_offset, type)) {
+        SOCK_LOGE("LbsLogInterface_closeLog() LbsLogInterface_LogCategory_encode() fail on type");
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        SOCK_LOGE("LbsLogInterface_closeLog() mtk_socket_write() failed, fd=%d err=[%s]%d",
+            client_fd->fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool LbsLogInterface_writeLog(mtk_socket_fd* client_fd, LbsLogInterface_LogCategory type, char log[], int log_size) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        SOCK_LOGE("LbsLogInterface_writeLog() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, LBS_LOG_INTERFACE_WRITE_LOG);
+    if(!LbsLogInterface_LogCategory_encode(_buff, &_offset, type)) {
+        SOCK_LOGE("LbsLogInterface_writeLog() LbsLogInterface_LogCategory_encode() fail on type");
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+//    ASSERT_LESS_EQUAL_THAN_FOR_MSG(log_size, 15360);
+    mtk_socket_put_char_array(_buff, &_offset, log, log_size);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        SOCK_LOGE("LbsLogInterface_writeLog() mtk_socket_write() failed, fd=%d err=[%s]%d",
+            client_fd->fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+// Receiver
+bool LbsLogInterface_receiver_decode(char* _buff, LbsLogInterface_callbacks* callbacks) {
+    int _ret = 0;
+    int _offset = 0;
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    if(_ret != LBS_LOG_INTERFACE_PROTOCOL_TYPE) {
+        SOCK_LOGE("LbsLogInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+            _ret, LBS_LOG_INTERFACE_PROTOCOL_TYPE);
+        return false;
+    }
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    switch(_ret) {
+    case LBS_LOG_INTERFACE_OPEN_LOG: {
+        if(callbacks->LbsLogInterface_openLog_handler == NULL) {
+            SOCK_LOGE("LbsLogInterface_receiver_decode() LbsLogInterface_openLog_handler() is NULL");
+            return false;
+        }
+        LbsLogInterface_LogCategory type;
+        LbsLogInterface_LogCategory_decode(_buff, &_offset, &type);
+        char filePath[256];
+        mtk_socket_get_string(_buff, &_offset, filePath, 256);
+        callbacks->LbsLogInterface_openLog_handler(type, filePath);
+        break;
+    }
+    case LBS_LOG_INTERFACE_CLOSE_LOG: {
+        if(callbacks->LbsLogInterface_closeLog_handler == NULL) {
+            SOCK_LOGE("LbsLogInterface_receiver_decode() LbsLogInterface_closeLog_handler() is NULL");
+            return false;
+        }
+        LbsLogInterface_LogCategory type;
+        LbsLogInterface_LogCategory_decode(_buff, &_offset, &type);
+        callbacks->LbsLogInterface_closeLog_handler(type);
+        break;
+    }
+    case LBS_LOG_INTERFACE_WRITE_LOG: {
+        if(callbacks->LbsLogInterface_writeLog_handler == NULL) {
+            SOCK_LOGE("LbsLogInterface_receiver_decode() LbsLogInterface_writeLog_handler() is NULL");
+            return false;
+        }
+        LbsLogInterface_LogCategory type;
+        LbsLogInterface_LogCategory_decode(_buff, &_offset, &type);
+        char log[15360];
+        int log_size = mtk_socket_get_char_array(_buff, &_offset, log, 15360);
+        callbacks->LbsLogInterface_writeLog_handler(type, log, log_size);
+        break;
+    }
+    default: {
+        SOCK_LOGE("LbsLogInterface_receiver_decode() unknown msgId=[%d]", _ret);
+        return false;
+    }
+    }
+    return true;
+}
+bool LbsLogInterface_receiver_read_and_decode(int server_fd, LbsLogInterface_callbacks* callbacks) {
+    int _ret;
+    char _buff[LBS_LOG_INTERFACE_BUFF_SIZE] = {0};
+
+    _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+    if(_ret == -1) {
+        SOCK_LOGE("LbsLogInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return LbsLogInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h
new file mode 100644
index 0000000..42a6dc5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/inc/Meta2MnldInterface.h
@@ -0,0 +1,43 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Meta2MnldInterface_H__
+#define __Meta2MnldInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define META2MNLD_INTERFACE_PROTOCOL_TYPE 303
+#define META2MNLD_INTERFACE_BUFF_SIZE 12
+
+/**
+ * The interface from Meta to Mnld
+ */
+typedef enum {
+    META2MNLD_INTERFACE_REQ_GNSS_LOCATION = 0,
+    META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION = 1,
+} Meta2MnldInterface_message_id;
+
+
+
+// Sender
+bool Meta2MnldInterface_reqGnssLocation(mtk_socket_fd* client_fd, int source);
+
+bool Meta2MnldInterface_cancelGnssLocation(mtk_socket_fd* client_fd, int source);
+
+// Receiver
+typedef struct {
+    void (*Meta2MnldInterface_reqGnssLocation_handler) (int source);
+    void (*Meta2MnldInterface_cancelGnssLocation_handler) (int source);
+} Meta2MnldInterface_callbacks;
+
+bool Meta2MnldInterface_receiver_decode(char* _buff, Meta2MnldInterface_callbacks* callbacks);
+bool Meta2MnldInterface_receiver_read_and_decode(int server_fd, Meta2MnldInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c
new file mode 100644
index 0000000..8b1b767
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_meta_interface/src/Meta2MnldInterface.c
@@ -0,0 +1,112 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Meta2MnldInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Sender
+bool Meta2MnldInterface_reqGnssLocation(mtk_socket_fd* client_fd, int source) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Meta2MnldInterface_reqGnssLocation() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_REQ_GNSS_LOCATION);
+    mtk_socket_put_int(_buff, &_offset, source);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Meta2MnldInterface_reqGnssLocation() mtk_socket_write() failed, fd=%p err=[%s]%d", 
+            client_fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool Meta2MnldInterface_cancelGnssLocation(mtk_socket_fd* client_fd, int source) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Meta2MnldInterface_cancelGnssLocation() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION);
+    mtk_socket_put_int(_buff, &_offset, source);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Meta2MnldInterface_cancelGnssLocation() mtk_socket_write() failed, fd=%p err=[%s]%d", 
+            client_fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+// Receiver
+bool Meta2MnldInterface_receiver_decode(char* _buff, Meta2MnldInterface_callbacks* callbacks) {
+    int _ret = 0;
+    int _offset = 0;
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    if(_ret != META2MNLD_INTERFACE_PROTOCOL_TYPE) {
+        LOGE("Meta2MnldInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+            _ret, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+        return false;
+    }
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    switch(_ret) {
+    case META2MNLD_INTERFACE_REQ_GNSS_LOCATION: {
+        if(callbacks->Meta2MnldInterface_reqGnssLocation_handler == NULL) {
+            LOGE("Meta2MnldInterface_receiver_decode() Meta2MnldInterface_reqGnssLocation_handler() is NULL");
+            return false;
+        }
+        int source = mtk_socket_get_int(_buff, &_offset);
+        callbacks->Meta2MnldInterface_reqGnssLocation_handler(source);
+        break;
+    }
+    case META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION: {
+        if(callbacks->Meta2MnldInterface_cancelGnssLocation_handler == NULL) {
+            LOGE("Meta2MnldInterface_receiver_decode() Meta2MnldInterface_cancelGnssLocation_handler() is NULL");
+            return false;
+        }
+        int source = mtk_socket_get_int(_buff, &_offset);
+        callbacks->Meta2MnldInterface_cancelGnssLocation_handler(source);
+        break;
+    }
+    default: {
+        LOGE("Meta2MnldInterface_receiver_decode() unknown msgId=[%d]", _ret);
+        return false;
+    }
+    }
+    return true;
+}
+bool Meta2MnldInterface_receiver_read_and_decode(int server_fd, Meta2MnldInterface_callbacks* callbacks) {
+    int _ret;
+    char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+
+    _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+    if(_ret == -1) {
+        LOGE("Meta2MnldInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d", 
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return Meta2MnldInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_Attitude.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_Attitude.h
new file mode 100644
index 0000000..cece8bf
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_Attitude.h
@@ -0,0 +1,231 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+/* Usage:
+ * 1. Fill in struct IMU
+ * 2. Call mpe_update_posture()
+ * 3. Call mpe_get_euler_angle() or mpe_get_rotation_vector() to get
+ *    <azimuth, pitch, roll> or the rotation vector.
+ *
+ * E.g.
+ *      struct IMU imu;
+ *
+ *      // Fill in the acceleration value from the accelerometer
+ *      imu.acceleration[0] = acc_x;
+ *      imu.acceleration[1] = acc_y;
+ *      imu.acceleration[2] = acc_z;
+ *
+ *      // Fill in the angular velocity from the gyroscope
+ *      imu.angularVelocity[0] = gyro_x;
+ *      imu.angularVelocity[1] = gyro_y;
+ *      imu.angularVelocity[2] = gyro_z;
+ *
+ *      // Fill in magnetic field values from magnetic sensor
+ *      imu.magnetic[0] = mag_x;
+ *      imu.magnetic[1] = mag_y;
+ *      imu.magnetic[2] = mag_z;
+ *
+ *      mpe_update_posture(&imu, (curr_time - prev_time));
+ *
+ *  #ifdef ANDROID_2_3
+ *      float vector[3];
+ *      mpe_get_rotation_vector(vector);
+ *  #else
+ *      float angle[3];
+ *      mpe_get_euler_angle(angle);
+ *  #endif
+ */
+#ifndef __MPE_ATTITUDE_H_INCLUDED__
+#define __MPE_ATTITUDE_H_INCLUDED__
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#define use_speciall_name 0
+/* Sensor Fusion Mode */
+/*
+ * 1) low latency (real time)
+ * 2) 3-DOF rotation detection
+ * 3) eliminate accumulated error
+ * 4) Solve gyroscope temperature drift issue
+ * 5) decouple linear acceleration and gravity of G-sensor
+ * 6) provide absolute orientation (for applications like : navigation)
+ * 7) anti-interference from sudden change of ambient magnetism
+ */
+#define SENSOR_FUSION_MODE_ACC_GYRO_MAG 0
+/*
+ * 1) Need AGM and AG output in the same time
+ * 2) Provide both absolute yaw angle and reletive
+ * 3) Support Android two sensor types
+ */
+#define SENSOR_FUSION_MODE_BOTH_AGM_AG 1
+
+/**
+ * 1) unbounded accumulate error
+ * 2) temperature drift issue from gyro
+ * 3) relative orientation (NOT absolute)
+ */
+#define SENSOR_FUSION_MODE_ACC_GYRO   2
+/*
+ * 1) delayed response
+ * 2) can not resist the magnetic interference
+ * 3) confuse by linear acceleration and gravity
+ */
+#define SENSOR_FUSION_MODE_ACC_MAG    3
+
+/*
+ * 1) use for pedestrian dead reckoning
+ * 2) fused with radio localization system (like : GPS/WF)
+ */
+#define SENSOR_FUSION_MODE_PDR        4
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Definitions of the axis
+ *
+ *          |   /
+ *          |  /
+ *          | /
+ *     ---- |/ ------ x+
+ *          /
+ *         /|
+ *        / |
+ *       /  y-
+ *     z+
+ */
+/*
+ * The input data structure for the Sensor Fusion algorithm
+ */
+typedef struct IMU {
+    /* acceleration values are in meter per second per second (m/s^2) */
+    float acceleration[3];
+    float acceleration_raw[3];
+    /* angular rate values are in radians per second */
+    float  angularVelocity[3];
+    float  angularVelocity_raw[3];
+    /* magnetic vector values are in micro-Tesla (uT) */
+    float magnetic[3];
+    float magnetic_raw[3];
+
+    //float light[3];
+    //float proximity[3];
+    float thermometer;
+    float pressure;
+    int64_t input_time_acc;
+    int64_t input_time_gyro;
+    int64_t input_time_mag;
+    int64_t input_time_baro;
+
+} IMU, *LPIMU;
+
+/*
+ * Updates the posture of the device
+ *
+ * @param pImu A pointer to input data structure.
+ * @param deltaTime The time difference between calls. The unit is millisecond.
+ */
+int mpe_update_posture(LPIMU pImu, int deltaTime);
+/*
+ * Filter the raw data of the gyroscope
+ *
+ * @param pImu A pointer to input data structure.
+ * @param threshold Low-pass filter threshold. The unit is degree.
+ */
+void mpe_gyro_filter(LPIMU pImu, float threshold);
+/*
+ * Returns the rotation vector of the device
+ *
+ * The rotation vector represents the orientation of the device as a
+ * combination of an angle and an axis, in which the device has rotated
+ * through an angle theta around an axis [x, y, z]. The three elements
+ * of the rotation vector are
+ *
+ * vector = [x*sin(theta/2), y*sin(theta/2), z*sin(theta/2]
+ *
+ * @param vector The result rotation vector
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_rotation_vector(float *vector);
+/*
+ * Returns a gravity vector
+ *
+ * Gravity vector provides faster tilt angle change detection.
+ *
+ * @param gravity a 3-element array contains the result gravity vector
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_gravity(float *gravity);
+/*
+ * Returns a acceleration vector without gravity
+ *
+ * Linear acceleration decouples gravity so that applications can get more
+ * faster and precise motion.
+ *
+ * @param acceleration a 3-element array contains the result acceleration vector
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_linear_acceleration(float *acceleration);
+/*
+ * Returns euler angles of the device.
+ *
+ * Euler angles are used to describe the orientation of a rigid body. All
+ * values are angles in degrees.
+ * The three elements of euler angles are [azimuth, pitch, roll].
+ *
+ * @param angles a 3-element array contains the result euler angles
+ * @return 0 on success, < 0 on failure
+ */
+int mpe_get_euler_angle(float *angles);
+
+int mpe_get_game_rotation_vector(float *vector);
+int mpe_get_rotation_matrix(float *matrix);
+void mpe_set_fusion_mode(int mode);
+int mpe_re_initialize(void);
+int mpe_calculate_GEO_rotation_vector(float *gravity, float *geomagnetic, float *vector, float *euler);
+int mpe_get_global_rotation(LPIMU pImu, float *rotation);
+int mpe_set_radio_information(float *speed, float *confidence);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MPE_ATTITUDE_H_INCLUDED__ */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_DR.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_DR.h
new file mode 100644
index 0000000..f989e04
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_DR.h
@@ -0,0 +1,83 @@
+#ifndef __MPE_DR_H_INCLUDED__
+#define __MPE_DR_H_INCLUDED__
+
+#include "stdint.h"
+#include "mpe_Attitude.h"
+
+/******************************************************************************
+* Version Info
+******************************************************************************/
+
+#define MPE_VERSION_HEAD 'M','P','E','_','V','E','R','_'
+#define MPE_MAJOR_VERSION '1','8','0','3','2','0','0','1' // y,y,m,m,d,d,rev,rev
+#define MPE_BRANCH_INFO '_','3','.','0','0','_'
+#define MPE_MINER_VERSION '0','0'
+
+#define MPE_VER_INFO MPE_VERSION_HEAD,MPE_MAJOR_VERSION,MPE_BRANCH_INFO,MPE_MINER_VERSION
+
+#define MPE_GRAVITY_EARTH   9.8066f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct MNL2MPE_AIDING_DATA{
+    double  latitude[2]; /* latitude in radian */
+    double  longitude[2]; /* longitude in radian */
+    double  altitude[2]; /* altitude in meters above the WGS 84 reference ellipsoid */
+    float   KF_velocity[3]; /* Kalman Filter velocity in meters per second under (N,E,D) frame */
+    float   LS_velocity[3]; /* Least Square velocity in meters per second under (N,E,D) frame */
+    float   HACC; /*  position horizontal accuracy in meters */
+    float   VACC; /*  vertical accuracy in meters */
+    float   KF_velocitySigma[3]; /* Kalman Filter velocity one sigma error in meter per second under (N,E,D) frame */
+    float   LS_velocitySigma[3]; /* Least Square velocity one sigma error in meter per second under (N,E,D) frame */
+    float   HDOP; /* horizontal dilution of precision value in unitless */
+    float   confidenceIndex[3]; /* GPS confidence index */
+    unsigned int   gps_sec; /* Timestamp of GPS location */
+    unsigned int   leap_sec; /* correct GPS time with phone kernel time */
+} MNL2MPE_AIDING_DATA;
+
+
+typedef struct MPE2MNL_AIDING_DATA{
+    double  latitude; /* latitude in radian */
+    double  longitude; /* longitude in radian */
+    double  altitude; /* altitude in meters above the WGS 84 reference ellipsoid */
+    float   velocity[3]; /* SENSOR velocity in meters per second under (N,E,D) frame */
+    float   acceleration[3]; /* SENSOR acceleration in meters per second^2 under (N,E,D) frame */
+    float   HACC; /*  position horizontal accuracy in meters */
+    float   VACC; /*  vertical accuracy in meters */
+    float   velocitySigma[3]; /* SENSOR velocity one sigma error in meter per second under (N,E,D) frame */
+    float   accelerationSigma[3]; /* SENSOR acceleration one sigma error in meter per second^2 under (N,E,D) frame */
+    float   bearing; /* SENSOR heading in degrees UNDER (N,E,D) frame*/
+    float   confidenceIndex[3]; /*  SENSOR confidence index */
+    float   barometerHeight;         /*barometer height in meter*/
+    int     valid_flag[4]; /*  SENSOR AGMB hardware valid flag */
+    int     staticIndex; /* AR status [static, move, uncertain],[0,1,99]*/
+    unsigned long long timestamp; /* Timestamp of SENSOR location */
+} MPE2MNL_AIDING_DATA;
+
+
+typedef enum{
+    MTK_MPE_SYS_FLAG = 0x00,
+    MTK_MPE_KER_FLAG,
+    MTK_MPE_RAW_FLAG,
+    MTK_MPE_RES1_FLAG,
+    MTK_MPE_MAX_FLAG
+}MTK_VALID_FLAG_TYPE;
+
+
+int mpe_update_dead_reckoning(LPIMU pImu, int deltaTime_us, MNL2MPE_AIDING_DATA *pGPS);
+int get_map_matching_result(LPIMU pImu, MNL2MPE_AIDING_DATA *pGPS, MPE2MNL_AIDING_DATA dr_position, MNL2MPE_AIDING_DATA *pMAP);
+int mpe_get_dr_position(MPE2MNL_AIDING_DATA *pos);
+int mpe_get_dr_gyro_bias(float *bias);
+int mpe_get_dr_acc_bias(float *bias);
+int mpe_dr_re_initialize(void);
+int mpe_get_dr_entry(LPIMU pImu, MNL2MPE_AIDING_DATA *pGPS, MPE2MNL_AIDING_DATA *pos);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MPE_DR_H_INCLUDED__ */
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_common.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_common.h
new file mode 100644
index 0000000..6004282
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_common.h
@@ -0,0 +1,163 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef MPE_COMMON_H
+#define MPE_COMMON_H
+
+#include <string.h>
+#include <pthread.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#include <climits>   // C++ header
+#else
+#include <limits.h>  // C header
+#endif
+
+/******************************************************************************
+* Define
+******************************************************************************/
+/* MPE Conf flag */
+#define MPE_CONF_MPE_ENABLE     (1U<<0)
+#define MPE_CONF_PRT_RAWDATA    (1U<<1)
+#define MPE_CONF_AUTO_CALIB     (1U<<2)
+#define MPE_CONF_INDOOR_ENABLE  (1U<<3)
+
+// define TRUE and FALSE
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+// Ensure NULL is defined
+#ifdef NULL
+#undef NULL
+#endif
+#define NULL 0
+
+#define SECS_IN_DAY  (86400)            // Seconds in a Day
+#define DIFF_GPS_C_TIME ((365*10+2+5)*SECS_IN_DAY) // GPS epoch = 06Jan1980,  C epoch   = 01Jan1970,10years+leap years+,5 days Jan * sec in day
+
+typedef pthread_mutex_t MPE_MUTEX;
+typedef pthread_cond_t MPE_EVENT;
+
+//Socket name
+#define MNLD_MNL2ADR_SOCKET                 "mnl2adr_socket"
+#define MNLD_ADR2MNL_SOCKET                 "adr2mnl_socket"
+
+/*****************************************************************************
+ * FLP specific types
+ *****************************************************************************/
+//Define debug buffer size
+#define DEBUG_LOG
+#define MNL_MPE_MAX_BUFF_SIZE (6*1024)
+#define MNL_MPE_NMEA_MAX_SIZE (10*1024)
+
+#define MAX_NUM_SAMPLES 15
+#define MPE_LOG_NAME_MAX_LEN 128
+
+#define CMD_SEND_FROM_MNLD 0x40
+#define CMD_MPED_REBOOT_DONE 0x41
+/******************************************************************************
+* enum
+******************************************************************************/
+typedef enum {
+    MPE_IDLE_MODE = 0,
+    MPE_START_MODE  = 1,
+} MPE_OPERATION_MODE;
+
+typedef enum {
+    SENSOR_USER_ID_CALIB = 0,
+    SENSOR_USER_ID_MPE = 1,
+    SENSOR_USER_ID_MAX
+} SENSOR_USER_ID;
+
+typedef enum {
+    SENSOR_TYPE_ACC = 0,
+    SENSOR_TYPE_GYR,
+    SENSOR_TYPE_UNCAL_GYR,
+    SENSOR_TYPE_MAG,
+    SENSOR_TYPE_BAR,
+    SENSOR_TYPE_GYR_TMP,
+    SENSOR_TYPE_MAX
+} SENSOR_TYPE;
+
+typedef enum{
+    MNL_ADR_TYPE_MNL2ADR_GPS_OPEN = 0x100,
+    MNL_ADR_TYPE_MNL2ADR_GPS_OPEN_DONE,
+    MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE,
+    MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE_DONE,
+    MNL_ADR_TYPE_MNL2ADR_MNL_REBOOT,
+    MNL_ADR_TYPE_MNL2ADR_NMEA_DATA,
+
+    MNL_ADR_TYPE_ADR2MNL_NMEA_DATA = 0x200,
+    MNL_ADR_TYPE_ADR2MNL_PMTK_CMD
+}MNL_ADR_TYPE;
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/******************************************************************************
+* functions Prototype
+******************************************************************************/
+unsigned char mpe_sys_sensor_threads_create(void);
+UINT32 mpe_sys_get_mpe_conf_flag( void );
+void mpe_sys_read_mpe_conf_flag(void);
+INT32 mpe_sys_gps_to_sys_time ( UINT32 gps_sec);
+void mpe_sys_get_time_stamp(double* timetag, UINT32 leap_sec);
+
+void mpe_log_init();
+void mpe_log_deinit();
+UINT16 mpe_log_check_file();
+void mpe_log_mtklogger_check(INT16 record_mode, char *logpath, INT8 log_location);
+
+void mpe_run_algo( void );
+void mpe_kernel_initialize( void );
+int mnl2mpe_hdlr(int fd);
+void mnl2mpe_hdlr_init(void);
+int mpe2mnl_hdlr(char *buff);
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif //#ifndef MPE_COMMON_H
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_sensor.h b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_sensor.h
new file mode 100644
index 0000000..812eb25
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/inc/mpe_sensor.h
@@ -0,0 +1,72 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef SE_SENSOR_LISTENER_API_H
+#define SE_SENSOR_LISTENER_API_H
+
+#include "mpe_Attitude.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+typedef struct EVENT_DATA {
+    float x;
+    float y;
+    float z;
+    int64_t timestamp;
+} EVENT_DATA;
+
+//unsigned char mpe_sensor_get_listen_mode(void);
+void mpe_sensor_set_listen_mode(unsigned char mode);
+void mpe_sensor_get_accuracy(INT8 *accuracy);
+unsigned char mpe_sensor_init(SENSOR_USER_ID id);
+unsigned char mpe_sensor_deinit(SENSOR_USER_ID id);
+unsigned char mpe_sensor_start(SENSOR_USER_ID id, SENSOR_TYPE mpe_type, UINT32 periodInMs);
+unsigned char mpe_sensor_stop(SENSOR_USER_ID id, SENSOR_TYPE mpe_type);
+void mpe_sensor_get_calib_accuracy(INT8 *accuracy);
+unsigned char mpe_sensor_get_calib_gyr_data(void);
+unsigned char mpe_sensor_check_mnl_response(void);
+UINT16 mpe_sensor_check_time();
+UINT16 mpe_sensor_acquire_Data (IMU* data);
+void mpe_sensor_run (void);
+void mpe_sensor_update_mnl_sec(UINT32 gps_sec, UINT32 leap_sec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //#ifndef SE_SENSOR_LISTENER_API_H
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_logger.c b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_logger.c
new file mode 100644
index 0000000..e80b4f3
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_logger.c
@@ -0,0 +1,362 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+//-----------------------------------------------------------------------------
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include "mpe_common.h"
+#include "mpe_sensor.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE_LOG"
+#endif
+
+//-----------------------------------------------------------------------------
+//using namespace android;
+//-----------------------------------------------------------------------------
+
+#define MAX_DBG_LOG_W_SEC 3600
+#define MAX_DBG_LOG_DIR_SIZE   (300UL*1024UL*1024UL)
+#define MPE_DBG_LOG_FILE_NUM_LIMIT  200
+
+enum {
+    GPS_DEBUGLOG_DISABLE       = 0x00,
+    GPS_DEBUGLOG_ENABLE        = 0x01,
+};
+
+enum {
+    log_in_sdcard = 0x00,
+    log_in_data_misc,
+};
+
+FILE *data_file_local = NULL;
+static UINT32 current_file_w_sec = 0;
+static long long current_file_sec = 0;
+static INT32 current_file_index = 0;
+
+//for mtklogger
+INT16 u2Log_enable = 0;
+static INT8 u1Log_location = log_in_sdcard;
+static char Log_path[MPE_LOG_NAME_MAX_LEN];
+
+//extern UINT32 current_gps_sec;
+UINT32 current_gps_sec;
+
+static void mpe_log_check_and_delete_file (void);
+
+/*******************************************************************************
+* Static function
+********************************************************************************/
+
+static int GetFileSize(char *filename)
+{
+    char dir_filename[MPE_LOG_NAME_MAX_LEN];
+    struct stat statbuff;
+
+    memset(dir_filename, 0x00, sizeof(dir_filename));
+
+    if (NULL == filename) {
+        LOGD("File name is NULL!! %s", filename);
+        return 0;
+    }
+
+    snprintf(dir_filename, sizeof(dir_filename), "%s/%s", Log_path,filename);
+
+    if (stat(dir_filename,&statbuff) < 0) {
+        LOGD("open file(%s) state  fail(%s)!!", dir_filename, strerror(errno));
+        return 0;
+    } else {
+        return statbuff.st_size;
+    }
+}
+
+//-----------------------------------------------------------------------------
+static INT16 mpe_log_check_total_file(char se_filename[][MPE_LOG_NAME_MAX_LEN], unsigned long *total_file_size )
+{
+    DIR *dir;
+    struct dirent *ptr;
+    struct stat buf;
+    INT16 i= 0;
+    unsigned long tmp_size = 0, total_size = 0;
+    char pathname[MPE_LOG_NAME_MAX_LEN];
+    char *file_in_dir, name_tmp[MPE_LOG_NAME_MAX_LEN];
+
+    dir = opendir(Log_path);
+    *total_file_size = 0;
+
+    if (dir != NULL) {
+        while((ptr = readdir(dir)) != NULL && i < MPE_DBG_LOG_FILE_NUM_LIMIT) {
+            memset(pathname, 0, MPE_LOG_NAME_MAX_LEN);
+            memset(name_tmp, 0, MPE_LOG_NAME_MAX_LEN);
+            sprintf(pathname, "%s%s", Log_path, ptr->d_name );
+            if (stat(pathname, &buf) == -1) {
+                LOGD("stat return failed %s%s\n", Log_path, ptr->d_name);
+                continue;
+            }
+            if (i >= MPE_DBG_LOG_FILE_NUM_LIMIT) {
+                LOGD("max file reached %d\n",i);
+                break;
+            }
+            if (S_ISREG(buf.st_mode)) {
+                file_in_dir = ptr->d_name;
+                if(!strncmp(file_in_dir, "se_ut", 5)) {
+                    memcpy(&name_tmp,file_in_dir, MPE_LOG_NAME_MAX_LEN);
+                    memcpy((se_filename+i), &name_tmp, MPE_LOG_NAME_MAX_LEN);
+                    tmp_size = GetFileSize(*(se_filename+i));
+                    total_size += tmp_size;
+                    i++;
+                }
+            }
+        }
+        closedir(dir);
+        *total_file_size = total_size;
+        LOGD("total file size = %lu %"PRId16, total_size, i);
+    }
+    return i;
+}
+
+//-----------------------------------------------------------------------------
+static void mpe_log_conv_filename_to_time( UINT16 file_cnt, char se_filename[][MPE_LOG_NAME_MAX_LEN], INT32 *file_time[],UINT16 *oldest_file_indx  )
+{
+    UINT16 min_index = 0, j;
+    INT32 min_time = 0, min_subtag = 0;
+    INT32 local_file_time[MPE_DBG_LOG_FILE_NUM_LIMIT];
+    INT32 local_file_subtag[MPE_DBG_LOG_FILE_NUM_LIMIT] = { 0 };
+    char tmp_file_time[12];
+    char tmp_file_subtag[12];
+    char tmp_file_name[MPE_LOG_NAME_MAX_LEN];
+
+    if (file_cnt < 1) {
+        return;
+    }
+
+    for (j = 0; j < file_cnt; j++) {
+        memset(tmp_file_time, 0, sizeof(tmp_file_time));
+        memset(tmp_file_subtag, 0, sizeof(tmp_file_subtag));
+        memset(tmp_file_name, 0, sizeof(tmp_file_name));
+        strncpy(tmp_file_name, se_filename[j], strlen(se_filename[j]));
+        tmp_file_name[strlen(tmp_file_name)-4] = 0;
+        if (tmp_file_name[16] == '_') {
+            strncpy(tmp_file_subtag, tmp_file_name+17, strlen(tmp_file_name+17));
+            local_file_subtag[j] = atoi(tmp_file_subtag);
+        } else {
+            local_file_subtag[j] = 0;
+        }
+
+        tmp_file_name[16] = 0;
+        strncpy(tmp_file_time, tmp_file_name+5, strlen(tmp_file_name+5));
+        local_file_time[j] = atoi(tmp_file_time);
+
+        if ((j == 0) || (local_file_time[j] < min_time) ||
+            (local_file_time[j] == min_time && local_file_subtag[j] < min_subtag))
+        {
+            min_time = local_file_time[j];
+            min_subtag = local_file_subtag[j];
+            min_index = j;
+        }
+    }
+    memcpy(file_time,local_file_time, file_cnt*sizeof(INT32));
+
+    *oldest_file_indx = min_index;
+    LOGD("oldest_file = %u, %s, %d %d\n", *oldest_file_indx, se_filename[min_index], min_time, min_subtag);
+
+    return;
+}
+
+
+//-----------------------------------------------------------------------------
+static void mpe_log_check_and_delete_file (void)
+{
+    unsigned long total_file_size;
+    char se_filename[MPE_DBG_LOG_FILE_NUM_LIMIT][MPE_LOG_NAME_MAX_LEN];
+    INT16 total_file;
+    UINT16 oldest_indx;
+    INT32 *file_time[MPE_DBG_LOG_FILE_NUM_LIMIT];
+    char del_filename[MPE_LOG_NAME_MAX_LEN];
+
+    total_file = mpe_log_check_total_file(se_filename, &total_file_size);
+
+    if (total_file > 0) {
+        mpe_log_conv_filename_to_time(total_file, se_filename, file_time, &oldest_indx);
+        while (total_file_size > MAX_DBG_LOG_DIR_SIZE || total_file >= MPE_DBG_LOG_FILE_NUM_LIMIT) {
+            LOGD("total size = %lu, total file = %"PRId16, total_file_size, total_file);
+
+            //remove oldest file
+            memset(del_filename, 0, MPE_LOG_NAME_MAX_LEN);
+            sprintf(del_filename, "%s%s", Log_path,*(se_filename + oldest_indx));
+            LOGD("delete filename %s %s", del_filename, *(se_filename+oldest_indx));
+
+            if (remove(del_filename) == 0) {
+                LOGD("remove %s success", del_filename);
+            } else {
+                LOGD("remove %s failed", del_filename);
+            }
+
+            total_file = mpe_log_check_total_file(se_filename, &total_file_size);
+            mpe_log_conv_filename_to_time(total_file, se_filename, file_time, &oldest_indx);
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+static unsigned char mpe_log_open_new_file (void)
+{
+    char name[MPE_LOG_NAME_MAX_LEN];
+    unsigned char ret = FALSE;
+    char header_name[6] = "se_ut";
+
+    if (data_file_local != NULL) {
+        fclose(data_file_local);
+    } else {
+        return ret;
+    }
+
+    if (u2Log_enable) {
+        current_file_index++;
+        sprintf(name, "%s%s0%lld_%d.txt", Log_path, header_name, current_file_sec, current_file_index);
+        LOGD("open file - time %s", name);
+        data_file_local = fopen(name, "w+");
+        if (data_file_local == NULL) {
+            LOGD("se file open %s\n", strerror(errno));
+            ret = FALSE;
+        } else {
+            ret = TRUE;
+        }
+        mpe_log_check_and_delete_file();
+    }
+    return ret;
+}
+
+/*******************************************************************************
+* Global function
+********************************************************************************/
+void mpe_log_mtklogger_check ( INT16 record_mode, char *logpath, INT8 log_location)
+{
+    //char name[MPE_LOG_NAME_MAX_LEN];
+    //char header_name[6] = "se_ut";
+
+    if (record_mode == GPS_DEBUGLOG_DISABLE) {
+        u2Log_enable = 0;
+
+        if (data_file_local != NULL) {
+            LOGD("stop recording se data");
+            data_file_local = NULL;
+        }
+    } else if(record_mode == GPS_DEBUGLOG_ENABLE) {
+        memcpy(&Log_path, logpath, MPE_LOG_NAME_MAX_LEN);
+        u2Log_enable = 1;
+        LOGD("se logger path: %s", Log_path);
+
+        /*if (data_file_local == NULL && mpe_sensor_get_listen_mode() == MPE_START_MODE) {
+            sprintf(name, "%s%s0%u.txt", Log_path, header_name, current_gps_sec);
+            current_file_sec = (long long)current_gps_sec;
+            current_file_index = 0;
+            data_file_local = fopen(name,"w+");
+            LOGD("open file - mtklog %s\n", name);
+            if (data_file_local == NULL) {
+                LOGD("se file open %s\n", strerror(errno));
+            }
+            if (chmod(name, 0600) < 0) {
+                LOGD("se file chmod %s\n", strerror(errno));
+            }
+            mpe_log_check_and_delete_file();
+        }*/
+    }
+    u1Log_location = log_location;
+}
+
+UINT16 mpe_log_check_file()
+{
+    unsigned char file_stat;
+
+    if (u2Log_enable) {
+        current_file_w_sec++;
+        if (current_file_w_sec >= MAX_DBG_LOG_W_SEC) {
+            file_stat = mpe_log_open_new_file();
+            if (file_stat) {
+                current_file_w_sec = 0;
+            }
+        }
+    }
+    return 0;
+}
+
+void mpe_log_init()
+{
+    char name[MPE_LOG_NAME_MAX_LEN];
+    char header_name[6] = "se_ut";
+
+    current_file_w_sec = 0;
+    if (u2Log_enable) {
+        LOGD("logpath : %s", Log_path);
+        sprintf(name, "%s%s0%u.txt",Log_path, header_name ,current_gps_sec);
+        current_file_sec = (long long)current_gps_sec;
+        current_file_index = 0;
+
+        LOGD("open file - gps %s", name);
+        data_file_local = fopen(name, "w+");
+        if (data_file_local == NULL) {
+            LOGD("se file open %s\n", strerror(errno));
+        }
+        if(chmod(name, 0600) < 0) {
+            LOGD("se file chmod %s\n", strerror(errno));
+        }
+        mpe_log_check_and_delete_file();
+    }
+    return;
+}
+void mpe_log_deinit()
+{
+    if(data_file_local != NULL) {
+        fclose(data_file_local);
+    }
+    current_file_w_sec = 0;
+    return;
+}
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_main.c b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_main.c
new file mode 100644
index 0000000..8460eb5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_main.c
@@ -0,0 +1,315 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2008
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER 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 BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'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 BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+***************************************************************/
+#ifndef MPE_MAIN_C
+#define MPE_MAIN_C
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*****************************************************************************
+ * Include
+ *****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "mpe_common.h"
+#include "mpe_DR.h"
+#include "mpe_sensor.h"
+#include "mpe.h"
+#include "data_coder.h"
+#include "mtk_lbs_utility.h"
+#include "mnld.h"
+#include "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+#if defined(__ANDROID_OS__)
+#include <private/android_filesystem_config.h>
+#endif
+
+#if defined(__ANDROID_OS__)
+#define MPE_DEFAULT_CONFIG_FILE "/system/vendor/etc/adr/mpe.conf"
+#elif defined(__LINUX_OS__)
+#define MPE_DEFAULT_CONFIG_FILE "/etc/adr/mpe.conf"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE_MA"
+#endif
+
+/*****************************************************************************
+ * GLobal Variable
+ *****************************************************************************/
+static const char pMPEVersion[] = {MPE_VER_INFO,0x00};
+unsigned char isUninit_SE = FALSE;
+static MNL2MPE_AIDING_DATA mnl_latest_in;
+static MNL2MPE_AIDING_DATA mnl_glo_in;
+static MPE2MNL_AIDING_DATA mnl_glo_out;
+static UINT32 gMPEConfFlag = 0;
+
+//Mtklogger function
+char mpe_debuglog_file_name[MPE_LOG_NAME_MAX_LEN];
+
+//check for baro validity
+//extern unsigned char isfirst_baro;
+unsigned char isfirst_baro = 0;
+
+// se log
+extern FILE *data_file_local;
+
+float gyr_temperature = 0.0f;
+float gyr_scp_calib_done = 0.0f;
+
+unsigned char gMpeThreadExist = 0;
+
+UINT32 mpe_sys_get_mpe_conf_flag(void) {
+    return gMPEConfFlag;
+}
+
+void mpe_sys_read_mpe_conf_flag(void) {
+    const char mpe_prop_path[] = MPE_DEFAULT_CONFIG_FILE;
+    char propbuf[512];
+    UINT32 flag = 0;
+    FILE *fp = fopen(mpe_prop_path, "rb");
+    LOGD("%s\n", pMPEVersion);
+    if(!fp) {
+        LOGD("mpe config flag - can't open");
+        gMPEConfFlag = 0;
+        return;
+    }
+    while(fgets(propbuf, sizeof(propbuf), fp)) {
+        if(strstr(propbuf, "mpe_enable=1")) {
+            flag |= MPE_CONF_MPE_ENABLE;
+        } else if(strstr(propbuf, "print_rawdata=1")) {
+            flag |= MPE_CONF_PRT_RAWDATA;
+        } else if(strstr(propbuf, "auto_calib=1")) {
+            flag |= MPE_CONF_AUTO_CALIB;
+        } else if(strstr(propbuf, "indoor_enable=1")) {
+            flag |= MPE_CONF_INDOOR_ENABLE;
+        }
+    }
+    LOGD("mpe config flag %u", flag);
+    fclose(fp);
+    gMPEConfFlag = flag;
+    return;
+}
+
+INT32 mpe_sys_gps_to_sys_time( UINT32 gps_sec ) {
+    return (INT32) ( gps_sec + DIFF_GPS_C_TIME );// difference between GPS and
+}
+
+void mpe_sys_get_time_stamp(double* timetag, UINT32 leap_sec) {
+    struct tm tm_pt;
+    struct timeval tv;
+    //get second and usec
+    gettimeofday(&tv, NULL);
+    //convert to local time
+    localtime_r(&tv.tv_sec, &tm_pt);
+    (*timetag) = mktime(&tm_pt);
+    (*timetag)= (*timetag) + leap_sec +((float)tv.tv_usec)/1000000;
+}
+
+void mnl2mpe_hdlr_init(void) {
+    memset(&mnl_latest_in, 0 , sizeof(MNL2MPE_AIDING_DATA));
+    memset(&mnl_glo_in, 0 , sizeof(MNL2MPE_AIDING_DATA));
+    memset(&mnl_glo_out, 0 , sizeof(MPE2MNL_AIDING_DATA));
+}
+
+int adr2mnl_send_nmea_data(const char * nmea_buffer, const UINT32 length) {
+    LOGD("adr2mnl_send_nmea_data");
+    char buff[MNL_MPE_NMEA_MAX_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_ADR2MNL_NMEA_DATA);
+    put_int(buff, &offset, length);
+    put_binary(buff, &offset, nmea_buffer, length);
+
+    return safe_sendto(MNLD_ADR2MNL_SOCKET, buff, MNL_MPE_NMEA_MAX_SIZE);
+}
+
+int mnl2mpe_hdlr(int fd) {
+    char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int mnl2mpe_offset = 0;
+    int read_len;
+    int log_rec = 0, rec_loc =0;
+    UINT32 type, length;
+
+    read_len = safe_recvfrom(fd, mnl2mpe_buff, sizeof(mnl2mpe_buff));
+    if (read_len <= 0) {
+        LOGE("safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    type = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+    length = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+    LOGD("mpe recv, type = %u, len = %u", type, length);
+
+    switch (type) {
+        case CMD_SEND_FROM_MNLD: {
+            log_rec = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+            rec_loc = get_int(mnl2mpe_buff, &mnl2mpe_offset, sizeof(mnl2mpe_buff));
+            get_binary(mnl2mpe_buff, &mnl2mpe_offset, mpe_debuglog_file_name, sizeof(mnl2mpe_buff), sizeof(mpe_debuglog_file_name));
+            LOGD("log_rec =%d, rec_loc=%d, mpelog_path:%s", log_rec, rec_loc,mpe_debuglog_file_name );
+            mpe_log_mtklogger_check((INT16)log_rec, mpe_debuglog_file_name, (INT8)rec_loc);
+            break;
+        }
+        case MNL_ADR_TYPE_MNL2ADR_NMEA_DATA: {
+            char nmea[MNL_MPE_NMEA_MAX_SIZE] = {0};
+            get_binary(mnl2mpe_buff, &mnl2mpe_offset, nmea, sizeof(mnl2mpe_buff), sizeof(nmea));
+            LOGD("rec nmea:%s", nmea);
+            if(length <= MNL_MPE_NMEA_MAX_SIZE) {
+                adr2mnl_send_nmea_data(nmea, length);
+            }
+            break;
+        }
+        default: {
+            LOGD("MPE_DBG: invalid msg type = %d", type);
+        }
+    }
+    return 0;
+}
+
+int mpe_kernel_inject(IMU* data, UINT16 len, MPE2MNL_AIDING_DATA *mnl_out) {
+    int i=0;
+    UNUSED(mnl_out);
+
+    if(data == NULL) {
+        LOGD("allocate sensor cb error\n");
+        return MTK_GPS_ERROR;
+    }
+
+    for(i = 0; i < len; i++ ) {
+        if(data + i != NULL) {
+            if (mpe_sys_get_mpe_conf_flag() & MPE_CONF_PRT_RAWDATA) {
+                LOGD("[%d] MPErpy %"PRId64" %f %f %f %f %f %f %f %f %f %f %lf %lf %lf %lf %lf %lf %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %u %u %f",
+                    i, (data+i)->input_time_gyro,
+                    (data+i)->acceleration[0], (data+i)->acceleration[1], (data+i)->acceleration[2],
+                    (data+i)->angularVelocity[0], (data+i)->angularVelocity[1], (data+i)->angularVelocity[2],
+                    (data+i)->magnetic[0], (data+i)->magnetic[1], (data+i)->magnetic[2],
+                    (data+i)->pressure,
+                    mnl_glo_in.latitude[0], mnl_glo_in.longitude[0], mnl_glo_in.altitude[0],
+                    mnl_glo_in.latitude[1], mnl_glo_in.longitude[1], mnl_glo_in.altitude[1],
+                    mnl_glo_in.LS_velocity[0], mnl_glo_in.LS_velocity[1], mnl_glo_in.LS_velocity[2],
+                    mnl_glo_in.KF_velocity[0], mnl_glo_in.KF_velocity[1], mnl_glo_in.KF_velocity[2],
+                    mnl_glo_in.LS_velocitySigma[0], mnl_glo_in.LS_velocitySigma[1], mnl_glo_in.LS_velocitySigma[2],
+                    mnl_glo_in.KF_velocitySigma[0], mnl_glo_in.KF_velocitySigma[1], mnl_glo_in.KF_velocitySigma[2],
+                    mnl_glo_in.HACC, mnl_glo_in.VACC, mnl_glo_in.HDOP,
+                    mnl_glo_in.confidenceIndex[0], mnl_glo_in.confidenceIndex[1], mnl_glo_in.confidenceIndex[2],
+                    mnl_glo_in.gps_sec, mnl_glo_in.leap_sec, (data+i)->thermometer);
+            }
+
+            /*if (mpe_get_dr_entry(data+i, &mnl_glo_in, mnl_out)) {
+                if (mpe_sys_get_mpe_conf_flag() & MPE_CONF_PRT_RAWDATA) {
+                    LOGD("MPE_DBG: MPE mpe_update_posture return false");
+                }
+            }*/
+        } else {
+            LOGD("accept null data\n");
+        }
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+void mpe_set_mnl_out_flag(MPE2MNL_AIDING_DATA *mnl_out) {
+    //if (mpe_sensor_get_listen_mode() == MPE_START_MODE) {
+    if (0) {
+        mnl_out->valid_flag[MTK_MPE_SYS_FLAG] = 1;
+    } else {
+        mnl_out->valid_flag[MTK_MPE_SYS_FLAG] = 0;
+    }
+    mnl_out->valid_flag[MTK_MPE_RAW_FLAG] = 1;
+    if(isfirst_baro == 1) {
+        mnl_out->barometerHeight= -16000;
+    }
+    if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_INDOOR_ENABLE) || gyr_scp_calib_done == 0) {
+        mnl_out->HACC= 20000;
+    }
+}
+
+/*void mpe_sensor_stop_notify( void ) {
+    char mpe2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(mpe2mpe_buff, &offset, CMD_STOP_MPE_REQ);
+    put_int(mpe2mpe_buff, &offset, sizeof(INT32));
+    put_int(mpe2mpe_buff, &offset, 2);
+    safe_sendto(MNLD_MPE_SOCKET, mpe2mpe_buff, MNL_MPE_MAX_BUFF_SIZE);
+    isUninit_SE = TRUE;
+    LOGD("send uninit request from listener \n");
+}*/
+
+void mpe_run_algo( void ) {
+    //int data_ret = 0;
+    IMU SE_data[MAX_NUM_SAMPLES];
+    //UINT16 data_cnt = 0;
+    MPE2MNL_AIDING_DATA mnl_out;
+
+    memset(SE_data, 0 ,MAX_NUM_SAMPLES*sizeof(IMU));
+    memset(&mnl_out, 0, sizeof(MPE2MNL_AIDING_DATA));
+
+    //data_cnt = mpe_sensor_acquire_Data(SE_data);
+#if 0
+    if(data_cnt) {
+        data_ret = mpe_kernel_inject(SE_data, data_cnt, &mnl_out);
+        mpe_set_mnl_out_flag(&mnl_out);
+        memcpy(&mnl_glo_out, &mnl_out, sizeof(MPE2MNL_AIDING_DATA));
+    }
+#endif
+    memcpy(&mnl_glo_in, &mnl_latest_in, sizeof(MNL2MPE_AIDING_DATA));
+}
+
+#ifdef __cplusplus
+  extern "C" }
+#endif
+
+#endif //#ifndef MPE_FUSION_MAIN_C
diff --git a/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_sensor.cpp b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_sensor.cpp
new file mode 100644
index 0000000..86e315b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_mpe_interface/src/mpe_sensor.cpp
@@ -0,0 +1,589 @@
+/* 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) 2010. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+//-----------------------------------------------------------------------------
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <dirent.h>
+#include <errno.h>
+#include "mpe_common.h"
+#include "mpe_sensor.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE_SE"
+#endif
+
+#if defined(__ANDROID_OS__)
+/* HIDL */
+#include <sys/prctl.h>
+#include <android/sensor.h>
+#include <android-base/macros.h>
+#include <android/frameworks/sensorservice/1.0/IEventQueue.h>
+#include <android/frameworks/sensorservice/1.0/IEventQueueCallback.h>
+#include <android/frameworks/sensorservice/1.0/ISensorManager.h>
+#include <sensors/convert.h>
+#include <utils/Mutex.h>
+
+using namespace android;
+using android::frameworks::sensorservice::V1_0::ISensorManager;
+using android::frameworks::sensorservice::V1_0::Result;
+using android::hardware::sensors::V1_0::SensorType;
+using android::frameworks::sensorservice::V1_0::IEventQueueCallback;
+using android::hardware::Return;
+using android::hardware::sensors::V1_0::Event;
+using android::frameworks::sensorservice::V1_0::IEventQueue;
+#endif
+
+#define SENSOR_TYPE_DEVICE_PRIVATE_BASE       65536
+#define SENSOR_TYPE_GYRO_TEMPERATURE          (71 + SENSOR_TYPE_DEVICE_PRIVATE_BASE)
+
+#define SENSOR_LOG_SCALE 1e6
+
+unsigned char isfirst_baro = 1;
+UINT32 current_gps_sec = 0;
+
+static unsigned char phone_time_reset = 0;
+static UINT32 current_leap_sec = 18;
+static double mnl_inject_sys_time = 0.0;
+static unsigned char SE_listener_mode = MPE_IDLE_MODE;
+static UINT16 gyr_log_cnt = 0;
+static INT64 gyr_log_time = 0;
+
+//chre data sync
+static UINT16 acc_cnt = 0;
+static UINT16 gyr_cnt = 0;
+static unsigned char prev_data_is_gyro = false;
+static EVENT_DATA acc_samples[MAX_NUM_SAMPLES];
+static EVENT_DATA gyr_samples[MAX_NUM_SAMPLES];
+static EVENT_DATA mag_samples;
+static float bar_samples = 0;
+float gyr_temperature = 0.0f;
+float gyr_scp_calib_done = 0.0f;
+
+static INT8 raw_accuracy[SENSOR_TYPE_MAX] = {0};
+static INT8 calib_accuracy[SENSOR_TYPE_MAX] = {0};
+static unsigned char calib_get_gyro_data = false;
+
+extern FILE *data_file_local;
+extern INT16 u2Log_enable;
+
+typedef enum {
+    SENSOR_ERR   = -1,
+    SENSOR_INIT   = 0,
+    SENSOR_UNINIT = 1,
+} SENSOR_STATUS;
+
+#if defined(__ANDROID_OS__)
+class SensorDeathRecipient : public android::hardware::hidl_death_recipient
+{
+public:
+    // hidl_death_recipient interface
+    virtual void serviceDied(uint64_t cookie,
+            const ::android::wp<::android::hidl::base::V1_0::IBase>& who) override;
+};
+#endif
+
+typedef struct SENSOR_CONTEXT {
+#if defined(__ANDROID_OS__)
+
+    Mutex   mDataLock;
+    int32_t sensorHandle[SENSOR_TYPE_MAX];
+    int     mSensorStatus[SENSOR_TYPE_MAX];
+    sp<IEventQueueCallback> mpListener;
+    sp<IEventQueue> queue;
+    sp<SensorDeathRecipient> mpDeathRecipient;
+#endif
+} SENSOR_CONTEXT;
+
+static SENSOR_CONTEXT sensorContext[SENSOR_USER_ID_MAX];
+
+//-----------------------------------------------------------------------------
+unsigned char mpe_sensor_get_listen_mode(void)
+{
+    return SE_listener_mode;
+}
+
+void mpe_sensor_set_listen_mode(unsigned char mode)
+{
+    LOGD("Set listen mode from %u to %u", SE_listener_mode, mode);
+    SE_listener_mode = mode;
+}
+
+
+UINT16 mpe_sensor_check_time()
+{
+    INT32 mnl_inject_gps_time;
+    double time_diff;
+
+    mnl_inject_gps_time = mpe_sys_gps_to_sys_time(current_gps_sec);
+    time_diff = abs((int)(mnl_inject_sys_time - mnl_inject_gps_time));
+
+    if (time_diff > 3600) {
+        LOGD("Detect change in global time, global: %lf, gps: %d, diff: %lf \n",mnl_inject_sys_time, mnl_inject_gps_time, time_diff);
+        phone_time_reset = 1;
+    } else {
+        phone_time_reset = 0;
+    }
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+void mpe_sensor_get_accuracy(INT8 *accuracy)
+{
+    memcpy(accuracy, raw_accuracy, sizeof(raw_accuracy));
+}
+
+//-----------------------------------------------------------------------------
+
+UINT16 mpe_sensor_acquire_Data (IMU* data)
+{
+    INT16 i = 0, j = 0;
+    UINT16 size = 0;
+
+    //LOGD("SE_Acquire_Data acc_cnt:%u gyr:%u",acc_cnt, gyr_cnt);
+    if (gyr_cnt >= MAX_NUM_SAMPLES || gyr_cnt == 0) {
+        LOGD("MPE_DBG: gyr data abnormal, acc_cnt:%d, gyr_cnt:%d",acc_cnt, gyr_cnt);
+        size = 0;
+    } else if (acc_cnt >= MAX_NUM_SAMPLES || acc_cnt == 0) {
+        LOGD("MPE_DBG: acc data abnormal, acc_cnt:%d, gyr_cnt:%d",acc_cnt, gyr_cnt);
+        size = 0;
+    } else {
+        for(i = 0; i < gyr_cnt; i++) {
+            // acc
+            if(i >= acc_cnt) {
+                j = acc_cnt - 1;
+            } else {
+                j = i;
+            }
+            data[i].acceleration[0] = acc_samples[j].x;
+            data[i].acceleration[1] = acc_samples[j].y;
+            data[i].acceleration[2] = acc_samples[j].z;
+            data[i].acceleration_raw[0] = acc_samples[j].x;
+            data[i].acceleration_raw[1] = acc_samples[j].y;
+            data[i].acceleration_raw[2] = acc_samples[j].z;
+            data[i].input_time_acc = acc_samples[j].timestamp;
+
+            // gyro
+            data[i].angularVelocity[0] = gyr_samples[i].x;
+            data[i].angularVelocity[1] = gyr_samples[i].y;
+            data[i].angularVelocity[2] = gyr_samples[i].z;
+            data[i].angularVelocity_raw[0] = gyr_samples[i].x;
+            data[i].angularVelocity_raw[1] = gyr_samples[i].y;
+            data[i].angularVelocity_raw[2] = gyr_samples[i].z;
+            data[i].input_time_gyro = gyr_samples[i].timestamp;
+            data[i].thermometer = gyr_temperature;
+
+            // mag
+            data[i].magnetic[0] = mag_samples.x;
+            data[i].magnetic[1] = mag_samples.y;
+            data[i].magnetic[2] = mag_samples.z;
+            data[i].magnetic_raw[0] = mag_samples.x;
+            data[i].magnetic_raw[1] = mag_samples.y;
+            data[i].magnetic_raw[2] = mag_samples.z;
+            data[i].input_time_mag = mag_samples.timestamp;
+
+            // pres
+            data[i].pressure = bar_samples;
+        }
+        size = gyr_cnt;
+    }
+    acc_cnt = 0;
+    gyr_cnt = 0;
+    memset(&acc_samples, 0 ,MAX_NUM_SAMPLES*sizeof(EVENT_DATA));
+    memset(&gyr_samples, 0 ,MAX_NUM_SAMPLES*sizeof(EVENT_DATA));
+    return size;
+}
+
+// Update mnl_inject_sys_time, current_gps_sec, current_leap_sec
+void mpe_sensor_update_mnl_sec(UINT32 gps_sec, UINT32 leap_sec)
+{
+    current_gps_sec = gps_sec;
+    current_leap_sec = leap_sec;
+    mpe_sys_get_time_stamp(&mnl_inject_sys_time, current_leap_sec);
+    return;
+}
+
+//-----------------------------------------------------------------------------
+void mpe_sensor_run(void)
+{
+    unsigned char ret = FALSE;
+    INT32 mnl_inject_gps_time;
+
+    LOGD("SE sensor run source\n");
+    mnl_inject_gps_time = mpe_sys_gps_to_sys_time(current_gps_sec);
+    LOGD("mnl_inject_gps_time: %d, mnl_inject_sys_time: %lf",mnl_inject_gps_time, mnl_inject_sys_time);
+    LOGD("global_gps_diff =%lf\n", (fabs(mnl_inject_sys_time - mnl_inject_gps_time)));
+
+    if(fabs(mnl_inject_sys_time - mnl_inject_gps_time) <= 3600.0)
+    {
+        if(!mpe_sys_sensor_threads_create())
+        {
+            return;
+        }
+        mpe_sensor_set_listen_mode(MPE_START_MODE);
+        mpe_log_init();
+
+        //register sensor listener
+        mpe_kernel_initialize();
+        LOGD("SE_sensor_run success");
+    }
+    return;
+}
+
+#if defined(__ANDROID_OS__)
+class CalibListenrCallback : public IEventQueueCallback {
+  public:
+    Return<void> onEvent(const Event &e) {
+        sensors_event_t sensorEvent;
+        android::hardware::sensors::V1_0::implementation::convertToSensorEvent(e, &sensorEvent);
+
+        switch(e.sensorType)
+        {
+            case SensorType::GYROSCOPE:
+                calib_accuracy[SENSOR_TYPE_GYR] = sensorEvent.gyro.status;
+                calib_get_gyro_data = TRUE;
+                break;
+            default:
+                LOGD("unknown type(%d)", sensorEvent.type);
+        }
+        return android::hardware::Void();
+    }
+};
+
+class MpeListenrCallback : public IEventQueueCallback {
+  public:
+    Return<void> onEvent(const Event &e) {
+        sensors_event_t sensorEvent;
+        android::hardware::sensors::V1_0::implementation::convertToSensorEvent(e, &sensorEvent);
+
+        switch(e.sensorType)
+        {
+            case SensorType::ACCELEROMETER:
+                if(prev_data_is_gyro) {
+                    prev_data_is_gyro = false;
+                    mpe_run_algo();
+                }
+                if(acc_cnt < MAX_NUM_SAMPLES) {
+                    acc_samples[acc_cnt].x = sensorEvent.acceleration.x;
+                    acc_samples[acc_cnt].y = sensorEvent.acceleration.y;
+                    acc_samples[acc_cnt].z = sensorEvent.acceleration.z;
+                    acc_samples[acc_cnt].timestamp = sensorEvent.timestamp;
+                    acc_cnt++;
+                    raw_accuracy[SENSOR_TYPE_ACC] = sensorEvent.acceleration.status;
+
+                    if(u2Log_enable && (data_file_local != NULL)) {
+                        fprintf(data_file_local,"$%c%X%c%X%c%X\n",(sensorEvent.acceleration.x<0)?'-':' ',abs((int)(sensorEvent.acceleration.x*SENSOR_LOG_SCALE)),
+                            (sensorEvent.acceleration.y<0)?'-':' ',abs((int)(sensorEvent.acceleration.y*SENSOR_LOG_SCALE)),
+                            (sensorEvent.acceleration.z<0)?'-':' ',abs((int)(sensorEvent.acceleration.z*SENSOR_LOG_SCALE)));
+                    }
+                }
+                break;
+            case SensorType::GYROSCOPE:
+                if(gyr_cnt < MAX_NUM_SAMPLES) {
+                    gyr_samples[gyr_cnt].x = sensorEvent.gyro.x;
+                    gyr_samples[gyr_cnt].y = sensorEvent.gyro.y;
+                    gyr_samples[gyr_cnt].z = sensorEvent.gyro.z;
+                    gyr_samples[gyr_cnt].timestamp = sensorEvent.timestamp;
+                    gyr_cnt++;
+                    raw_accuracy[SENSOR_TYPE_GYR] = sensorEvent.gyro.status;
+                }
+                prev_data_is_gyro = true;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    if(gyr_log_cnt >= 200 || gyr_log_cnt == 0) {
+                        fprintf(data_file_local,"^ %llX\n",(sensorEvent.timestamp));
+                        gyr_log_cnt = 0;
+                        gyr_log_time = sensorEvent.timestamp;
+                    }
+                    gyr_log_cnt++;
+                    fprintf(data_file_local, "! %X%c%X%c%X%c%X\n",(int)((sensorEvent.timestamp-gyr_log_time)/1000.0),
+                        (sensorEvent.gyro.x<0)?'-':' ',abs((int)(sensorEvent.gyro.x*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.y<0)?'-':' ',abs((int)(sensorEvent.gyro.y*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.z<0)?'-':' ',abs((int)(sensorEvent.gyro.z*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case SensorType::GYROSCOPE_UNCALIBRATED:
+                if(gyr_cnt < MAX_NUM_SAMPLES) {
+                    gyr_samples[gyr_cnt].x = sensorEvent.uncalibrated_gyro.x_uncalib;
+                    gyr_samples[gyr_cnt].y = sensorEvent.uncalibrated_gyro.y_uncalib;
+                    gyr_samples[gyr_cnt].z = sensorEvent.uncalibrated_gyro.z_uncalib;
+                    gyr_samples[gyr_cnt].timestamp = sensorEvent.timestamp;
+                    gyr_cnt++;
+                    raw_accuracy[SENSOR_TYPE_GYR] = 3;
+                }
+                prev_data_is_gyro = true;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    if(gyr_log_cnt >= 200 || gyr_log_cnt == 0) {
+                        fprintf(data_file_local,"^ %llX\n",(sensorEvent.timestamp));
+                        gyr_log_cnt = 0;
+                        gyr_log_time = sensorEvent.timestamp;
+                    }
+                    gyr_log_cnt++;
+                    fprintf(data_file_local, "! %X%c%X%c%X%c%X%c%X\n",(int)((sensorEvent.timestamp-gyr_log_time)/1000.0),
+                        (sensorEvent.gyro.x<0)?'-':' ',abs((int)(sensorEvent.gyro.x*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.y<0)?'-':' ',abs((int)(sensorEvent.gyro.y*SENSOR_LOG_SCALE)),
+                        (sensorEvent.gyro.z<0)?'-':' ',abs((int)(sensorEvent.gyro.z*SENSOR_LOG_SCALE)),
+                        (gyr_temperature<0)?'-':' ',abs((int)(gyr_temperature*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case SensorType::MAGNETIC_FIELD:
+                mag_samples.x = sensorEvent.magnetic.x;
+                mag_samples.y = sensorEvent.magnetic.y;
+                mag_samples.z = sensorEvent.magnetic.z;
+                mag_samples.timestamp = sensorEvent.timestamp;
+                raw_accuracy[SENSOR_TYPE_MAG] = sensorEvent.magnetic.status;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    fprintf(data_file_local,"@%c%X%c%X%c%X\n",(sensorEvent.magnetic.x<0)?'-':' ',abs((int)(sensorEvent.magnetic.x*SENSOR_LOG_SCALE)),
+                        (sensorEvent.magnetic.y<0)?'-':' ',abs((int)(sensorEvent.magnetic.y*SENSOR_LOG_SCALE)),
+                        (sensorEvent.magnetic.z<0)?'-':' ',abs((int)(sensorEvent.magnetic.z*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case SensorType::PRESSURE:
+                bar_samples = sensorEvent.pressure;
+                isfirst_baro = 0;
+                if(u2Log_enable && (data_file_local != NULL)) {
+                    fprintf(data_file_local,"~%c%X\n",(bar_samples<0)?'-':' ',abs((int)(bar_samples*SENSOR_LOG_SCALE)));
+                }
+                break;
+            case (android::hardware::sensors::V1_0::SensorType)SENSOR_TYPE_GYRO_TEMPERATURE:
+                gyr_temperature = sensorEvent.data[0];
+                gyr_scp_calib_done = sensorEvent.data[1];
+                break;
+            default:
+                LOGD("unknown type(%d)", sensorEvent.type);
+        }
+        return android::hardware::Void();
+    }
+};
+
+void SensorDeathRecipient::serviceDied(uint64_t, const wp<::android::hidl::base::V1_0::IBase>&)
+{
+
+    Mutex::Autolock lock(sensorContext[SENSOR_USER_ID_MPE].mDataLock);
+    LOGD("Sensor service died. Cleanup sensor manager instance!");
+    sensorContext[SENSOR_USER_ID_MPE].mpListener = NULL;
+    sensorContext[SENSOR_USER_ID_MPE].queue = NULL;
+    sensorContext[SENSOR_USER_ID_MPE].mpDeathRecipient = NULL;
+}
+#endif
+unsigned char mpe_sensor_init(SENSOR_USER_ID id)
+{
+    if (id >= SENSOR_USER_ID_MAX) {
+        LOGD("mpe_sensor_init wrong id=%d", id);
+        return FALSE;
+    }
+#if defined(__ANDROID_OS__)
+    if (id == SENSOR_USER_ID_CALIB) {
+        ::prctl(PR_SET_NAME,"CalibThread", 0, 0, 0);
+    } else if (id == SENSOR_USER_ID_MPE) {
+        ::prctl(PR_SET_NAME,"MpeThread", 0, 0, 0);
+    }
+    sensorContext[id].mpListener = NULL;
+    sensorContext[id].queue = NULL;
+    sensorContext[id].mpDeathRecipient = NULL;
+#endif
+    return TRUE;
+}
+
+unsigned char mpe_sensor_deinit(SENSOR_USER_ID id)
+{
+    if (id >= SENSOR_USER_ID_MAX) {
+        LOGD("mpe_sensor_deinit wrong id=%d", id);
+        return FALSE;
+    }
+#if defined(__ANDROID_OS__)
+    sensorContext[id].mpListener = NULL;
+    sensorContext[id].queue = NULL;
+    sensorContext[id].mpDeathRecipient = NULL;
+#endif
+
+    if (id == SENSOR_USER_ID_MPE) {
+        mpe_log_deinit();
+        mpe_sensor_set_listen_mode(MPE_IDLE_MODE);
+        phone_time_reset = 0;
+        isfirst_baro = 1;
+        acc_cnt = 0;
+        gyr_cnt = 0;
+        gyr_log_cnt = 0;
+        prev_data_is_gyro = false;
+        gyr_temperature = 0;
+        gyr_scp_calib_done = 0;
+    }
+    return TRUE;
+}
+
+unsigned char mpe_sensor_start(SENSOR_USER_ID id, SENSOR_TYPE mpe_type, UINT32 periodInMs)
+{
+#if defined(__ANDROID_OS__)
+    android::hardware::sensors::V1_0::SensorType type;
+
+    LOGD("mpe_sensor_start id=%d type=%d periodMs=%u",id, mpe_type, periodInMs);
+    if (mpe_type == SENSOR_TYPE_ACC) {
+        type = SensorType::ACCELEROMETER;
+    } else if (mpe_type == SENSOR_TYPE_GYR) {
+        type = SensorType::GYROSCOPE;
+    } else if (mpe_type == SENSOR_TYPE_UNCAL_GYR) {
+        type = SensorType::GYROSCOPE_UNCALIBRATED;
+    } else if (mpe_type == SENSOR_TYPE_MAG) {
+        type = SensorType::MAGNETIC_FIELD;
+    } else if (mpe_type == SENSOR_TYPE_BAR) {
+        type = SensorType::PRESSURE;
+    } else if (mpe_type == SENSOR_TYPE_GYR_TMP) {
+        type = (android::hardware::sensors::V1_0::SensorType)SENSOR_TYPE_GYRO_TEMPERATURE;
+    } else {
+        LOGD("unknown type");
+        return FALSE;
+    }
+    Mutex::Autolock lock(sensorContext[id].mDataLock);
+    sensorContext[id].mSensorStatus[mpe_type] = SENSOR_ERR;
+    // sensor HIDL interface
+    sp<ISensorManager> manager = ISensorManager::getService();
+    if (manager == NULL) {
+        LOGD("getService() failed");
+        return FALSE;
+    }
+    if (sensorContext[id].mpDeathRecipient == NULL) {
+        sensorContext[id].mpDeathRecipient = new SensorDeathRecipient();
+        ::android::hardware::Return<bool> linked = manager->linkToDeath(sensorContext[id].mpDeathRecipient, /*cookie*/ 0);
+        if (!linked || !linked.isOk()) {
+            LOGE("Unable to link to sensor service death notifications");
+            return FALSE;
+        }
+    }
+    manager->getDefaultSensor(type,
+        [&](const auto &sensor, Result result) {
+            if (result == Result::OK) {
+                sensorContext[id].sensorHandle[mpe_type] = sensor.sensorHandle;
+            }
+        });
+    if (sensorContext[id].sensorHandle[mpe_type] == 0) {
+        LOGD("getDefaultSensor FAIL!");
+        return FALSE;
+    }
+    Result res;
+    if (sensorContext[id].mpListener == NULL) {
+        if (id == SENSOR_USER_ID_CALIB) {
+            sensorContext[id].mpListener = new CalibListenrCallback();
+        } else if (id == SENSOR_USER_ID_MPE) {
+            sensorContext[id].mpListener = new MpeListenrCallback();
+        }
+        manager->createEventQueue(sensorContext[id].mpListener,
+            [&] (const auto &q, Result result) {
+                if (result == Result::OK) {
+                    sensorContext[id].queue = q;
+                }
+            });
+        if (sensorContext[id].queue == NULL) {
+            LOGD("createEventQueue FAIL!");
+            return FALSE;
+        }
+    }
+    ::android::hardware::Return<Result> _ret =
+        sensorContext[id].queue->enableSensor(
+        sensorContext[id].sensorHandle[mpe_type], periodInMs*1000, 0);
+    if (!_ret.isOk()) {
+            LOGD("enableSensor FAIL!");
+            return FALSE;
+    }
+    sensorContext[id].mSensorStatus[mpe_type] = SENSOR_INIT;
+#endif
+
+    return TRUE;
+}
+
+unsigned char mpe_sensor_stop(SENSOR_USER_ID id, SENSOR_TYPE mpe_type)
+{
+#if defined(__ANDROID_OS__)
+    Mutex::Autolock lock(sensorContext[id].mDataLock);
+
+    LOGD("mpe_sensor_stop id=%d type=%d",id, mpe_type);
+
+    if (sensorContext[id].mSensorStatus[mpe_type] != SENSOR_INIT) {
+        LOGD("mpe_sensor_stop no need");
+        return FALSE;
+    }
+    if (sensorContext[id].queue == NULL) {
+        LOGD("mpe_sensor_stop bypass: serviceDied");
+        return FALSE;
+    }
+    ::android::hardware::Return<Result> _ret =
+        sensorContext[id].queue->disableSensor(sensorContext[id].sensorHandle[mpe_type]);
+    if (!_ret.isOk()) {
+        LOGD("disableSensor FAIL!");
+        return FALSE;
+    }
+    sensorContext[id].mSensorStatus[mpe_type] = SENSOR_UNINIT;
+    sensorContext[id].sensorHandle[mpe_type] = 0;
+#endif
+    return TRUE;
+}
+
+void mpe_sensor_get_calib_accuracy(INT8 *accuracy)
+{
+    memcpy(accuracy, calib_accuracy, sizeof(calib_accuracy));
+}
+
+unsigned char mpe_sensor_get_calib_gyr_data(void)
+{
+    return calib_get_gyro_data;
+}
+
+unsigned char mpe_sensor_check_mnl_response(void)
+{
+    double current_sys_time, delta_input_time;
+
+    mpe_sys_get_time_stamp(&current_sys_time, current_leap_sec);
+    delta_input_time = fabs(current_sys_time - mnl_inject_sys_time);
+
+    LOGD("mpe_sensor_check_mnl_response %lf, %lf %lf %d %d\n",delta_input_time, current_sys_time, mnl_inject_sys_time, phone_time_reset, mpe_sensor_get_listen_mode());
+
+    if (delta_input_time > 2.f || phone_time_reset)
+    {
+        mpe_sensor_set_listen_mode(MPE_IDLE_MODE);
+        LOGD("close SE, dt = %lf, %lf, ,%lf, %u\n",delta_input_time,current_sys_time, mnl_inject_sys_time, phone_time_reset);
+        return FALSE;
+    }
+    return TRUE;
+}
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h b/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h
new file mode 100644
index 0000000..ea048ef
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/inc/Mnld2NlpUtilsInterface.h
@@ -0,0 +1,43 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __Mnld2NlpUtilsInterface_H__
+#define __Mnld2NlpUtilsInterface_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE 302
+#define MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE 12
+
+/**
+ * The interface from Mnld to NlpUtils
+ */
+typedef enum {
+    MNLD2NLP_UTILS_INTERFACE_REQ_NLP_LOCATION = 0,
+    MNLD2NLP_UTILS_INTERFACE_CANCEL_NLP_LOCATION = 1,
+} Mnld2NlpUtilsInterface_message_id;
+
+
+
+// Sender
+bool Mnld2NlpUtilsInterface_reqNlpLocation(mtk_socket_fd* client_fd, int source);
+
+bool Mnld2NlpUtilsInterface_cancelNlpLocation(mtk_socket_fd* client_fd, int source);
+
+// Receiver
+typedef struct {
+    void (*Mnld2NlpUtilsInterface_reqNlpLocation_handler) (int source);
+    void (*Mnld2NlpUtilsInterface_cancelNlpLocation_handler) (int source);
+} Mnld2NlpUtilsInterface_callbacks;
+
+bool Mnld2NlpUtilsInterface_receiver_decode(char* _buff, Mnld2NlpUtilsInterface_callbacks* callbacks);
+bool Mnld2NlpUtilsInterface_receiver_read_and_decode(int server_fd, Mnld2NlpUtilsInterface_callbacks* callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c b/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c
new file mode 100644
index 0000000..1cadc1b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnl_nlp_interface/src/Mnld2NlpUtilsInterface.c
@@ -0,0 +1,112 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "Mnld2NlpUtilsInterface.h"
+#include "mtk_socket_data_coder.h"
+
+// Sender
+bool Mnld2NlpUtilsInterface_reqNlpLocation(mtk_socket_fd* client_fd, int source) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Mnld2NlpUtilsInterface_reqNlpLocation() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_REQ_NLP_LOCATION);
+    mtk_socket_put_int(_buff, &_offset, source);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Mnld2NlpUtilsInterface_reqNlpLocation() mtk_socket_write() failed, fd=%p err=[%s]%d",
+            client_fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+bool Mnld2NlpUtilsInterface_cancelNlpLocation(mtk_socket_fd* client_fd, int source) {
+    pthread_mutex_lock(&client_fd->mutex);
+    if(!mtk_socket_client_connect(client_fd)) {
+        LOGE("Mnld2NlpUtilsInterface_cancelNlpLocation() mtk_socket_client_connect() failed");
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    int _ret;
+    char _buff[MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE] = {0};
+    int _offset = 0;
+    mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE);
+    mtk_socket_put_int(_buff, &_offset, MNLD2NLP_UTILS_INTERFACE_CANCEL_NLP_LOCATION);
+    mtk_socket_put_int(_buff, &_offset, source);
+    _ret = mtk_socket_write(client_fd->fd, _buff, _offset);
+    if(_ret == -1) {
+        LOGE("Mnld2NlpUtilsInterface_cancelNlpLocation() mtk_socket_write() failed, fd=%p err=[%s]%d",
+            client_fd, strerror(errno), errno);
+        mtk_socket_client_close(client_fd);
+        pthread_mutex_unlock(&client_fd->mutex);
+        return false;
+    }
+    mtk_socket_client_close(client_fd);
+    pthread_mutex_unlock(&client_fd->mutex);
+    return true;
+}
+
+// Receiver
+bool Mnld2NlpUtilsInterface_receiver_decode(char* _buff, Mnld2NlpUtilsInterface_callbacks* callbacks) {
+    int _ret = 0;
+    int _offset = 0;
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    if(_ret != MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE) {
+        LOGE("Mnld2NlpUtilsInterface_receiver_decode() protocol_type=[%d] is not equals to [%d]",
+            _ret, MNLD2NLP_UTILS_INTERFACE_PROTOCOL_TYPE);
+        return false;
+    }
+    _ret = mtk_socket_get_int(_buff, &_offset);
+    switch(_ret) {
+    case MNLD2NLP_UTILS_INTERFACE_REQ_NLP_LOCATION: {
+        if(callbacks->Mnld2NlpUtilsInterface_reqNlpLocation_handler == NULL) {
+            LOGE("Mnld2NlpUtilsInterface_receiver_decode() Mnld2NlpUtilsInterface_reqNlpLocation_handler() is NULL");
+            return false;
+        }
+        int source = mtk_socket_get_int(_buff, &_offset);
+        callbacks->Mnld2NlpUtilsInterface_reqNlpLocation_handler(source);
+        break;
+    }
+    case MNLD2NLP_UTILS_INTERFACE_CANCEL_NLP_LOCATION: {
+        if(callbacks->Mnld2NlpUtilsInterface_cancelNlpLocation_handler == NULL) {
+            LOGE("Mnld2NlpUtilsInterface_receiver_decode() Mnld2NlpUtilsInterface_cancelNlpLocation_handler() is NULL");
+            return false;
+        }
+        int source = mtk_socket_get_int(_buff, &_offset);
+        callbacks->Mnld2NlpUtilsInterface_cancelNlpLocation_handler(source);
+        break;
+    }
+    default: {
+        LOGE("Mnld2NlpUtilsInterface_receiver_decode() unknown msgId=[%d]", _ret);
+        return false;
+    }
+    }
+    return true;
+}
+bool Mnld2NlpUtilsInterface_receiver_read_and_decode(int server_fd, Mnld2NlpUtilsInterface_callbacks* callbacks) {
+    int _ret;
+    char _buff[MNLD2NLP_UTILS_INTERFACE_BUFF_SIZE] = {0};
+
+    _ret = mtk_socket_read(server_fd, _buff, sizeof(_buff));
+    if(_ret == -1) {
+        LOGE("Mnld2NlpUtilsInterface_receiver_read_and_decode() mtk_socket_read() failed, fd=%d err=[%s]%d",
+            server_fd, strerror(errno), errno);
+        return false;
+    }
+    return Mnld2NlpUtilsInterface_receiver_decode(_buff, callbacks);
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld.service b/src/connectivity/gps/mtk_mnld/mnld.service
new file mode 100644
index 0000000..c2a69bf
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=MNL Daemon
+
+[Service]
+ExecStart=/usr/bin/mnld0
+Restart=always
+#StandardOutput=kmsg+console
+
+[Install]
+WantedBy=basic.target
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps.h b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps.h
new file mode 100644
index 0000000..11804f3
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps.h
@@ -0,0 +1,2234 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_H
+
+#ifdef __LINUX_OS__
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+/*
+ * Enums defined in HIDL in hardware/interfaces are auto-generated and present
+ * in gnss-base.h.
+ */
+
+/* for compatibility */
+
+/*#define GPS_REQUEST_AGPS_DATA_CONN GNSS_REQUEST_AGNSS_DATA_CONN
+#define GPS_RELEASE_AGPS_DATA_CONN GNSS_RELEASE_AGNSS_DATA_CONN
+#define GPS_AGPS_DATA_CONNECTED GNSS_AGNSS_DATA_CONNECTED
+#define GPS_AGPS_DATA_CONN_DONE GNSS_AGNSS_DATA_CONN_DONE
+#define GPS_AGPS_DATA_CONN_FAILED GNSS_AGNSS_DATA_CONN_FAILED
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS AGPS_RIL_NETWORK_TYPE_MMS
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL AGPS_RIL_NETWORK_TYPE_SUPL
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN AGPS_RIL_NETWORK_TYPE_DUN
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI AGPS_RIL_NETWORK_TYPE_HIPRI
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX AGPS_RIL_NETWORK_TYPE_WIMAX
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT GNSS_MULTIPATH_INDICATIOR_NOT_PRESENT
+#define AGPS_SETID_TYPE_MSISDN AGPS_SETID_TYPE_MSISDM
+#define GPS_MEASUREMENT_OPERATION_SUCCESS GPS_MEASUREMENT_SUCCESS
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS GPS_NAVIGATION_MESSAGE_SUCCESS
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L2CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L5CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_CNAV2
+#define GPS_LOCATION_HAS_ACCURACY GPS_LOCATION_HAS_HORIZONTAL_ACCURACY
+*/
+/**
+ * The id of this module
+ */
+#define GPS_HARDWARE_MODULE_ID "gps"
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS             0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT         -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC              -101
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GpsUtcTime;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in gps_measurement_callback(). */
+#define GPS_MAX_MEASUREMENT   32
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT   64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t GpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define GPS_POSITION_MODE_STANDALONE    0
+/** AGPS MS-Based mode. */
+#define GPS_POSITION_MODE_MS_BASED      1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define GPS_POSITION_MODE_MS_ASSISTED   2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t GpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define GPS_POSITION_RECURRENCE_PERIODIC    0
+/** Request a single shot GPS fix. */
+#define GPS_POSITION_RECURRENCE_SINGLE      1
+
+/** GPS status event values. */
+typedef uint16_t GpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define GPS_STATUS_NONE             0
+/** GPS has begun navigating. */
+#define GPS_STATUS_SESSION_BEGIN    1
+/** GPS has stopped navigating. */
+#define GPS_STATUS_SESSION_END      2
+/** GPS has powered on but is not navigating. */
+#define GPS_STATUS_ENGINE_ON        3
+/** GPS is powered off. */
+#define GPS_STATUS_ENGINE_OFF       4
+
+/** Flags to indicate which values are valid in a GpsLocation. */
+typedef uint16_t GpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GpsLocation has valid latitude and longitude. */
+#define GPS_LOCATION_HAS_LAT_LONG   0x0001
+/** GpsLocation has valid altitude. */
+#define GPS_LOCATION_HAS_ALTITUDE   0x0002
+/** GpsLocation has valid speed. */
+#define GPS_LOCATION_HAS_SPEED      0x0004
+/** GpsLocation has valid bearing. */
+#define GPS_LOCATION_HAS_BEARING    0x0008
+/** GpsLocation has valid accuracy. */
+#define GPS_LOCATION_HAS_ACCURACY   0x0010
+
+/**
+ * GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define GPS_CAPABILITY_SCHEDULING       (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define GPS_CAPABILITY_MSB              (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define GPS_CAPABILITY_MSA              (1 << 2)
+/** GPS supports single-shot fixes */
+#define GPS_CAPABILITY_SINGLE_SHOT      (1 << 3)
+/** GPS supports on demand time injection */
+#define GPS_CAPABILITY_ON_DEMAND_TIME   (1 << 4)
+/** GPS supports Geofencing  */
+#define GPS_CAPABILITY_GEOFENCING       (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS     (1 << 6)
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES     (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t GpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#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
+
+/** AGPS type */
+typedef uint16_t AGpsType;
+#define AGPS_TYPE_SUPL          1
+#define AGPS_TYPE_C2K           2
+
+typedef uint16_t AGpsSetIDType;
+#define AGPS_SETID_TYPE_NONE    0
+#define AGPS_SETID_TYPE_IMSI    1
+#define AGPS_SETID_TYPE_MSISDN  2
+
+typedef uint16_t ApnIpType;
+#define APN_IP_INVALID          0
+#define APN_IP_IPV4             1
+#define APN_IP_IPV6             2
+#define APN_IP_IPV4V6           3
+
+/**
+ * String length constants
+ */
+#define GPS_NI_SHORT_STRING_MAXLEN      256
+#define GPS_NI_LONG_STRING_MAXLEN       2048
+
+/**
+ * GpsNiType constants
+ */
+typedef uint32_t GpsNiType;
+#define GPS_NI_TYPE_VOICE              1
+#define GPS_NI_TYPE_UMTS_SUPL          2
+#define GPS_NI_TYPE_UMTS_CTRL_PLANE    3
+
+/**
+ * GpsNiNotifyFlags constants
+ */
+typedef uint32_t GpsNiNotifyFlags;
+/** NI requires notification */
+#define GPS_NI_NEED_NOTIFY          0x0001
+/** NI requires verification */
+#define GPS_NI_NEED_VERIFY          0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define GPS_NI_PRIVACY_OVERRIDE     0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int GpsUserResponseType;
+#define GPS_NI_RESPONSE_ACCEPT         1
+#define GPS_NI_RESPONSE_DENY           2
+#define GPS_NI_RESPONSE_NORESP         3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int GpsNiEncodingType;
+#define GPS_ENC_NONE                   0
+#define GPS_ENC_SUPL_GSM_DEFAULT       1
+#define GPS_ENC_SUPL_UTF8              2
+#define GPS_ENC_SUPL_UCS2              3
+#define GPS_ENC_UNKNOWN                -1
+
+/** AGPS status event values. */
+typedef uint16_t AGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define GPS_REQUEST_AGPS_DATA_CONN  1
+/** GPS releases the AGPS data connection. */
+#define GPS_RELEASE_AGPS_DATA_CONN  2
+/** AGPS data connection initiated */
+#define GPS_AGPS_DATA_CONNECTED     3
+/** AGPS data connection completed */
+#define GPS_AGPS_DATA_CONN_DONE     4
+/** AGPS data connection failed */
+#define GPS_AGPS_DATA_CONN_FAILED   5
+
+typedef uint16_t AGpsRefLocationType;
+#define AGPS_REF_LOCATION_TYPE_GSM_CELLID   1
+#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID  2
+#define AGPS_REF_LOCATION_TYPE_MAC          3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID   4
+
+/* Deprecated, to be removed in the next Android release. */
+#define AGPS_REG_LOCATION_TYPE_MAC          3
+
+/** Network types for update_network_state "type" parameter */
+#define AGPS_RIL_NETWORK_TYPE_MOBILE        0
+#define AGPS_RIL_NETWORK_TYPE_WIFI          1
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS    2
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL   3
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN   4
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX        6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsClockFlags;
+#define GPS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+#define GPS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+#define GPS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+#define GPS_CLOCK_HAS_BIAS                      (1<<3)
+#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+#define GPS_CLOCK_HAS_DRIFT                     (1<<5)
+#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/**
+ * Flags to indicate what fields in GnssClock are valid.
+ */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsClockType;
+#define GPS_CLOCK_TYPE_UNKNOWN                  0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME            1
+#define GPS_CLOCK_TYPE_GPS_TIME                 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t GpsMeasurementFlags;
+#define GPS_MEASUREMENT_HAS_SNR                               (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION                         (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY             (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH                           (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY               (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE                       (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY           (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE                        (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY            (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER                        (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT                (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                     (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY         (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX                       (1<<17)
+#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE      (1<<18)
+
+/**
+ * Flags to indicate what fields in GnssMeasurement are valid.
+ */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsLossOfLock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN                            0
+#define GPS_LOSS_OF_LOCK_OK                                 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP                         2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
+ */
+typedef uint8_t GpsMultipathIndicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN                 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED                1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED                2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsMeasurementState;
+#define GPS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ *         GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsAccumulatedDeltaRangeState;
+#define GPS_ADR_STATE_UNKNOWN                       0
+#define GPS_ADR_STATE_VALID                     (1<<0)
+#define GPS_ADR_STATE_RESET                     (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN                       0
+#define GNSS_ADR_STATE_VALID                     (1<<0)
+#define GNSS_ADR_STATE_RESET                     (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN         0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA            1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV          2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV          3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2           4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN              0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW              0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t                                 GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE                      0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA        (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA          (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX               (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t                         GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN      0
+#define GNSS_CONSTELLATION_GPS          1
+#define GNSS_CONSTELLATION_SBAS         2
+#define GNSS_CONSTELLATION_GLONASS      3
+#define GNSS_CONSTELLATION_QZSS         4
+#define GNSS_CONSTELLATION_BEIDOU       5
+#define GNSS_CONSTELLATION_GALILEO      6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define GPS_XTRA_INTERFACE      "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define GPS_DEBUG_INTERFACE      "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+#define AGPS_INTERFACE      "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define SUPL_CERTIFICATE_INTERFACE  "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define AGPS_RIL_INTERFACE      "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define GPS_GEOFENCING_INTERFACE   "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define GPS_MEASUREMENT_INTERFACE   "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define GPS_NAVIGATION_MESSAGE_INTERFACE     "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define GNSS_CONFIGURATION_INTERFACE     "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(GpsLocation) */
+    size_t          size;
+    /** Contains GpsLocationFlags bits. */
+    uint16_t        flags;
+    /** Represents latitude in degrees. */
+    double          latitude;
+    /** Represents longitude in degrees. */
+    double          longitude;
+    /**
+     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     */
+    double          altitude;
+    /** Represents speed in meters per second. */
+    float           speed;
+    /** Represents heading in degrees. */
+    float           bearing;
+    /** Represents expected accuracy in meters. */
+    float           accuracy;
+    /** Timestamp for the location fix. */
+    GpsUtcTime      timestamp;
+} GpsLocation;
+
+/** Represents the status. */
+typedef struct {
+    /** set to sizeof(GpsStatus) */
+    size_t          size;
+    GpsStatusValue status;
+} GpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvInfo) */
+    size_t          size;
+    /** Pseudo-random number for the SV. */
+    int     prn;
+    /** Signal to noise ratio. */
+    float   snr;
+    /** Elevation of SV in degrees. */
+    float   elevation;
+    /** Azimuth of SV in degrees. */
+    float   azimuth;
+} GpsSvInfo;
+
+typedef struct {
+    /** set to sizeof(GnssSvInfo) */
+    size_t size;
+
+    /**
+     * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+     * distinction is made by looking at constellation field. Values should be
+     * in the range of:
+     *
+     * - GPS:     1-32
+     * - SBAS:    120-151, 183-192
+     * - GLONASS: 1-24, the orbital slot number (OSN), if known.  Or, if not:
+     *            93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+     *            i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+     * - QZSS:    193-200
+     * - Galileo: 1-36
+     * - Beidou:  1-37
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    float c_n0_dbhz;
+
+    /** Elevation of SV in degrees. */
+    float elevation;
+
+    /** Azimuth of SV in degrees. */
+    float azimuth;
+
+    /**
+     * Contains additional data about the given SV. Value should be one of those
+     * GNSS_SV_FLAGS_* constants
+     */
+    GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvStatus) */
+    size_t size;
+    int num_svs;
+    GpsSvInfo sv_list[GPS_MAX_SVS];
+    uint32_t ephemeris_mask;
+    uint32_t almanac_mask;
+    uint32_t used_in_fix_mask;
+} GpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+    AGpsRefLocationType type;
+    /** Mobile Country Code. */
+    uint16_t mcc;
+    /** Mobile Network Code .*/
+    uint16_t mnc;
+    /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+     * lac is populated with tac, to ensure that we don't break old clients that
+     * might rely in the old (wrong) behavior.
+     */
+    uint16_t lac;
+    /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+    uint32_t cid;
+    /** Tracking Area Code in LTE. */
+    uint16_t tac;
+    /** Physical Cell id in LTE (not used in 2G and 3G) */
+    uint16_t pcid;
+} AGpsRefLocationCellID;
+
+typedef struct {
+    uint8_t mac[6];
+} AGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+    AGpsRefLocationType type;
+    union {
+        AGpsRefLocationCellID   cellID;
+        AGpsRefLocationMac      mac;
+    } u;
+} AGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_callback)(GpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* gps_status_callback)(GpsStatus* status);
+
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
+ */
+typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of GPS_CAPABILITY_* flags.
+ */
+typedef void (* gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+    /** Set to sizeof(GnssSystemInfo) */
+    size_t   size;
+    /* year in which the last update was made to the underlying hardware/firmware
+     * used to capture GNSS signals, e.g. 2016 */
+    uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int   (*init)( GpsCallbacks* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+} GpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+    gps_xtra_download_request download_request_cb;
+    gps_create_thread create_thread_cb;
+} GpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+    /** set to sizeof(GpsXtraInterface) */
+    size_t          size;
+    /**
+     * Opens the XTRA interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int  (*init)( GpsXtraCallbacks* callbacks );
+    /** Injects XTRA data into the GPS. */
+    int  (*inject_xtra_data)( char* data, int length );
+} GpsXtraInterface;
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} GpsDebugInterface;
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus) */
+    size_t                  size;
+
+    AGpsType                type;
+    AGpsStatusValue         status;
+
+    /**
+     * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+     * address, or set to INADDR_NONE otherwise.
+     */
+    uint32_t                ipaddr;
+
+    /**
+     * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+     * Any other value of addr.ss_family will be rejected.
+     */
+    struct sockaddr_storage addr;
+} AGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* agps_status_callback)(AGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+    agps_status_callback status_cb;
+    gps_create_thread create_thread_cb;
+} AGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface) */
+    size_t size;
+
+    /**
+     * Opens the AGPS interface and provides the callback routines to the
+     * implementation of this interface.
+     */
+    void (*init)(AGpsCallbacks* callbacks);
+    /**
+     * Deprecated.
+     * If the HAL supports AGpsInterface_v2 this API will not be used, see
+     * data_conn_open_with_apn_ip_type for more information.
+     */
+    int (*data_conn_open)(const char* apn);
+    /**
+     * Notifies that the AGPS data connection has been closed.
+     */
+    int (*data_conn_closed)();
+    /**
+     * Notifies that a data connection is not available for AGPS.
+     */
+    int (*data_conn_failed)();
+    /**
+     * Sets the hostname and port for the AGPS server.
+     */
+    int (*set_server)(AGpsType type, const char* hostname, int port);
+
+    /**
+     * Notifies that a data connection is available and sets the name of the
+     * APN, and its IP type, to be used for SUPL connections.
+     */
+    int (*data_conn_open_with_apn_ip_type)(
+            const char* apn,
+            ApnIpType apnIpType);
+} AGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define AGPS_CERTIFICATE_OPERATION_SUCCESS               0
+#define AGPS_CERTIFICATE_ERROR_GENERIC                -100
+#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES  -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+    size_t  length;
+    u_char* data;
+} DerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+    u_char data[20];
+} Sha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+    /** set to sizeof(SuplCertificateInterface) */
+    size_t size;
+
+    /**
+     * Installs a set of Certificates used for SUPL connections to the AGPS server.
+     * If needed the HAL should find out internally any certificates that need to be removed to
+     * accommodate the certificates to install.
+     * The certificates installed represent a full set of valid certificates needed to connect to
+     * AGPS SUPL servers.
+     * The list of certificates is required, and all must be available at the same time, when trying
+     * to establish a connection with the AGPS Server.
+     *
+     * Parameters:
+     *      certificates - A pointer to an array of DER encoded certificates that are need to be
+     *                     installed in the HAL.
+     *      length - The number of certificates to install.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+     *      AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+     *          certificates attempted to be installed, the state of the certificates stored should
+     *          remain the same as before on this error case.
+     *
+     * IMPORTANT:
+     *      If needed the HAL should find out internally the set of certificates that need to be
+     *      removed to accommodate the certificates to install.
+     */
+    int  (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length );
+
+    /**
+     * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+     * expected that the given set of certificates is removed from the internal store of the HAL.
+     *
+     * Parameters:
+     *      fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+     *                     certificates to revoke.
+     *      length - The number of fingerprints provided.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+     *
+     * IMPORTANT:
+     *      If any of the certificates provided (through its fingerprint) is not known by the HAL,
+     *      it should be ignored and continue revoking/deleting the rest of them.
+     */
+    int  (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length );
+} SuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+    /** set to sizeof(GpsNiNotification) */
+    size_t          size;
+
+    /**
+     * An ID generated by HAL to associate NI notifications and UI
+     * responses
+     */
+    int             notification_id;
+
+    /**
+     * An NI type used to distinguish different categories of NI
+     * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ...
+     */
+    GpsNiType       ni_type;
+
+    /**
+     * Notification/verification options, combinations of GpsNiNotifyFlags constants
+     */
+    GpsNiNotifyFlags notify_flags;
+
+    /**
+     * Timeout period to wait for user response.
+     * Set to 0 for no time out limit.
+     */
+    int             timeout;
+
+    /**
+     * Default response when time out.
+     */
+    GpsUserResponseType default_response;
+
+    /**
+     * Requestor ID
+     */
+    char            requestor_id[GPS_NI_SHORT_STRING_MAXLEN];
+
+    /**
+     * Notification message. It can also be used to store client_id in some cases
+     */
+    char            text[GPS_NI_LONG_STRING_MAXLEN];
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType requestor_id_encoding;
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType text_encoding;
+
+    /**
+     * A pointer to extra data. Format:
+     * key_1 = value_1
+     * key_2 = value_2
+     */
+    char           extras[GPS_NI_LONG_STRING_MAXLEN];
+
+} GpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+    /**
+     * Sends the notification request from HAL to GPSLocationProvider.
+     */
+    gps_ni_notify_callback notify_cb;
+    gps_create_thread create_thread_cb;
+} GpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+    /** set to sizeof(GpsNiInterface) */
+    size_t          size;
+
+   /** Registers the callbacks for HAL to use. */
+   void (*init) (GpsNiCallbacks *callbacks);
+
+   /** Sends a response to HAL. */
+   void (*respond) (int notif_id, GpsUserResponseType user_response);
+} GpsNiInterface;
+
+#if defined(__ANDROID_OS__)
+struct gps_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct gps_device_t {
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#endif
+
+#define AGPS_RIL_REQUEST_REFLOC_CELLID  (1<<0L)
+#define AGPS_RIL_REQUEST_REFLOC_MAC     (1<<1L)
+
+typedef void (*agps_ril_request_set_id)(uint32_t flags);
+typedef void (*agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+    agps_ril_request_set_id request_setid;
+    agps_ril_request_ref_loc request_refloc;
+    gps_create_thread create_thread_cb;
+} AGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+    /** set to sizeof(AGpsRilInterface) */
+    size_t          size;
+    /**
+     * Opens the AGPS interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    void  (*init)( AGpsRilCallbacks* callbacks );
+
+    /**
+     * Sets the reference location.
+     */
+    void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+    /**
+     * Sets the set ID.
+     */
+    void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+    /**
+     * Send network initiated message.
+     */
+    void (*ni_message) (uint8_t *msg, size_t len);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ *      There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ *     In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define GPS_GEOFENCE_ENTERED     (1<<0L)
+#define GPS_GEOFENCE_EXITED      (1<<1L)
+#define GPS_GEOFENCE_UNCERTAIN   (1<<2L)
+
+#define GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define GPS_GEOFENCE_AVAILABLE   (1<<1L)
+
+#define GPS_GEOFENCE_OPERATION_SUCCESS           0
+#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define GPS_GEOFENCE_ERROR_ID_EXISTS          -101
+#define GPS_GEOFENCE_ERROR_ID_UNKNOWN         -102
+#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define GPS_GEOFENCE_ERROR_GENERIC            -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_callback) (int32_t geofence_id,  GpsLocation* location,
+        int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          GPS_GEOFENCE_ERROR_ID_EXISTS  - geofence with id already exists
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+    gps_geofence_transition_callback geofence_transition_callback;
+    gps_geofence_status_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsClock) */
+    size_t size;
+    GpsClockFlags flags;
+    int16_t leap_second;
+    GpsClockType type;
+    int64_t time_ns;
+    double time_uncertainty_ns;
+    int64_t full_bias_ns;
+    double bias_ns;
+    double bias_uncertainty_ns;
+    double drift_nsps;
+    double drift_uncertainty_nsps;
+} GpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+    /** set to sizeof(GnssClock) */
+    size_t size;
+
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    GnssClockFlags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+     *      1,000,000,000
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+     */
+    int16_t leap_second;
+
+    /**
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
+     *
+     * For local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * available) from this value.
+     *
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+     * The value contains the 'time uncertainty' in it.
+     *
+     * This field is mandatory.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * The sign of the value is defined by the following equation:
+     *      local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+     *
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * bias) in nanoseconds. The uncertainty is represented as an absolute
+     * (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+     *
+     * This value is mandatory if the receiver has estimated GNSS time
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
+     */
+    double drift_uncertainty_nsps;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+    GpsMeasurementFlags flags;
+    int8_t prn;
+    double time_offset_ns;
+    GpsMeasurementState state;
+    int64_t received_gps_tow_ns;
+    int64_t received_gps_tow_uncertainty_ns;
+    double c_n0_dbhz;
+    double pseudorange_rate_mps;
+    double pseudorange_rate_uncertainty_mps;
+    GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+    double accumulated_delta_range_m;
+    double accumulated_delta_range_uncertainty_m;
+    double pseudorange_m;
+    double pseudorange_uncertainty_m;
+    double code_phase_chips;
+    double code_phase_uncertainty_chips;
+    float carrier_frequency_hz;
+    int64_t carrier_cycles;
+    double carrier_phase;
+    double carrier_phase_uncertainty;
+    GpsLossOfLock loss_of_lock;
+    int32_t bit_number;
+    int16_t time_from_last_bit_ms;
+    double doppler_shift_hz;
+    double doppler_shift_uncertainty_hz;
+    GpsMultipathIndicator multipath_indicator;
+    double snr_db;
+    double elevation_deg;
+    double elevation_uncertainty_deg;
+    double azimuth_deg;
+    double azimuth_uncertainty_deg;
+    bool used_in_fix;
+} GpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    GnssMeasurementFlags flags;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     *
+     * This is a mandatory value.
+     */
+    GnssMeasurementState state;
+
+    /**
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
+     *
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     *
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_sv_time_uncertainty_in_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s. The correction of a given
+     * Pseudorange Rate value includes corrections for receiver and satellite
+     * clock frequency errors. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
+     *
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+     * shift' is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     *
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This is a mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     *
+     * This is a mandatory value.
+     */
+    GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     *
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
+     *
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
+     */
+    GnssMultipathIndicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
+     */
+    double snr_db;
+} GnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsData) */
+    size_t size;
+    size_t measurement_count;
+    GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GpsClock clock;
+} GpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gps_measurement_callback) (GpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks;
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsMeasurementCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface;
+
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsNavigationMessage) */
+    size_t size;
+    int8_t prn;
+    GpsNavigationMessageType type;
+    NavigationMessageStatus status;
+    int16_t message_id;
+    int16_t submessage_id;
+    size_t data_length;
+    uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+    /** set to sizeof(GnssNavigationMessage) */
+    size_t size;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a mandatory value.
+     */
+    GnssNavigationMessageType type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    NavigationMessageStatus status;
+
+    /**
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
+     */
+    int16_t message_id;
+
+    /**
+     * Sub-message identifier. If required by the message 'type', this value
+     * contains a sub-index within the current message (or frame) that is being
+     * transmitted.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+     */
+    int16_t submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     *
+     * This is a mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+     *
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
+     */
+    uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+    /** set to sizeof(GpsNavigationMessageCallbacks) */
+    size_t size;
+    gps_navigation_message_callback navigation_message_callback;
+    gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsNavigationMessageInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates as they become
+     * available.
+     *
+     * Status:
+     *      GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+     *      GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+     *              without a corresponding call to 'close'.
+     *      GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+     *              the HAL will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsNavigationMessageInterface;
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+} GnssConfigurationInterface;
+
+__END_DECLS
+
+#endif
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_internal.h b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_internal.h
new file mode 100644
index 0000000..67a16e8
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_internal.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H
+
+#ifdef __LINUX_OS__
+//#include <hardware/gps.h>
+#include "gps.h"
+
+/****************************************************************************
+ * This file contains legacy structs that are deprecated/retired from gps.h *
+ ****************************************************************************/
+
+__BEGIN_DECLS
+
+/**
+ * Legacy GPS callback structure.
+ * Deprecated, to be removed in the next Android release.
+ * Use GpsCallbacks instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsCallbacks_v1) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+} GpsCallbacks_v1;
+
+#pragma pack(push,4)
+// We need to keep the alignment of this data structure to 4-bytes, to ensure that in 64-bit
+// environments the size of this legacy definition does not collide with _v2. Implementations should
+// be using _v2 and _v3, so it's OK to pay the 'unaligned' penalty in 64-bit if an old
+// implementation is still in use.
+
+/**
+ * Legacy struct to represent the status of AGPS.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v1) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+} AGpsStatus_v1;
+
+#pragma pack(pop)
+
+/**
+ * Legacy struct to represent the status of AGPS augmented with a IPv4 address
+ * field.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus_v2) */
+    size_t          size;
+    AGpsType        type;
+    AGpsStatusValue status;
+
+    /*-------------------- New fields in _v2 --------------------*/
+
+    uint32_t        ipaddr;
+} AGpsStatus_v2;
+
+/**
+ * Legacy extended interface for AGPS support.
+ * See AGpsInterface_v2 for more information.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface_v1) */
+    size_t          size;
+    void  (*init)( AGpsCallbacks* callbacks );
+    int  (*data_conn_open)( const char* apn );
+    int  (*data_conn_closed)();
+    int  (*data_conn_failed)();
+    int  (*set_server)( AGpsType type, const char* hostname, int port );
+} AGpsInterface_v1;
+
+__END_DECLS
+
+#endif
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_INTERNAL_H */
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_mtk.h b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_mtk.h
new file mode 100644
index 0000000..df13674
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/hardware/gps_mtk.h
@@ -0,0 +1,698 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+
+#if defined (__ANDROID_OS__)
+#include <hardware/gps_internal.h>
+#elif defined (__LINUX_OS__)
+#include "gps_internal.h"
+#endif
+
+__BEGIN_DECLS
+
+// MTK extended GpsAidingData values.
+#define GPS_DELETE_HOT_STILL 0x2000
+#define GPS_DELETE_EPO      0x4000
+
+// ====================vzw debug screen API =================
+/**
+ * Name for the VZW debug interface.
+ */
+#define VZW_DEBUG_INTERFACE      "vzw-debug"
+
+#define VZW_DEBUG_STRING_MAXLEN      200
+
+/** Represents data of VzwDebugData. */
+typedef struct {
+    /** set to sizeof(VzwDebugData) */
+    size_t size;
+
+    char  vzw_msg_data[VZW_DEBUG_STRING_MAXLEN];
+} VzwDebugData;
+
+
+typedef void (* vzw_debug_callback)(VzwDebugData* vzw_message);
+
+/** Callback structure for the Vzw debug interface. */
+typedef struct {
+    vzw_debug_callback vzw_debug_cb;
+} VzwDebugCallbacks;
+
+
+/** Extended interface for VZW DEBUG support. */
+typedef struct {
+    /** set to sizeof(VzwDebugInterface) */
+    size_t          size;
+
+    /** Registers the callbacks for Vzw debug message. */
+    int  (*init)( VzwDebugCallbacks* callbacks );
+
+    /** Set Vzw debug screen enable/disable **/
+    void (*set_vzw_debug_screen)(bool enabled);
+} VzwDebugInterface;
+
+////////////////////// GNSS HIDL v1.0 ////////////////////////////
+
+/** Represents a location. */
+typedef struct {
+    GpsLocation legacyLocation;
+    /**
+    * Represents expected horizontal position accuracy, radial, in meters
+    * (68% confidence).
+    */
+    float           horizontalAccuracyMeters;
+
+    /**
+    * Represents expected vertical position accuracy in meters
+    * (68% confidence).
+    */
+    float           verticalAccuracyMeters;
+
+    /**
+    * Represents expected speed accuracy in meter per seconds
+    * (68% confidence).
+    */
+    float           speedAccuracyMetersPerSecond;
+
+    /**
+    * Represents expected bearing accuracy in degrees
+    * (68% confidence).
+    */
+    float           bearingAccuracyDegrees;
+
+} GpsLocation_ext;
+
+
+typedef struct {
+    GnssSvInfo legacySvInfo;
+
+    /// v1.0 ///
+    float carrier_frequency;
+
+} GnssSvInfo_ext;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo_ext gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus_ext;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_ext_callback)(GpsLocation_ext* location);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_ext_callback)(GnssSvStatus_ext* sv_info);
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_ext_callback) (int32_t geofence_id,
+        GpsLocation_ext* location, int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_ext_callback) (int32_t status,
+        GpsLocation_ext* last_location);
+
+typedef struct {
+    gps_geofence_transition_ext_callback geofence_transition_callback;
+    gps_geofence_status_ext_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks_ext;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks_ext* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface_ext;
+
+typedef struct {
+    GnssMeasurement legacyMeasurement;
+
+    /**
+     * Automatic gain control (AGC) level. AGC acts as a variable gain
+     * amplifier adjusting the power of the incoming signal. The AGC level
+     * may be used to indicate potential interference. When AGC is at a
+     * nominal level, this value must be set as 0. Higher gain (and/or lower
+     * input power) must be output as a positive number. Hence in cases of
+     * strong jamming, in the band of this signal, this value must go more
+     * negative.
+     *
+     * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+     * other RF HW components) may also affect the typical output of of this
+     * value on any given hardware design in an open sky test - the
+     * important aspect of this output is that changes in this value are
+     * indicative of changes on input signal power in the frequency band for
+     * this measurement.
+     */
+    double agc_level_db;
+} GnssMeasurement_ext;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement_ext measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData_ext;
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_ext_callback) (GnssData_ext* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_ext_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks_ext;
+
+
+/////// Gnss debug ////
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+typedef enum {
+    /** Ephemeris is known for this satellite. */
+    EPHEMERIS,
+    /**
+     * Ephemeris is not known, but Almanac (approximate location) is known.
+     */
+    ALMANAC_ONLY,
+    /**
+     * Both ephemeris & almanac are not known (e.g. during a cold start
+     * blind search.)
+     */
+    NOT_AVAILABLE
+} SatelliteEphemerisType;
+
+typedef enum {
+    /**
+     * The ephemeris (or almanac only) information was demodulated from the
+     * signal received on the device
+     */
+    DEMODULATED,
+    /**
+     * The ephemeris (or almanac only) information was received from a SUPL
+     * server.
+     */
+    SUPL_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * server.
+     */
+    OTHER_SERVER_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * method, e.g. injected via a local debug tool, from build defaults
+     * (e.g. almanac), or is from a satellite
+     * with SatelliteEphemerisType::NOT_AVAILABLE.
+     */
+    OTHER
+} SatelliteEphemerisSource;
+
+typedef enum {
+    /** The ephemeris is known good. */
+    GOOD,
+    /** The ephemeris is known bad. */
+    BAD,
+    /** The ephemeris is unknown to be good or bad. */
+    UNKNOWN
+} SatelliteEphemerisHealth;
+
+/**
+ * Provides the current best known position from any
+ * source (GNSS or injected assistance).
+ */
+typedef struct {
+    /**
+     * Validity of the data in this struct. False only if no
+     * latitude/longitude information is known.
+     */
+    bool valid;
+    /** Latitude expressed in degrees */
+    double latitudeDegrees;
+    /** Longitude expressed in degrees */
+    double longitudeDegrees;
+    /** Altitude above ellipsoid expressed in meters */
+    float altitudeMeters;
+    /** Represents horizontal speed in meters per second. */
+    float speedMetersPerSec;
+    /** Represents heading in degrees. */
+    float bearingDegrees;
+    /**
+     * Estimated horizontal accuracy of position expressed in meters,
+     * radial, 68% confidence.
+     */
+    double horizontalAccuracyMeters;
+    /**
+     * Estimated vertical accuracy of position expressed in meters, with
+     * 68% confidence.
+     */
+    double verticalAccuracyMeters;
+    /**
+     * Estimated speed accuracy in meters per second with 68% confidence.
+     */
+    double speedAccuracyMetersPerSecond;
+    /**
+     * estimated bearing accuracy degrees with 68% confidence.
+     */
+    double bearingAccuracyDegrees;
+    /**
+     * Time duration before this report that this position information was
+     * valid.  This can, for example, be a previous injected location with
+     * an age potentially thousands of seconds old, or
+     * extrapolated to the current time (with appropriately increased
+     * accuracy estimates), with a (near) zero age.
+     */
+    float ageSeconds;
+} PositionDebug;
+
+/**
+ * Provides the current best known UTC time estimate.
+ * If no fresh information is available, e.g. after a delete all,
+ * then whatever the effective defaults are on the device must be
+ * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+ * in the specified units.
+ */
+typedef struct {
+    /** UTC time estimate. */
+    GnssUtcTime timeEstimate;
+    /** 68% error estimate in time. */
+    float timeUncertaintyNs;
+    /**
+     * 68% error estimate in local clock drift,
+     * in nanoseconds per second (also known as parts per billion - ppb.)
+     */
+    float frequencyUncertaintyNsPerSec;
+} TimeDebug;
+
+/**
+ * Provides a single satellite info that has decoded navigation data.
+ */
+typedef struct {
+    /** Satellite vehicle ID number */
+    int16_t svid;
+    /** Defines the constellation type of the given SV. */
+    GnssConstellationType constellation;
+
+    /**
+     * Defines the standard broadcast ephemeris or almanac availability for
+     * the satellite.  To report status of predicted orbit and clock
+     * information, see the serverPrediction fields below.
+     */
+    SatelliteEphemerisType ephemerisType;
+    /** Defines the ephemeris source of the satellite. */
+    SatelliteEphemerisSource ephemerisSource;
+    /**
+     * Defines whether the satellite is known healthy
+     * (safe for use in location calculation.)
+     */
+    SatelliteEphemerisHealth ephemerisHealth;
+    /**
+     * Time duration from this report (current time), minus the
+     * effective time of the ephemeris source (e.g. TOE, TOA.)
+     * Set to 0 when ephemerisType is NOT_AVAILABLE.
+     */
+    float ephemerisAgeSeconds;
+
+    /**
+     * True if a server has provided a predicted orbit and clock model for
+     * this satellite.
+     */
+    bool serverPredictionIsAvailable;
+    /**
+     * Time duration from this report (current time) minus the time of the
+     * start of the server predicted information.  For example, a 1 day
+     * old prediction would be reported as 86400 seconds here.
+     */
+    float serverPredictionAgeSeconds;
+} SatelliteData;
+
+/**
+ * Provides a set of debug information that is filled by the GNSS chipset
+ * when the method getDebugData() is invoked.
+ */
+typedef struct {
+    /** Current best known position. */
+    PositionDebug position;
+    /** Current best know time estimate */
+    TimeDebug time;
+    /**
+     * Provides a list of the available satellite data, for all
+     * satellites and constellations the device can track,
+     * including GnssConstellationType UNKNOWN.
+     */
+    SatelliteData satelliteDataArray[GNSS_MAX_SVS];
+} DebugData;
+
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    // size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+    /// v1.0 ///
+    bool (*get_internal_state)(DebugData* debugData);
+} GpsDebugInterface_ext;
+
+
+////////////////////// GNSS HIDL v1.1 ////////////////////////////
+
+/**
+ * Callback for reporting driver name information.
+ */
+typedef void (* gnss_set_name_callback)(const char* name, int length);
+
+/**
+ * Callback for requesting framework NLP or Fused location injection.
+ */
+typedef void (* gnss_request_location_callback)(bool independentFromGnss);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_ext_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_ext_callback gnss_sv_status_cb;
+
+    /////v1.1////
+    gnss_set_name_callback set_name_cb;
+    gnss_request_location_callback request_location_cb;
+} GpsCallbacks_ext;
+
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    /// v1.0 ///
+//    int   (*init)( GpsCallbacks* callbacks );
+    /// v1.1 ///
+    int   (*init)( GpsCallbacks_ext* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+     /// v1.0 ///
+//    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+//            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+    /// v1.1 ///
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time,
+            bool lowPowerMode);
+
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+
+    /// v1.1 ///
+    int  (*inject_fused_location)(double latitude, double longitude, float accuracy);
+
+} GpsInterface_ext;
+
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface_ext) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    /// v1.0 ///
+//    int (*init) (GpsMeasurementCallbacks* callbacks);
+    /// v1.1 ///
+    int (*init) (GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface_ext;
+
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+
+   //// v1.1 ////
+   void (*setBlacklist) (long long* blacklist, int32_t size);
+} GnssConfigurationInterface_ext;
+
+
+#if defined (__ANDROID_OS__)
+struct gps_device_t_ext {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#elif defined (__LINUX_OS__)
+struct gps_device_t_ext {
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+#endif
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_MTK_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/epo.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/epo.h
new file mode 100644
index 0000000..d72ce08
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/epo.h
@@ -0,0 +1,61 @@
+#ifndef __EPO_H__
+#define __EPO_H__
+
+#include "curl.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EPO_PATH                    MTK_GPS_DATA_PATH
+#define EPO_FILE                    MTK_GPS_DATA_PATH"EPO.DAT"
+#define EPO_UPDATE_FILE             MTK_GPS_DATA_PATH"EPOTMP.DAT"
+#define EPO_UPDATE_HAL              MTK_GPS_DATA_PATH"EPOHAL.DAT"
+#define MTK_EPO_ONE_SV_SIZE  72
+#define SECONDS_PER_HOUR (60*60)
+#define EPO_DL_MAX_RETRY_TIME 3  //The max retry time of curl_easy_download fail
+#define EPO_INVALIDE_DL_MAX_RETRY_TIME 3  //The max retry time of whole download process
+#define EPO_INVALIDE_DL_RETRY_SLEEP (100*1000)  //100 ms
+#define MAX_EPO_PIECE 10
+#define EPO_MERGE_FULL_FILE   -1
+#define EPO_MD5_AVAILABLE_BIT   (1<<0)
+#define EPO_DAT_AVAILABLE_BIT   (1<<1)
+#define EPO_FILE_NAME_MAX_SIZE  60
+//#define EPO_MD5_FILE_MAX_SIZE   50
+#define EPO_MD5_FILE_MAX_SIZE   500
+
+#define GPS_EPO_FILE_LEN  32
+#define GPS_EPO_URL_LEN 256
+
+typedef struct EPO_Status {
+    unsigned int EPO_piece_flag[MAX_EPO_PIECE];
+    int last_DL_Date;
+    int today_retry_time;
+} EPO_Status_T;
+
+#ifdef CONFIG_GPS_MT3303
+void __getEpoUrl(char* filename, char* url);
+#endif
+
+int epo_downloader_init();
+int epo_read_cust_config();
+int epo_downloader_is_file_invalid();
+int epo_downloader_start();
+void epo_update_epo_file();
+int epo_is_wifi_trigger_enabled();
+int epo_is_epo_download_enabled();
+CURLcode curl_easy_download(char* url, char* filename);
+int mtk_gps_sys_epo_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+int mtk_gps_sys_epo_bd_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+void GpsToUtcTime(int i2Wn, double dfTow, time_t* uSecond);
+void getEpoUrl(char * filename, char * url);
+int mtk_gps_sys_epo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond);
+int mtk_gps_sys_read_lock(int fd, off_t offset, int whence, off_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps.h
new file mode 100644
index 0000000..596499c
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps.h
@@ -0,0 +1,2233 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#ifdef __ANDROID_OS__
+#include <hardware/hardware.h>
+#endif
+__BEGIN_DECLS
+
+/*
+ * Enums defined in HIDL in hardware/interfaces are auto-generated and present
+ * in gnss-base.h.
+ */
+
+/* for compatibility */
+
+/*#define GPS_REQUEST_AGPS_DATA_CONN GNSS_REQUEST_AGNSS_DATA_CONN
+#define GPS_RELEASE_AGPS_DATA_CONN GNSS_RELEASE_AGNSS_DATA_CONN
+#define GPS_AGPS_DATA_CONNECTED GNSS_AGNSS_DATA_CONNECTED
+#define GPS_AGPS_DATA_CONN_DONE GNSS_AGNSS_DATA_CONN_DONE
+#define GPS_AGPS_DATA_CONN_FAILED GNSS_AGNSS_DATA_CONN_FAILED
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS AGPS_RIL_NETWORK_TYPE_MMS
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL AGPS_RIL_NETWORK_TYPE_SUPL
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN AGPS_RIL_NETWORK_TYPE_DUN
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI AGPS_RIL_NETWORK_TYPE_HIPRI
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX AGPS_RIL_NETWORK_TYPE_WIMAX
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT GNSS_MULTIPATH_INDICATIOR_NOT_PRESENT
+#define AGPS_SETID_TYPE_MSISDN AGPS_SETID_TYPE_MSISDM
+#define GPS_MEASUREMENT_OPERATION_SUCCESS GPS_MEASUREMENT_SUCCESS
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS GPS_NAVIGATION_MESSAGE_SUCCESS
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L2CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L5CNAV
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_CNAV2
+#define GPS_LOCATION_HAS_ACCURACY GPS_LOCATION_HAS_HORIZONTAL_ACCURACY
+*/
+/**
+ * The id of this module
+ */
+#define GPS_HARDWARE_MODULE_ID "gps"
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS             0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT         -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC              -101
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GpsUtcTime;
+
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GPS_MAX_SVS 32
+/** Maximum number of SVs for gps_sv_status_callback(). */
+#define GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in gps_measurement_callback(). */
+#define GPS_MAX_MEASUREMENT   32
+
+/** Maximum number of Measurements in gnss_measurement_callback(). */
+#define GNSS_MAX_MEASUREMENT   64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t GpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define GPS_POSITION_MODE_STANDALONE    0
+/** AGPS MS-Based mode. */
+#define GPS_POSITION_MODE_MS_BASED      1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define GPS_POSITION_MODE_MS_ASSISTED   2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t GpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define GPS_POSITION_RECURRENCE_PERIODIC    0
+/** Request a single shot GPS fix. */
+#define GPS_POSITION_RECURRENCE_SINGLE      1
+
+/** GPS status event values. */
+typedef uint16_t GpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define GPS_STATUS_NONE             0
+/** GPS has begun navigating. */
+#define GPS_STATUS_SESSION_BEGIN    1
+/** GPS has stopped navigating. */
+#define GPS_STATUS_SESSION_END      2
+/** GPS has powered on but is not navigating. */
+#define GPS_STATUS_ENGINE_ON        3
+/** GPS is powered off. */
+#define GPS_STATUS_ENGINE_OFF       4
+
+/** Flags to indicate which values are valid in a GpsLocation. */
+typedef uint16_t GpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GpsLocation has valid latitude and longitude. */
+#define GPS_LOCATION_HAS_LAT_LONG   0x0001
+/** GpsLocation has valid altitude. */
+#define GPS_LOCATION_HAS_ALTITUDE   0x0002
+/** GpsLocation has valid speed. */
+#define GPS_LOCATION_HAS_SPEED      0x0004
+/** GpsLocation has valid bearing. */
+#define GPS_LOCATION_HAS_BEARING    0x0008
+/** GpsLocation has valid accuracy. */
+#define GPS_LOCATION_HAS_ACCURACY   0x0010
+
+/**
+ * GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define GPS_CAPABILITY_SCHEDULING       (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define GPS_CAPABILITY_MSB              (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define GPS_CAPABILITY_MSA              (1 << 2)
+/** GPS supports single-shot fixes */
+#define GPS_CAPABILITY_SINGLE_SHOT      (1 << 3)
+/** GPS supports on demand time injection */
+#define GPS_CAPABILITY_ON_DEMAND_TIME   (1 << 4)
+/** GPS supports Geofencing  */
+#define GPS_CAPABILITY_GEOFENCING       (1 << 5)
+/** GPS supports Measurements. */
+#define GPS_CAPABILITY_MEASUREMENTS     (1 << 6)
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES     (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t GpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#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
+
+/** AGPS type */
+typedef uint16_t AGpsType;
+#define AGPS_TYPE_SUPL          1
+#define AGPS_TYPE_C2K           2
+
+typedef uint16_t AGpsSetIDType;
+#define AGPS_SETID_TYPE_NONE    0
+#define AGPS_SETID_TYPE_IMSI    1
+#define AGPS_SETID_TYPE_MSISDN  2
+
+typedef uint16_t ApnIpType;
+#define APN_IP_INVALID          0
+#define APN_IP_IPV4             1
+#define APN_IP_IPV6             2
+#define APN_IP_IPV4V6           3
+
+/**
+ * String length constants
+ */
+#define GPS_NI_SHORT_STRING_MAXLEN      256
+#define GPS_NI_LONG_STRING_MAXLEN       2048
+
+/**
+ * GpsNiType constants
+ */
+typedef uint32_t GpsNiType;
+#define GPS_NI_TYPE_VOICE              1
+#define GPS_NI_TYPE_UMTS_SUPL          2
+#define GPS_NI_TYPE_UMTS_CTRL_PLANE    3
+
+/**
+ * GpsNiNotifyFlags constants
+ */
+typedef uint32_t GpsNiNotifyFlags;
+/** NI requires notification */
+#define GPS_NI_NEED_NOTIFY          0x0001
+/** NI requires verification */
+#define GPS_NI_NEED_VERIFY          0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define GPS_NI_PRIVACY_OVERRIDE     0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int GpsUserResponseType;
+#define GPS_NI_RESPONSE_ACCEPT         1
+#define GPS_NI_RESPONSE_DENY           2
+#define GPS_NI_RESPONSE_NORESP         3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int GpsNiEncodingType;
+#define GPS_ENC_NONE                   0
+#define GPS_ENC_SUPL_GSM_DEFAULT       1
+#define GPS_ENC_SUPL_UTF8              2
+#define GPS_ENC_SUPL_UCS2              3
+#define GPS_ENC_UNKNOWN                -1
+
+/** AGPS status event values. */
+typedef uint16_t AGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define GPS_REQUEST_AGPS_DATA_CONN  1
+/** GPS releases the AGPS data connection. */
+#define GPS_RELEASE_AGPS_DATA_CONN  2
+/** AGPS data connection initiated */
+#define GPS_AGPS_DATA_CONNECTED     3
+/** AGPS data connection completed */
+#define GPS_AGPS_DATA_CONN_DONE     4
+/** AGPS data connection failed */
+#define GPS_AGPS_DATA_CONN_FAILED   5
+
+typedef uint16_t AGpsRefLocationType;
+#define AGPS_REF_LOCATION_TYPE_GSM_CELLID   1
+#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID  2
+#define AGPS_REF_LOCATION_TYPE_MAC          3
+#define AGPS_REF_LOCATION_TYPE_LTE_CELLID   4
+
+/* Deprecated, to be removed in the next Android release. */
+#define AGPS_REG_LOCATION_TYPE_MAC          3
+
+/** Network types for update_network_state "type" parameter */
+#define AGPS_RIL_NETWORK_TYPE_MOBILE        0
+#define AGPS_RIL_NETWORK_TYPE_WIFI          1
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS    2
+#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL   3
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN   4
+#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define AGPS_RIL_NETWORK_TTYPE_WIMAX        6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsClockFlags;
+#define GPS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+#define GPS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+#define GPS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+#define GPS_CLOCK_HAS_BIAS                      (1<<3)
+#define GPS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+#define GPS_CLOCK_HAS_DRIFT                     (1<<5)
+#define GPS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/**
+ * Flags to indicate what fields in GnssClock are valid.
+ */
+typedef uint16_t GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsClockType;
+#define GPS_CLOCK_TYPE_UNKNOWN                  0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME            1
+#define GPS_CLOCK_TYPE_GPS_TIME                 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t GpsMeasurementFlags;
+#define GPS_MEASUREMENT_HAS_SNR                               (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION                         (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY             (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH                           (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY               (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE                       (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY           (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE                        (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY            (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER                        (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT                (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                     (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY         (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX                       (1<<17)
+#define GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE      (1<<18)
+
+/**
+ * Flags to indicate what fields in GnssMeasurement are valid.
+ */
+typedef uint32_t GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsLossOfLock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN                            0
+#define GPS_LOSS_OF_LOCK_OK                                 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP                         2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use GnssMultipathIndicator instead.
+ */
+typedef uint8_t GpsMultipathIndicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN                 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED                1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED                2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsMeasurementState;
+#define GPS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * GNSS_MEASUREMENT_STATE_CODE_LOCK | GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ *         GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t GnssMeasurementState;
+#define GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t GpsAccumulatedDeltaRangeState;
+#define GPS_ADR_STATE_UNKNOWN                       0
+#define GPS_ADR_STATE_VALID                     (1<<0)
+#define GPS_ADR_STATE_RESET                     (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t GnssAccumulatedDeltaRangeState;
+#define GNSS_ADR_STATE_UNKNOWN                       0
+#define GNSS_ADR_STATE_VALID                     (1<<0)
+#define GNSS_ADR_STATE_RESET                     (1<<1)
+#define GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN         0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA            1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV          2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV          3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2           4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the GnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN              0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW              0
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t                                 GnssSvFlags;
+#define GNSS_SV_FLAGS_NONE                      0
+#define GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA        (1 << 0)
+#define GNSS_SV_FLAGS_HAS_ALMANAC_DATA          (1 << 1)
+#define GNSS_SV_FLAGS_USED_IN_FIX               (1 << 2)
+
+/**
+ * Constellation type of GnssSvInfo
+ */
+typedef uint8_t                         GnssConstellationType;
+#define GNSS_CONSTELLATION_UNKNOWN      0
+#define GNSS_CONSTELLATION_GPS          1
+#define GNSS_CONSTELLATION_SBAS         2
+#define GNSS_CONSTELLATION_GLONASS      3
+#define GNSS_CONSTELLATION_QZSS         4
+#define GNSS_CONSTELLATION_BEIDOU       5
+#define GNSS_CONSTELLATION_GALILEO      6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define GPS_XTRA_INTERFACE      "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define GPS_DEBUG_INTERFACE      "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+#define AGPS_INTERFACE      "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define SUPL_CERTIFICATE_INTERFACE  "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define AGPS_RIL_INTERFACE      "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define GPS_GEOFENCING_INTERFACE   "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define GPS_MEASUREMENT_INTERFACE   "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define GPS_NAVIGATION_MESSAGE_INTERFACE     "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define GNSS_CONFIGURATION_INTERFACE     "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+    /** set to sizeof(GpsLocation) */
+    size_t          size;
+    /** Contains GpsLocationFlags bits. */
+    uint16_t        flags;
+    /** Represents latitude in degrees. */
+    double          latitude;
+    /** Represents longitude in degrees. */
+    double          longitude;
+    /**
+     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     */
+    double          altitude;
+    /** Represents speed in meters per second. */
+    float           speed;
+    /** Represents heading in degrees. */
+    float           bearing;
+    /** Represents expected accuracy in meters. */
+    float           accuracy;
+    /** Timestamp for the location fix. */
+    GpsUtcTime      timestamp;
+} GpsLocation;
+
+/** Represents the status. */
+typedef struct {
+    /** set to sizeof(GpsStatus) */
+    size_t          size;
+    GpsStatusValue status;
+} GpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvInfo instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvInfo) */
+    size_t          size;
+    /** Pseudo-random number for the SV. */
+    int     prn;
+    /** Signal to noise ratio. */
+    float   snr;
+    /** Elevation of SV in degrees. */
+    float   elevation;
+    /** Azimuth of SV in degrees. */
+    float   azimuth;
+} GpsSvInfo;
+
+typedef struct {
+    /** set to sizeof(GnssSvInfo) */
+    size_t size;
+
+    /**
+     * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+     * distinction is made by looking at constellation field. Values should be
+     * in the range of:
+     *
+     * - GPS:     1-32
+     * - SBAS:    120-151, 183-192
+     * - GLONASS: 1-24, the orbital slot number (OSN), if known.  Or, if not:
+     *            93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+     *            i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+     * - QZSS:    193-200
+     * - Galileo: 1-36
+     * - Beidou:  1-37
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    float c_n0_dbhz;
+
+    /** Elevation of SV in degrees. */
+    float elevation;
+
+    /** Azimuth of SV in degrees. */
+    float azimuth;
+
+    /**
+     * Contains additional data about the given SV. Value should be one of those
+     * GNSS_SV_FLAGS_* constants
+     */
+    GnssSvFlags flags;
+
+} GnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssSvStatus instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsSvStatus) */
+    size_t size;
+    int num_svs;
+    GpsSvInfo sv_list[GPS_MAX_SVS];
+    uint32_t ephemeris_mask;
+    uint32_t almanac_mask;
+    uint32_t used_in_fix_mask;
+} GpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+    AGpsRefLocationType type;
+    /** Mobile Country Code. */
+    uint16_t mcc;
+    /** Mobile Network Code .*/
+    uint16_t mnc;
+    /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+     * lac is populated with tac, to ensure that we don't break old clients that
+     * might rely in the old (wrong) behavior.
+     */
+    uint16_t lac;
+    /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+    uint32_t cid;
+    /** Tracking Area Code in LTE. */
+    uint16_t tac;
+    /** Physical Cell id in LTE (not used in 2G and 3G) */
+    uint16_t pcid;
+} AGpsRefLocationCellID;
+
+typedef struct {
+    uint8_t mac[6];
+} AGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+    AGpsRefLocationType type;
+    union {
+        AGpsRefLocationCellID   cellID;
+        AGpsRefLocationMac      mac;
+    } u;
+} AGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_callback)(GpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* gps_status_callback)(GpsStatus* status);
+
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_sv_status_callback() instead.
+ */
+typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_callback)(GnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of GPS_CAPABILITY_* flags.
+ */
+typedef void (* gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * GpsMeasurement support will be verified.
+ */
+typedef struct {
+    /** Set to sizeof(GnssSystemInfo) */
+    size_t   size;
+    /* year in which the last update was made to the underlying hardware/firmware
+     * used to capture GNSS signals, e.g. 2016 */
+    uint16_t year_of_hw;
+} GnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*gnss_set_system_info)(const GnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_callback gnss_sv_status_cb;
+} GpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int   (*init)( GpsCallbacks* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+} GpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+    gps_xtra_download_request download_request_cb;
+    gps_create_thread create_thread_cb;
+} GpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+    /** set to sizeof(GpsXtraInterface) */
+    size_t          size;
+    /**
+     * Opens the XTRA interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    int  (*init)( GpsXtraCallbacks* callbacks );
+    /** Injects XTRA data into the GPS. */
+    int  (*inject_xtra_data)( char* data, int length );
+} GpsXtraInterface;
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} GpsDebugInterface;
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+    /** set to sizeof(AGpsStatus) */
+    size_t                  size;
+
+    AGpsType                type;
+    AGpsStatusValue         status;
+
+    /**
+     * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+     * address, or set to INADDR_NONE otherwise.
+     */
+    uint32_t                ipaddr;
+
+    /**
+     * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+     * Any other value of addr.ss_family will be rejected.
+     */
+    struct sockaddr_storage addr;
+} AGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* agps_status_callback)(AGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+    agps_status_callback status_cb;
+    gps_create_thread create_thread_cb;
+} AGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+    /** set to sizeof(AGpsInterface) */
+    size_t size;
+
+    /**
+     * Opens the AGPS interface and provides the callback routines to the
+     * implementation of this interface.
+     */
+    void (*init)(AGpsCallbacks* callbacks);
+    /**
+     * Deprecated.
+     * If the HAL supports AGpsInterface_v2 this API will not be used, see
+     * data_conn_open_with_apn_ip_type for more information.
+     */
+    int (*data_conn_open)(const char* apn);
+    /**
+     * Notifies that the AGPS data connection has been closed.
+     */
+    int (*data_conn_closed)();
+    /**
+     * Notifies that a data connection is not available for AGPS.
+     */
+    int (*data_conn_failed)();
+    /**
+     * Sets the hostname and port for the AGPS server.
+     */
+    int (*set_server)(AGpsType type, const char* hostname, int port);
+
+    /**
+     * Notifies that a data connection is available and sets the name of the
+     * APN, and its IP type, to be used for SUPL connections.
+     */
+    int (*data_conn_open_with_apn_ip_type)(
+            const char* apn,
+            ApnIpType apnIpType);
+} AGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define AGPS_CERTIFICATE_OPERATION_SUCCESS               0
+#define AGPS_CERTIFICATE_ERROR_GENERIC                -100
+#define AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES  -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+    size_t  length;
+    u_char* data;
+} DerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+    u_char data[20];
+} Sha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+    /** set to sizeof(SuplCertificateInterface) */
+    size_t size;
+
+    /**
+     * Installs a set of Certificates used for SUPL connections to the AGPS server.
+     * If needed the HAL should find out internally any certificates that need to be removed to
+     * accommodate the certificates to install.
+     * The certificates installed represent a full set of valid certificates needed to connect to
+     * AGPS SUPL servers.
+     * The list of certificates is required, and all must be available at the same time, when trying
+     * to establish a connection with the AGPS Server.
+     *
+     * Parameters:
+     *      certificates - A pointer to an array of DER encoded certificates that are need to be
+     *                     installed in the HAL.
+     *      length - The number of certificates to install.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+     *      AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+     *          certificates attempted to be installed, the state of the certificates stored should
+     *          remain the same as before on this error case.
+     *
+     * IMPORTANT:
+     *      If needed the HAL should find out internally the set of certificates that need to be
+     *      removed to accommodate the certificates to install.
+     */
+    int  (*install_certificates) ( const DerEncodedCertificate* certificates, size_t length );
+
+    /**
+     * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+     * expected that the given set of certificates is removed from the internal store of the HAL.
+     *
+     * Parameters:
+     *      fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+     *                     certificates to revoke.
+     *      length - The number of fingerprints provided.
+     * Returns:
+     *      AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+     *
+     * IMPORTANT:
+     *      If any of the certificates provided (through its fingerprint) is not known by the HAL,
+     *      it should be ignored and continue revoking/deleting the rest of them.
+     */
+    int  (*revoke_certificates) ( const Sha1CertificateFingerprint* fingerprints, size_t length );
+} SuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+    /** set to sizeof(GpsNiNotification) */
+    size_t          size;
+
+    /**
+     * An ID generated by HAL to associate NI notifications and UI
+     * responses
+     */
+    int             notification_id;
+
+    /**
+     * An NI type used to distinguish different categories of NI
+     * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ...
+     */
+    GpsNiType       ni_type;
+
+    /**
+     * Notification/verification options, combinations of GpsNiNotifyFlags constants
+     */
+    GpsNiNotifyFlags notify_flags;
+
+    /**
+     * Timeout period to wait for user response.
+     * Set to 0 for no time out limit.
+     */
+    int             timeout;
+
+    /**
+     * Default response when time out.
+     */
+    GpsUserResponseType default_response;
+
+    /**
+     * Requestor ID
+     */
+    char            requestor_id[GPS_NI_SHORT_STRING_MAXLEN];
+
+    /**
+     * Notification message. It can also be used to store client_id in some cases
+     */
+    char            text[GPS_NI_LONG_STRING_MAXLEN];
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType requestor_id_encoding;
+
+    /**
+     * Client name decoding scheme
+     */
+    GpsNiEncodingType text_encoding;
+
+    /**
+     * A pointer to extra data. Format:
+     * key_1 = value_1
+     * key_2 = value_2
+     */
+    char           extras[GPS_NI_LONG_STRING_MAXLEN];
+
+} GpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+    /**
+     * Sends the notification request from HAL to GPSLocationProvider.
+     */
+    gps_ni_notify_callback notify_cb;
+    gps_create_thread create_thread_cb;
+} GpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+    /** set to sizeof(GpsNiInterface) */
+    size_t          size;
+
+   /** Registers the callbacks for HAL to use. */
+   void (*init) (GpsNiCallbacks *callbacks);
+
+   /** Sends a response to HAL. */
+   void (*respond) (int notif_id, GpsUserResponseType user_response);
+} GpsNiInterface;
+
+#if defined(__ANDROID_OS__)
+struct gps_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#elif defined(__LINUX_OS__)
+struct gps_device_t {
+    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
+};
+#endif
+
+#define AGPS_RIL_REQUEST_REFLOC_CELLID  (1<<0L)
+#define AGPS_RIL_REQUEST_REFLOC_MAC     (1<<1L)
+
+typedef void (*agps_ril_request_set_id)(uint32_t flags);
+typedef void (*agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+    agps_ril_request_set_id request_setid;
+    agps_ril_request_ref_loc request_refloc;
+    gps_create_thread create_thread_cb;
+} AGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+    /** set to sizeof(AGpsRilInterface) */
+    size_t          size;
+    /**
+     * Opens the AGPS interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    void  (*init)( AGpsRilCallbacks* callbacks );
+
+    /**
+     * Sets the reference location.
+     */
+    void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct);
+    /**
+     * Sets the set ID.
+     */
+    void (*set_set_id) (AGpsSetIDType type, const char* setid);
+
+    /**
+     * Send network initiated message.
+     */
+    void (*ni_message) (uint8_t *msg, size_t len);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+    /**
+     * Notify GPS of network status changes.
+     * These parameters match values in the android.net.NetworkInfo class.
+     */
+    void (*update_network_availability) (int avaiable, const char* apn);
+} AGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ *      There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ *     In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define GPS_GEOFENCE_ENTERED     (1<<0L)
+#define GPS_GEOFENCE_EXITED      (1<<1L)
+#define GPS_GEOFENCE_UNCERTAIN   (1<<2L)
+
+#define GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define GPS_GEOFENCE_AVAILABLE   (1<<1L)
+
+#define GPS_GEOFENCE_OPERATION_SUCCESS           0
+#define GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define GPS_GEOFENCE_ERROR_ID_EXISTS          -101
+#define GPS_GEOFENCE_ERROR_ID_UNKNOWN         -102
+#define GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define GPS_GEOFENCE_ERROR_GENERIC            -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_callback) (int32_t geofence_id,  GpsLocation* location,
+        int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_callback) (int32_t status, GpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES  - geofence limit has been reached.
+ *          GPS_GEOFENCE_ERROR_ID_EXISTS  - geofence with id already exists
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ *              invalid transition
+ *          GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ *                    when monitor_transitions is invalid
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - GPS_GEOFENCE_OPERATION_SUCCESS
+ *          GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ *          GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+    gps_geofence_transition_callback geofence_transition_callback;
+    gps_geofence_status_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssClock instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsClock) */
+    size_t size;
+    GpsClockFlags flags;
+    int16_t leap_second;
+    GpsClockType type;
+    int64_t time_ns;
+    double time_uncertainty_ns;
+    int64_t full_bias_ns;
+    double bias_ns;
+    double bias_uncertainty_ns;
+    double drift_nsps;
+    double drift_uncertainty_nsps;
+} GpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+    /** set to sizeof(GnssClock) */
+    size_t size;
+
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    GnssClockFlags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+     *      1,000,000,000
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+     */
+    int16_t leap_second;
+
+    /**
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
+     *
+     * For local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * available) from this value.
+     *
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+     * The value contains the 'time uncertainty' in it.
+     *
+     * This field is mandatory.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * The sign of the value is defined by the following equation:
+     *      local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+     *
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * bias) in nanoseconds. The uncertainty is represented as an absolute
+     * (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+     *
+     * This value is mandatory if the receiver has estimated GNSS time
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
+     */
+    double drift_uncertainty_nsps;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+
+} GnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssMeasurement instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+    GpsMeasurementFlags flags;
+    int8_t prn;
+    double time_offset_ns;
+    GpsMeasurementState state;
+    int64_t received_gps_tow_ns;
+    int64_t received_gps_tow_uncertainty_ns;
+    double c_n0_dbhz;
+    double pseudorange_rate_mps;
+    double pseudorange_rate_uncertainty_mps;
+    GpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+    double accumulated_delta_range_m;
+    double accumulated_delta_range_uncertainty_m;
+    double pseudorange_m;
+    double pseudorange_uncertainty_m;
+    double code_phase_chips;
+    double code_phase_uncertainty_chips;
+    float carrier_frequency_hz;
+    int64_t carrier_cycles;
+    double carrier_phase;
+    double carrier_phase_uncertainty;
+    GpsLossOfLock loss_of_lock;
+    int32_t bit_number;
+    int16_t time_from_last_bit_ms;
+    double doppler_shift_hz;
+    double doppler_shift_uncertainty_hz;
+    GpsMultipathIndicator multipath_indicator;
+    double snr_db;
+    double elevation_deg;
+    double elevation_uncertainty_deg;
+    double azimuth_deg;
+    double azimuth_uncertainty_deg;
+    bool used_in_fix;
+} GpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+    /** set to sizeof(GpsMeasurement) */
+    size_t size;
+
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    GnssMeasurementFlags flags;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    GnssConstellationType constellation;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     *
+     * This is a mandatory value.
+     */
+    GnssMeasurementState state;
+
+    /**
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
+     *
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     *
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_sv_time_uncertainty_in_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s. The correction of a given
+     * Pseudorange Rate value includes corrections for receiver and satellite
+     * clock frequency errors. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
+     *
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+     * shift' is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     *
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This is a mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     *
+     * This is a mandatory value.
+     */
+    GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     *
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
+     *
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
+     */
+    GnssMultipathIndicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
+     */
+    double snr_db;
+} GnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssData instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsData) */
+    size_t size;
+    size_t measurement_count;
+    GpsMeasurement measurements[GPS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GpsClock clock;
+} GpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gps_measurement_callback) (GpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_callback) (GnssData* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks;
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsMeasurementCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface;
+
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+    /** set to sizeof(GpsNavigationMessage) */
+    size_t size;
+    int8_t prn;
+    GpsNavigationMessageType type;
+    NavigationMessageStatus status;
+    int16_t message_id;
+    int16_t submessage_id;
+    size_t data_length;
+    uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+    /** set to sizeof(GnssNavigationMessage) */
+    size_t size;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a mandatory value.
+     */
+    GnssNavigationMessageType type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    NavigationMessageStatus status;
+
+    /**
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
+     */
+    int16_t message_id;
+
+    /**
+     * Sub-message identifier. If required by the message 'type', this value
+     * contains a sub-index within the current message (or frame) that is being
+     * transmitted.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+     */
+    int16_t submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     *
+     * This is a mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+     *
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
+     */
+    uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ *      message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+    /** set to sizeof(GpsNavigationMessageCallbacks) */
+    size_t size;
+    gps_navigation_message_callback navigation_message_callback;
+    gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsNavigationMessageInterface) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates as they become
+     * available.
+     *
+     * Status:
+     *      GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+     *      GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+     *              without a corresponding call to 'close'.
+     *      GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+     *              the HAL will not generate any updates upon returning this error code.
+     */
+    int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsNavigationMessageInterface;
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+} GnssConfigurationInterface;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_controller.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_controller.h
new file mode 100644
index 0000000..6b94470
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_controller.h
@@ -0,0 +1,68 @@
+#ifndef __GPS_CONTROLER_H__
+#define __GPS_CONTROLER_H__
+
+// #include <time.h>
+// #include <stdint.h>
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD_VERSION "MTK_MNLD_5_5_0_18011501"
+
+int gps_control_init();
+
+int gps_control_gps_start(int delete_aiding_data_flags);
+int gps_control_gps_stop();
+int gps_control_gps_reset(int delete_aiding_data_flags);
+
+void gps_control_kernel_wakelock_init();
+void gps_control_kernel_wakelock_take();
+void gps_control_kernel_wakelock_give();
+void gps_control_kernel_wakelock_uninit();
+
+bool mnl_offload_is_enabled(void);
+void mnl_offload_set_enabled(void);
+void mnl_offload_clear_enabled(void);
+bool mnld_offload_is_auto_mode(void);
+bool mnld_offload_is_always_on_mode(void);
+bool mnld_support_auto_switch_mode(void);
+void mnld_offload_check_capability(void);
+
+int mnl_init(void);
+void linux_signal_handler(int signo);
+int mnld_factory_test_entry(int argc, char** argv);
+int linux_setup_signal_handler(void);
+
+void gps_controller_agps_session_done(void);
+void gps_controller_rcv_pmtk(const char* pmtk);
+
+void get_chip_sv_support_capability(unsigned char* sv_type);
+#ifdef CONFIG_GPS_MT3303
+int gps_driver_state_init(void);
+void gps_control_mnl_set_status(void);
+void gps_control_mnl_set_pwrctl(void);
+int mnl_set_pwrctl(unsigned char pwrctl);
+
+int mnl_set_rdelay(int delay) ;
+
+int mnl_get_rdelay(void) ;
+
+
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+int get_gps_cmcc_log_enabled();
+#endif
+
+bool mnld_timeout_ne_enabled(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_dbg_log.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_dbg_log.h
new file mode 100644
index 0000000..a00d7f7
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/gps_dbg_log.h
@@ -0,0 +1,79 @@
+#ifndef __GPS_DBG_LOG_H__
+#define __GPS_DBG_LOG_H__
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+#define LOG_FILE            MTK_GPS_DATA_PATH"gpsdebug.log"
+#define LOG_FILE_PATH       MTK_GPS_DATA_PATH
+#define PATH_SUFFIX         "mtklog/gpsdbglog/"
+#define LOG_FILE_EXTEN_NAME ".nma"
+#define LOG_FILE_WRITING_EXTEN_NAME ".nmac"
+
+#if defined(__ANDROID_OS_P__)
+#define GPS_LOG_PERSIST_STATE "vendor.gpsdbglog.enable"
+#define GPS_LOG_PERSIST_PATH "vendor.gpsdbglog.path"
+#define GPS_LOG_PERSIST_FLNM "vendor.gpsdbglog.file"
+#elif defined(__ANDROID_OS_O__)
+#define GPS_LOG_PERSIST_STATE "debug.gpsdbglog.enable"
+#define GPS_LOG_PERSIST_PATH "debug.gpsdbglog.path"
+#define GPS_LOG_PERSIST_FLNM "debug.gpsdbglog.file"
+#endif
+
+#define GPS_LOG_PERSIST_VALUE_ENABLE "1"
+#define GPS_LOG_PERSIST_VALUE_DISABLE "0"
+#define GPS_LOG_PERSIST_VALUE_NONE "none"
+
+#define GPS_DBG_LOG_FILE_NUM_LIMIT 1000
+#define MAX_DBG_LOG_DIR_SIZE       (3UL*1024*1024*1024)
+#define MAX_DBG_LOG_FILE_SIZE      (25UL*1024*1024)
+
+enum {
+    MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNL = 0x00,
+    MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNL = 0x01,
+    MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD = 0x10,
+    MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD = 0x11,
+};
+// Task synchronization related type
+typedef enum{
+  MNLD_MUTEX_PINGPANG_WRITE = 0,
+  MNLD_MUTEX_MAX
+} mnld_mutex_enum;
+
+int gps_dbg_log_thread_init();
+
+int create_mtklogger2mnl_fd();
+
+int mtklogger2mnl_hdlr(int fd);
+
+size_t gps_log_dir_check(char * dirname);
+
+void gps_stop_dbglog_release_condition(void);
+
+void mtklogger_mped_reboot_message_update(void);
+int mnl_debug_file_check(char * dbg_file);
+//Rename gpsdebug name, .nmac to .nma
+void gps_log_file_rename(char *filename_cur);
+
+void gps_dbg_log_property_load(void);
+
+void gps_dbg_log_exit_flush(int force_exit) ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h
new file mode 100644
index 0000000..a77e739
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/hal_mnl_interface_common.h
@@ -0,0 +1,1350 @@
+#ifndef __HAL_MNL_INTERFACE_COMMON_H__
+#define __HAL_MNL_INTERFACE_COMMON_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HAL_MNL_BUFF_SIZE           (16 * 1024)
+#define HAL_MNL_INTERFACE_VERSION   1
+
+//======================================================
+// GPS HAL -> MNLD
+//======================================================
+#define MTK_HAL2MNL "mtk_hal2mnl"
+
+typedef enum {
+    HAL2MNL_HAL_REBOOT                      = 0,
+    HAL2MNL_GPS_INIT                        = 101,
+    HAL2MNL_GPS_START                       = 102,
+    HAL2MNL_GPS_STOP                        = 103,
+    HAL2MNL_GPS_CLEANUP                     = 104,
+    HAL2MNL_GPS_INJECT_TIME                 = 105,
+    HAL2MNL_GPS_INJECT_LOCATION             = 106,
+    HAL2MNL_GPS_DELETE_AIDING_DATA          = 107,
+    HAL2MNL_GPS_SET_POSITION_MODE           = 108,
+    HAL2MNL_DATA_CONN_OPEN                  = 201,
+    HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE = 202,
+    HAL2MNL_DATA_CONN_CLOSED                = 203,
+    HAL2MNL_DATA_CONN_FAILED                = 204,
+    HAL2MNL_SET_SERVER                      = 301,
+    HAL2MNL_SET_REF_LOCATION                = 302,
+    HAL2MNL_SET_ID                          = 303,
+    HAL2MNL_NI_MESSAGE                      = 401,
+    HAL2MNL_NI_RESPOND                      = 402,
+    HAL2MNL_UPDATE_NETWORK_STATE            = 501,
+    HAL2MNL_UPDATE_NETWORK_AVAILABILITY     = 502,
+    HAL2MNL_GPS_MEASUREMENT                 = 601,
+    HAL2MNL_GPS_NAVIGATION                  = 602,
+    HAL2MNL_VZW_DEBUG                       = 603,
+    HAL2MNL_GNSS_CONFIG                     = 604,
+    //HAL2MNL_SV_BLACKLIST                    = 605,
+    HAL2MNL_SEND_PMTK                       = 701,
+} hal2mnl_cmd;
+
+typedef int gps_pos_mode;
+#define GPS_POS_MODE_STANDALONE     0
+#define GPS_POS_MODE_MSB            1
+
+typedef int gps_pos_recurrence;
+#define GPS_POS_RECURRENCE_PERIODIC     0
+#define GPS_POS_RECURRENCE_SINGLE       1
+
+typedef int ni_user_response_type;
+#define NI_USER_RESPONSE_ACCEPT     1
+#define NI_USER_RESPONSE_DENY       2
+#define NI_USER_RESPONSE_NORESP     3
+
+typedef int cell_type;
+#define CELL_TYPE_GSM       1
+#define CELL_TYPE_UMTS      2
+
+typedef int agps_id_type;
+#define AGPS_ID_TYPE_NONE       0
+#define AGPS_ID_TYPE_IMSI       1
+#define AGPS_ID_TYPE_MSISDN     2
+
+typedef int network_type;
+#define NETWORK_TYPE_MOBILE         0
+#define NETWORK_TYPE_WIFI           1
+#define NETWORK_TYPE_MOBILE_MMS     2
+#define NETWORK_TYPE_MOBILE_SUPL    3
+#define NETWORK_TYPE_MOBILE_DUN     4
+#define NETWORK_TYPE_MOBILE_HIPRI   5
+#define NETWORK_TYPE_WIMAX          6
+
+typedef int apn_ip_type;
+#define MTK_APN_IP_INVALID          0
+#define MTK_APN_IP_IPV4             1
+#define MTK_APN_IP_IPV6             2
+#define MTK_APN_IP_IPV4V6           3
+
+typedef int agps_type;
+#define MTK_AGPS_TYPE_SUPL          1
+#define MTK_AGPS_TYPE_C2K           2
+
+//======================================================
+// MNLD -> GPS HAL
+//======================================================
+#define MTK_MNL2HAL "mtk_mnl2hal"
+
+typedef enum {
+    MNL2HAL_MNLD_REBOOT             = 1,
+    MNL2HAL_LOCATION                = 101,
+    MNL2HAL_GPS_STATUS              = 102,
+    MNL2HAL_GPS_SV                  = 103,
+    MNL2HAL_NMEA                    = 104,
+    MNL2HAL_GPS_CAPABILITIES        = 105,
+    MNL2HAL_GPS_MEASUREMENTS        = 106,
+    MNL2HAL_GPS_NAVIGATION          = 107,
+    MNL2HAL_GNSS_MEASUREMENTS       = 108,
+    MNL2HAL_GNSS_NAVIGATION         = 109,
+    MNL2HAL_REQUEST_WAKELOCK        = 201,
+    MNL2HAL_RELEASE_WAKELOCK        = 202,
+    MNL2HAL_REQUEST_UTC_TIME        = 301,
+    MNL2HAL_REQUEST_DATA_CONN       = 302,
+    MNL2HAL_RELEASE_DATA_CONN       = 303,
+    MNL2HAL_REQUEST_NI_NOTIFY       = 304,
+    MNL2HAL_REQUEST_SET_ID          = 305,
+    MNL2HAL_REQUEST_REF_LOC         = 306,
+    MNL2HAL_VZW_DEBUG_OUTPUT        = 307,
+    MNL2HAL_UPDATE_GNSS_NAME        = 308,
+    MNL2HAL_REQUEST_NLP             = 309,
+} mnl2hal_cmd;
+
+#define MTK_MNLD_GNSS_MAX_SVS            64
+#define GPS_MAX_MEASUREMENT     32
+#define MTK_MNLD_GNSS_MAX_MEASUREMENT    64
+
+typedef int gps_location_flags;
+#define MTK_GPS_LOCATION_HAS_LAT_LONG   0x0001
+#define MTK_GPS_LOCATION_HAS_ALT        0x0002
+#define MTK_GPS_LOCATION_HAS_SPEED      0x0004
+#define MTK_GPS_LOCATION_HAS_BEARING    0x0008
+#define MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY    0x0010
+#define MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY      0x0020
+#define MTK_GPS_LOCATION_HAS_SPEED_ACCURACY         0x0040
+#define MTK_GPS_LOCATION_HAS_BEARING_ACCURACY       0x0080
+
+typedef int gps_capabilites;
+#define GPS_CAP_SCHEDULING       0x0000001
+#define GPS_CAP_MSB              0x0000002
+#define GPS_CAP_MSA              0x0000004
+#define GPS_CAP_SINGLE_SHOT      0x0000008
+#define GPS_CAP_ON_DEMAND_TIME   0x0000010
+#define GPS_CAP_GEOFENCING       0x0000020
+#define GPS_CAP_MEASUREMENTS     0x0000040
+#define GPS_CAP_NAV_MESSAGES     0x0000080
+
+typedef int request_setid;
+#define REQUEST_SETID_IMSI     (1<<0L)
+#define REQUEST_SETID_MSISDN   (1<<1L)
+
+typedef int request_refloc;
+#define REQUEST_REFLOC_CELLID  (1<<0L)
+#define REQUEST_REFLOC_MAC     (1<<1L)   // not ready
+
+typedef short gps_clock_flags;
+#define GPS_CLK_HAS_LEAP_SECOND               (1<<0)
+#define GPS_CLK_HAS_TIME_UNCERTAINTY          (1<<1)
+#define GPS_CLK_HAS_FULL_BIAS                 (1<<2)
+#define GPS_CLK_HAS_BIAS                      (1<<3)
+#define GPS_CLK_HAS_BIAS_UNCERTAINTY          (1<<4)
+#define GPS_CLK_HAS_DRIFT                     (1<<5)
+#define GPS_CLK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+typedef char gps_clock_type;
+#define GPS_CLOCK_TYPE_UNKNOWN                  0
+#define GPS_CLOCK_TYPE_LOCAL_HW_TIME            1
+#define GPS_CLOCK_TYPE_GPS_TIME                 2
+
+typedef int gps_measurement_flags;
+#define GPS_MEASUREMENT_HAS_SNR                               (1<<0)
+#define GPS_MEASUREMENT_HAS_ELEVATION                         (1<<1)
+#define GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY             (1<<2)
+#define GPS_MEASUREMENT_HAS_AZIMUTH                           (1<<3)
+#define GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY               (1<<4)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE                       (1<<5)
+#define GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY           (1<<6)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE                        (1<<7)
+#define GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY            (1<<8)
+#define GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+#define GPS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+#define GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+#define GPS_MEASUREMENT_HAS_BIT_NUMBER                        (1<<13)
+#define GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT                (1<<14)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT                     (1<<15)
+#define GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY         (1<<16)
+#define GPS_MEASUREMENT_HAS_USED_IN_FIX                       (1<<17)
+
+typedef short gps_measurement_state;
+#define GPS_MEASUREMENT_STATE_UNKNOWN                   0
+#define GPS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define GPS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define GPS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define GPS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+
+typedef short gps_accumulated_delta_range_state;
+#define GPS_ADR_STATE_UNKNOWN                       0
+#define GPS_ADR_STATE_VALID                     (1<<0)
+#define GPS_ADR_STATE_RESET                     (1<<1)
+#define GPS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+typedef char gps_loss_of_lock;
+#define GPS_LOSS_OF_LOCK_UNKNOWN                            0
+#define GPS_LOSS_OF_LOCK_OK                                 1
+#define GPS_LOSS_OF_LOCK_CYCLE_SLIP                         2
+
+typedef char gps_multipath_indicator;
+#define GPS_MULTIPATH_INDICATOR_UNKNOWN                 0
+#define GPS_MULTIPATH_INDICATOR_DETECTED                1
+#define GPS_MULTIPATH_INDICATOR_NOT_USED                2
+
+typedef char gps_nav_msg_type;
+#define GPS_NAV_MSG_TYPE_UNKNOWN         0
+#define GPS_NAV_MSG_TYPE_L1CA            1
+#define GPS_NAV_MSG_TYPE_L2CNAV          2
+#define GPS_NAV_MSG_TYPE_L5CNAV          3
+#define GPS_NAV_MSG_TYPE_CNAV2           4
+
+typedef short nav_msg_status;
+#define NAV_MSG_STATUS_UNKONW              0
+#define NAV_MSG_STATUS_PARITY_PASSED   (1<<0)
+#define NAV_MSG_STATUS_PARITY_REBUILT  (1<<1)
+
+typedef int gps_status;
+#define MTK_GPS_STATUS_SESSION_BEGIN        1
+#define MTK_GPS_STATUS_SESSION_END          2
+#define MTK_GPS_STATUS_SESSION_ENGINE_ON    3
+#define MTK_GPS_STATUS_SESSION_ENGINE_OFF   4
+
+typedef int agps_ni_type;
+#define AGPS_NI_TYPE_VOICE              1
+#define AGPS_NI_TYPE_UMTS_SUPL          2
+#define AGPS_NI_TYPE_UMTS_CTRL_PLANE    3
+#define AGPS_NI_TYPE_EMERGENCY_SUPL     4
+
+typedef int agps_notify_type;
+#define AGPS_NOTIFY_TYPE_NONE                       0
+#define AGPS_NOTIFY_TYPE_NOTIFY_ONLY                1
+#define AGPS_NOTIFY_TYPE_NOTIFY_ALLOW_NO_ANSWER     2
+#define AGPS_NOTIFY_TYPE_NOTIFY_DENY_NO_ANSWER      3
+#define AGPS_NOTIFY_TYPE_PRIVACY                    4
+
+typedef int ni_encoding_type;
+#define NI_ENCODING_TYPE_NONE   0
+#define NI_ENCODING_TYPE_GSM7   1
+#define NI_ENCODING_TYPE_UTF8   2
+#define NI_ENCODING_TYPE_UCS2   3
+
+typedef struct {
+    gps_location_flags flags;
+    double lat;
+    double lng;
+    double alt;
+    float speed;
+    float bearing;
+    float h_accuracy;  //horizontal
+    float v_accuracy;  //vertical
+    float s_accuracy;  //spedd
+    float b_accuracy;  //bearing
+    int64_t timestamp;
+} gps_location;
+
+typedef struct {
+    int16_t   svid;
+    uint8_t   constellation;
+    float   c_n0_dbhz;
+    float   elevation;
+    float   azimuth;
+    uint8_t flags;
+    float     carrier_frequency;
+} gnss_sv;
+
+typedef struct {
+    int  num_svs;
+    gnss_sv  sv_list[MTK_MNLD_GNSS_MAX_SVS];
+} gnss_sv_info;
+
+typedef struct {
+    int prn;
+    bool has_ephemeris_data;
+    bool has_almanac_data;
+    bool used_in_fix;
+} NmeaCash;
+
+typedef uint16_t MTK_MNLD_NavigationMessageStatus;
+#define MTK_NAV_MESSAGE_STATUS_UNKNOWN              0
+#define MTK_NAV_MESSAGE_STATUS_PARITY_PASSED   (1<<0)
+#define MTK_NAV_MESSAGE_STATUS_PARITY_REBUILT  (1<<1)
+
+typedef int16_t MTK_MNLD_GnssNavigationMessageType;
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN       0
+/** GPS L1 C/A message contained in the structure.  */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA      0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV    0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV    0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2     0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA      0x0301
+/** Beidou D1 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1        0x0501
+/** Beidou D2 message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2        0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I         0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define MTK_GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F         0x0602
+
+typedef uint8_t MTK_MNLD_GnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_UNKNOWN                 0
+/** The measurement is indicated to be affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_PRESENT                 1
+/** The measurement is indicated to be not affected by multipath. */
+#define MTK_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT             2
+
+typedef uint16_t MTK_MNLD_GnssAccumulatedDeltaRangeState;
+#define MTK_GNSS_ADR_STATE_UNKNOWN                       0
+#define MTK_GNSS_ADR_STATE_VALID                     (1<<0)
+#define MTK_GNSS_ADR_STATE_RESET                     (1<<1)
+#define MTK_GNSS_ADR_STATE_CYCLE_SLIP                (1<<2)
+
+typedef uint32_t MTK_MNLD_GnssMeasurementState;
+#define MTK_GNSS_MEASUREMENT_STATE_UNKNOWN                   0
+#define MTK_GNSS_MEASUREMENT_STATE_CODE_LOCK             (1<<0)
+#define MTK_GNSS_MEASUREMENT_STATE_BIT_SYNC              (1<<1)
+#define MTK_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC         (1<<2)
+#define MTK_GNSS_MEASUREMENT_STATE_TOW_DECODED           (1<<3)
+#define MTK_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS        (1<<4)
+#define MTK_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC           (1<<5)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC       (1<<6)
+#define MTK_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED       (1<<7)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC       (1<<8)
+#define MTK_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC  (1<<9)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK    (1<<10)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define MTK_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC     (1<<12)
+#define MTK_GNSS_MEASUREMENT_STATE_SBAS_SYNC             (1<<13)
+
+typedef uint8_t  MTK_MNLD_GnssConstellationType;
+#define MTK_GNSS_CONSTELLATION_UNKNOWN      0
+#define MTK_GNSS_CONSTELLATION_GPS          1
+#define MTK_GNSS_CONSTELLATION_SBAS         2
+#define MTK_GNSS_CONSTELLATION_GLONASS      3
+#define MTK_GNSS_CONSTELLATION_QZSS         4
+#define MTK_GNSS_CONSTELLATION_BEIDOU       5
+#define MTK_GNSS_CONSTELLATION_GALILEO      6
+
+typedef uint32_t MTK_MNLD_GnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_SNR                               (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY                 (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES                    (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE                     (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define MTK_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY         (1<<12)
+
+typedef uint16_t MTK_MNLD_GnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_LEAP_SECOND               (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_TIME_UNCERTAINTY          (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_FULL_BIAS                 (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS                      (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY          (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT                     (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define MTK_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY         (1<<6)
+
+typedef struct {
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    gps_clock_flags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_LEAP_SECOND.
+     */
+    short leap_second;
+
+    /**
+     * Indicates the type of time reported by the 'time_ns' field.
+     */
+    gps_clock_type type;
+
+    /**
+     * The GPS receiver internal clock value. This can be either the local hardware clock value
+     * (GPS_CLOCK_TYPE_LOCAL_HW_TIME), or the current GPS time derived inside GPS receiver
+     * (GPS_CLOCK_TYPE_GPS_TIME). The field 'type' defines the time reported.
+     *
+     * For local hardware clock, this value is expected to be monotonically increasing during
+     * the reporting session. The real GPS time can be derived by compensating the 'full bias'
+     * (when it is available) from this value.
+     *
+     * For GPS time, this value is expected to be the best estimation of current GPS time that GPS
+     * receiver can achieve. Set the 'time uncertainty' appropriately when GPS time is specified.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias' field.
+     * The value contains the 'time uncertainty' in it.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This value should be set if GPS_CLOCK_TYPE_GPS_TIME is set.
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_TIME_UNCERTAINTY.
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver and the true GPS
+     * time since 0000Z, January 6, 1980, in nanoseconds.
+     * This value is used if and only if GPS_CLOCK_TYPE_LOCAL_HW_TIME is set, and GPS receiver
+     * has solved the clock for GPS time.
+     * The caller is responsible for using the 'bias uncertainty' field for quality check.
+     *
+     * The sign of the value is defined by the following equation:
+     *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+     *
+     * This value contains the 'bias uncertainty' in it.
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_FULL_BIAS.
+
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The value contains the 'bias uncertainty' in it.
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's bias in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_BIAS_UNCERTAINTY.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     * A positive value means that the frequency is higher than the nominal frequency.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT.
+     *
+     * If GpsMeasurement's 'flags' field contains GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+     * it is encouraged that this field is also provided.
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain GPS_CLOCK_HAS_DRIFT_UNCERTAINTY.
+     */
+    double drift_uncertainty_nsps;
+} gps_clock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+    /**
+     * A set of flags indicating the validity of the fields in this data
+     * structure.
+     */
+    MTK_MNLD_GnssClockFlags flags;
+
+    /**
+     * Leap second data.
+     * The sign of the value is defined by the following equation:
+     *      utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+     *      1,000,000,000
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_LEAP_SECOND.
+     */
+    int16_t leap_second;
+
+    /**
+     * The GNSS receiver internal clock value. This is the local hardware clock
+     * value.
+     *
+     * For local hardware clock, this value is expected to be monotonically
+     * increasing while the hardware clock remains power on. (For the case of a
+     * HW clock that is not continuously on, see the
+     * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+     * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+     * available) from this value.
+     *
+     * This GPS time is expected to be the best estimate of current GPS time
+     * that GNSS receiver can achieve.
+     *
+     * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+     * The value contains the 'time uncertainty' in it.
+     *
+     * This field is mandatory.
+     */
+    int64_t time_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+     * the reference local clock, by which all other times and time
+     * uncertainties are measured.)  (And thus this field can be not provided,
+     * per GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+     */
+    double time_uncertainty_ns;
+
+    /**
+     * The difference between hardware clock ('time' field) inside GPS receiver
+     * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * The sign of the value is defined by the following equation:
+     *      local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+     *
+     * This value is mandatory if the receiver has estimated GPS time. If the
+     * computed time is for a non-GPS constellation, the time offset of that
+     * constellation to GPS has to be applied to fill this value. The error
+     * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+     * and the caller is responsible for using this uncertainty (it can be very
+     * large before the GPS time has been solved for.) If the data is available
+     * 'flags' must contain GNSS_CLOCK_HAS_FULL_BIAS.
+     */
+    int64_t full_bias_ns;
+
+    /**
+     * Sub-nanosecond bias.
+     * The error estimate for the sum of this and the full_bias_ns is the
+     * bias_uncertainty_ns
+     *
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_BIAS. If GPS
+     * has computed a position fix. This value is mandatory if the receiver has
+     * estimated GPS time.
+     */
+    double bias_ns;
+
+    /**
+     * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+     * bias) in nanoseconds. The uncertainty is represented as an absolute
+     * (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+     * has estimated GPS time.
+     */
+    double bias_uncertainty_ns;
+
+    /**
+     * The clock's drift in nanoseconds (per second).
+     *
+     * A positive value means that the frequency is higher than the nominal
+     * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+     * over time.
+     *
+     * The value contains the 'drift uncertainty' in it.
+     * If the data is available 'flags' must contain GNSS_CLOCK_HAS_DRIFT.
+     *
+     * This value is mandatory if the receiver has estimated GNSS time
+     */
+    double drift_nsps;
+
+    /**
+     * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available 'flags' must contain
+     * GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+     * field is mandatory and must be populated.
+     */
+    double drift_uncertainty_nsps;
+
+    /**
+     * When there are any discontinuities in the HW clock, this field is
+     * mandatory.
+     *
+     * A "discontinuity" is meant to cover the case of a switch from one source
+     * of clock to another.  A single free-running crystal oscillator (XO)
+     * should generally not have any discontinuities, and this can be set and
+     * left at 0.
+     *
+     * If, however, the time_ns value (HW clock) is derived from a composite of
+     * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+     * restarted, then this value shall be incremented each time a discontinuity
+     * occurs.  (E.g. this value may start at zero at device boot-up and
+     * increment each time there is a change in clock continuity. In the
+     * unlikely event that this value reaches full scale, rollover (not
+     * clamping) is required, such that this value continues to change, during
+     * subsequent discontinuity events.)
+     *
+     * While this number stays the same, between GnssClock reports, it can be
+     * safely assumed that the time_ns value has been running continuously, e.g.
+     * derived from a single, high quality clock (XO like, or better, that's
+     * typically used during continuous GNSS signal sampling.)
+     *
+     * It is expected, esp. during periods where there are few GNSS signals
+     * available, that the HW clock be discontinuity-free as long as possible,
+     * as this avoids the need to use (waste) a GNSS measurement to fully
+     * re-solve for the GPS clock bias and drift, when using the accompanying
+     * measurements, from consecutive GnssData reports.
+     */
+    uint32_t hw_clock_discontinuity_count;
+} gnss_clock;
+
+typedef struct {
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    gps_measurement_flags flags;
+
+    /**
+     * Pseudo-random number in the range of [1, 32]
+     * This is a Mandatory value.
+     */
+    int8_t prn;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a Mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     * This is a Mandatory value.
+     */
+    gps_measurement_state state;
+
+    /**
+     * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     * The value is relative to the beginning of the current GPS week.
+     *
+     * Given the highest sync state that can be achieved, per each satellite, valid range for
+     * this field can be:
+     *     Searching       : [ 0       ]   : GPS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GPS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GPS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GPS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GPS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * However, if there is any ambiguity in integer millisecond,
+     * GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_gps_tow_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_gps_tow_uncertainty_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna input.
+     * This is a Mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s.
+     * The value also includes the effects of the receiver clock frequency and satellite clock
+     * frequency errors.
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive value indicates that the pseudorange is getting larger.
+     * This is a Mandatory value.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudurange rate in m/s.
+     * The uncertainty is represented as an absolute (single sided) value.
+     * This is a Mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     * This is a Mandatory value.
+     */
+    gps_accumulated_delta_range_state accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * The data is available if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Best derived Pseudorange by the chip-set, in meters.
+     * The value contains the 'pseudorange uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE.
+     */
+    double pseudorange_m;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange in meters.
+     * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY.
+     */
+    double pseudorange_uncertainty_m;
+
+    /**
+     * A fraction of the current C/A code cycle, in the range [0.0, 1023.0]
+     * This value contains the time (in Chip units) since the last C/A code cycle (GPS Msec epoch).
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'code-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE.
+     */
+    double code_phase_chips;
+
+    /**
+     * 1-Sigma uncertainty of the code-phase, in a fraction of chips.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY.
+     */
+    double code_phase_uncertainty_chips;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'loss of lock' state of the event.
+     */
+    gps_loss_of_lock loss_of_lock;
+
+    /**
+     * The number of GPS bits transmitted since Sat-Sun midnight (GPS week).
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_BIT_NUMBER.
+     */
+    int32_t bit_number;
+
+    /**
+     * The elapsed time since the last received bit in milliseconds, in the range [0, 20]
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT.
+     */
+    int16_t time_from_last_bit_ms;
+
+    /**
+     * Doppler shift in Hz.
+     * A positive value indicates that the SV is moving toward the receiver.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'doppler shift uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT.
+     */
+    double doppler_shift_hz;
+
+    /**
+     * 1-Sigma uncertainty of the doppler shift in Hz.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY.
+     */
+    double doppler_shift_uncertainty_hz;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     */
+    gps_multipath_indicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio in dB.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_SNR.
+     */
+    double snr_db;
+
+    /**
+     * Elevation in degrees, the valid range is [-90, 90].
+     * The value contains the 'elevation uncertainty' in it.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION.
+     */
+    double elevation_deg;
+
+    /**
+     * 1-Sigma uncertainty of the elevation in degrees, the valid range is [0, 90].
+     * The uncertainty is represented as the absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY.
+     */
+    double elevation_uncertainty_deg;
+
+    /**
+     * Azimuth in degrees, in the range [0, 360).
+     * The value contains the 'azimuth uncertainty' in it.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH.
+     *  */
+    double azimuth_deg;
+
+    /**
+     * 1-Sigma uncertainty of the azimuth in degrees, the valid range is [0, 180].
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY.
+     */
+    double azimuth_uncertainty_deg;
+
+    /**
+     * Whether the GPS represented by the measurement was used for computing the most recent fix.
+     * If the data is available, 'flags' must contain GPS_MEASUREMENT_HAS_USED_IN_FIX.
+     */
+    bool used_in_fix;
+} gps_measurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+    /** A set of flags indicating the validity of the fields in this data structure. */
+    MTK_MNLD_GnssMeasurementFlags flags;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * Defines the constellation of the given SV. Value should be one of those
+     * GNSS_CONSTELLATION_* constants
+     */
+    MTK_MNLD_GnssConstellationType constellation;
+
+    /**
+     * Time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by GpsData::clock::time_ns and should be
+     * interpreted in the same way as indicated by GpsClock::type.
+     *
+     * The sign of time_offset_ns is given by the following equation:
+     *      measurement time = GpsClock::time_ns + time_offset_ns
+     *
+     * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+     * This is a mandatory value.
+     */
+    double time_offset_ns;
+
+    /**
+     * Per satellite sync state. It represents the current sync state for the associated satellite.
+     * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+     *
+     * This is a mandatory value.
+     */
+    MTK_MNLD_GnssMeasurementState state;
+
+    /**
+     * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+     * Ensure that this field is independent (see comment at top of
+     * GnssMeasurement struct.)
+     *
+     * For GPS & QZSS, this is:
+     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
+     *   The value is relative to the beginning of the current GPS week.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range
+     *   for this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe sync   : [ 0    6s ]   : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     TOW decoded     : [ 0 1week ]   : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     *   Note well: if there is any ambiguity in integer millisecond,
+     *   GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     *
+     *   This value must be populated if 'state' != GNSS_MEASUREMENT_STATE_UNKNOWN.
+     *
+     * For Glonass, this is:
+     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching       : [ 0       ]   : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock   : [ 0   1ms ]   : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync     : [ 0  10ms ]   : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+     *
+     * For Beidou, this is:
+     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite, valid range for
+     *   this field can be:
+     *     Searching    : [ 0       ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0   1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Bit sync (D2): [ 0   2ms ] : GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+     *     Bit sync (D1): [ 0  20ms ] : GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+     *     Subframe (D2): [ 0  0.6s ] : GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+     *     Subframe (D1): [ 0    6s ] : GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+     *     Time of week : [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For Galileo, this is:
+     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     *
+     *     E1BC code lock   : [ 0   4ms ]   : GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]   :
+     *     GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *
+     *     E1B page    : [ 0    2s ] : GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week: [ 0 1week ] : GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+     *
+     * For SBAS, this is:
+     *   Received SBAS time, at the measurement time in nanoseconds.
+     *
+     *   Given the highest sync state that can be achieved, per each satellite,
+     *   valid range for this field can be:
+     *     Searching    : [ 0     ] : GNSS_MEASUREMENT_STATE_UNKNOWN
+     *     C/A code lock: [ 0 1ms ] : GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+     *     Symbol sync  : [ 0 2ms ] : GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+     *     Message      : [ 0  1s ] : GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+    */
+    int64_t received_sv_time_in_ns;
+
+    /**
+     * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+     *
+     * This value must be populated if 'state' != GPS_MEASUREMENT_STATE_UNKNOWN.
+     */
+    int64_t received_sv_time_uncertainty_in_ns;
+
+    /**
+     * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+     * It contains the measured C/N0 value for the signal at the antenna port.
+     *
+     * This is a mandatory value.
+     */
+    double c_n0_dbhz;
+
+    /**
+     * Pseudorange rate at the timestamp in m/s. The correction of a given
+     * Pseudorange Rate value includes corrections for receiver and satellite
+     * clock frequency errors. Ensure that this field is independent (see
+     * comment at top of GnssMeasurement struct.)
+     *
+     * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide GpsClock's
+     * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+     * corrections described above.)
+     *
+     * The value includes the 'pseudorange rate uncertainty' in it.
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+     * shift' is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     *
+     * This should be the most accurate pseudorange rate available, based on
+     * fresh signal measurements from this channel.
+     *
+     * It is mandatory that this value be provided at typical carrier phase PRR
+     * quality (few cm/sec per second of uncertainty, or better) - when signals
+     * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+     * 35 dB-Hz.
+     */
+    double pseudorange_rate_mps;
+
+    /**
+     * 1-Sigma uncertainty of the pseudorange_rate_mps.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * This is a mandatory value.
+     */
+    double pseudorange_rate_uncertainty_mps;
+
+    /**
+     * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+     * (indicating loss of lock).
+     *
+     * This is a mandatory value.
+     */
+    MTK_MNLD_GnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+    /**
+     * Accumulated delta range since the last channel reset in meters.
+     * A positive value indicates that the SV is moving away from the receiver.
+     *
+     * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+     * is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     *
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     * However, it is expected that the data is only accurate when:
+     *      'accumulated delta range state' == GPS_ADR_STATE_VALID.
+     */
+    double accumulated_delta_range_m;
+
+    /**
+     * 1-Sigma uncertainty of the accumulated delta range in meters.
+     * This value must be populated if 'accumulated delta range state' != GPS_ADR_STATE_UNKNOWN.
+     */
+    double accumulated_delta_range_uncertainty_m;
+
+    /**
+     * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+     * If the field is not set, the carrier frequency is assumed to be L1.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+     */
+    float carrier_frequency_hz;
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * Indications of possible cycle slips and resets in the accumulation of
+     * this value can be inferred from the accumulated_delta_range_state flags.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+     */
+    int64_t carrier_cycles;
+
+    /**
+     * The RF phase detected by the receiver, in the range [0.0, 1.0].
+     * This is usually the fractional part of the complete carrier phase measurement.
+     *
+     * The reference frequency is given by the field 'carrier_frequency_hz'.
+     * The value contains the 'carrier-phase uncertainty' in it.
+     *
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+     */
+    double carrier_phase;
+
+    /**
+     * 1-Sigma uncertainty of the carrier-phase.
+     * If the data is available, 'flags' must contain
+     * GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+     */
+    double carrier_phase_uncertainty;
+
+    /**
+     * An enumeration that indicates the 'multipath' state of the event.
+     *
+     * The multipath Indicator is intended to report the presence of overlapping
+     * signals that manifest as distorted correlation peaks.
+     *
+     * - if there is a distorted correlation peak shape, report that multipath
+     *   is GNSS_MULTIPATH_INDICATOR_PRESENT.
+     * - if there is not a distorted correlation peak shape, report
+     *   GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+     * - if signals are too weak to discern this information, report
+     *   GNSS_MULTIPATH_INDICATOR_UNKNOWN
+     *
+     * Example: when doing the standardized overlapping Multipath Performance
+     * test (3GPP TS 34.171) the Multipath indicator should report
+     * GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+     * contain multipath, and GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+     * signals that are tracked and do not contain multipath.
+     */
+    MTK_MNLD_GnssMultipathIndicator multipath_indicator;
+
+    /**
+     * Signal-to-noise ratio at correlator output in dB.
+     * If the data is available, 'flags' must contain GNSS_MEASUREMENT_HAS_SNR.
+     * This is the power ratio of the "correlation peak height above the
+     * observed noise floor" to "the noise RMS".
+     */
+    double snr_db;
+
+    /**
+       * Automatic gain control (AGC) level. AGC acts as a variable gain
+       * amplifier adjusting the power of the incoming signal. The AGC level
+       * may be used to indicate potential interference. When AGC is at a
+       * nominal level, this value must be set as 0. Higher gain (and/or lower
+       * input power) must be output as a positive number. Hence in cases of
+       * strong jamming, in the band of this signal, this value must go more
+       * negative.
+       */
+    double agc_level_db;
+} gnss_measurement;
+
+typedef struct {
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    gps_measurement measurements[GPS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    gps_clock clock;
+} gps_data;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    gnss_measurement measurements[MTK_MNLD_GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    gnss_clock clock;
+} gnss_data;
+
+typedef struct {
+    /**
+     * Pseudo-random number in the range of [1, 32]
+     * This is a Mandatory value.
+     */
+    int8_t prn;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a Mandatory value.
+     */
+    gps_nav_msg_type type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    nav_msg_status status;
+
+    /**
+     * Message identifier.
+     * It provides an index so the complete Navigation Message can be assembled. i.e. fo L1 C/A
+     * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+     * Subframe 1, 2, 3 does not contain a 'frame id' and this value can be set to -1.
+     */
+    short message_id;
+
+    /**
+     * Sub-message identifier.
+     * If required by the message 'type', this value contains a sub-index within the current
+     * message (or frame) that is being transmitted.
+     * i.e. for L1 C/A the submessage id corresponds to the sub-frame id of the navigation message.
+     */
+    short submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     * This is a Mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message.
+     * The bytes (or words) specified using big endian format (MSB first).
+     *
+     * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+     * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
+     */
+    char data[40];
+} gps_nav_msg;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+    /** set to sizeof(GnssNavigationMessage) */
+    size_t size;
+
+    /**
+     * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+     * This is a mandatory value.
+     */
+    int16_t svid;
+
+    /**
+     * The type of message contained in the structure.
+     * This is a mandatory value.
+     */
+    MTK_MNLD_GnssNavigationMessageType type;
+
+    /**
+     * The status of the received navigation message.
+     * No need to send any navigation message that contains words with parity error and cannot be
+     * corrected.
+     */
+    MTK_MNLD_NavigationMessageStatus status;
+
+    /**
+     * Message identifier. It provides an index so the complete Navigation
+     * Message can be assembled.
+     *
+     * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+     *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+     *   does not contain a 'frame id' and this value can be set to -1.)
+     *
+     * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+     *
+     * - For BeiDou D1, this refers to the frame number in the range of 1-24
+     *
+     * - For Beidou D2, this refers to the frame number, in the range of 1-120
+     *
+     * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+     *   number, in the range of 1-12
+     *
+     * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+     *   number in the range of 1-24
+     */
+    int16_t message_id;
+
+    /**
+     * Sub-message identifier. If required by the message 'type', this value
+     * contains a sub-index within the current message (or frame) that is being
+     * transmitted.
+     *
+     * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+     *   the subframe number of the navigation message, in the range of 1-5.
+     *
+     * - For Glonass L1 C/A, this refers to the String number, in the range from
+     *   1-15
+     *
+     * - For Galileo F/NAV, this refers to the page type in the range 1-6
+     *
+     * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+     */
+    int16_t submessage_id;
+
+    /**
+     * The length of the data (in bytes) contained in the current message.
+     * If this value is different from zero, 'data' must point to an array of the same size.
+     * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+     *
+     * This is a mandatory value.
+     */
+    size_t data_length;
+
+    /**
+     * The data of the reported GPS message. The bytes (or words) specified
+     * using big endian format (MSB first).
+     *
+     * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+     *   words. Each word (30 bits) should be fit into the last 30 bits in a
+     *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+     *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+     *
+     * - For Glonass L1 C/A, each string contains 85 data bits, including the
+     *   checksum.  These bits should be fit into 11 bytes, with MSB first (skip
+     *   B86-B88), covering a time period of 2 seconds.
+     *
+     * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+     *   excluded). Each word should be fit into 30-bytes, with MSB first (skip
+     *   B239, B240), covering a time period of 10 seconds.
+     *
+     * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+     *   a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+     *   into 29 bytes, with MSB first (skip B229-B232).
+     */
+    uint8_t* data;
+} gnss_nav_msg;
+
+#if 0
+void dump_gps_location(gps_location in);
+void dump_gnss_sv(gnss_sv in);
+void dump_gnss_sv_info(gnss_sv_info in);
+void dump_gps_data(gps_data in);
+void dump_gps_measurement(gps_measurement in);
+void dump_gps_clock(gps_clock in);
+void dump_gps_nav_msg(gps_nav_msg in);
+void dump_gnss_data(gnss_data in);
+void dump_gnss_measurement(gnss_measurement in);
+void dump_gnss_clock(gnss_clock in);
+void dump_gnss_nav_msg(gnss_nav_msg in);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h
new file mode 100644
index 0000000..34a275f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl2hal_interface.h
@@ -0,0 +1,89 @@
+#ifndef __MNL2HAL_INTERFACE_H__
+#define __MNL2HAL_INTERFACE_H__
+
+#include "hal_mnl_interface_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    void (*hal_reboot)();
+
+    void (*gps_init)();
+    void (*gps_start)();
+    void (*gps_stop)();
+    void (*gps_cleanup)();
+
+    void (*gps_inject_time)(int64_t time, int64_t time_reference, int uncertainty);
+    void (*gps_inject_location)(double lat, double lng, float acc);
+    void (*gps_delete_aiding_data)(int flags);
+    void (*gps_set_position_mode)(gps_pos_mode mode, gps_pos_recurrence recurrence,
+    int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode);
+
+    void (*data_conn_open)(const char* apn);
+    void (*data_conn_open_with_apn_ip_type)(const char* apn, apn_ip_type ip_type);
+    void (*data_conn_closed)();
+    void (*data_conn_failed)();
+
+    void (*set_server)(agps_type type, const char* hostname, int port);
+    void (*set_ref_location)(cell_type type, int mcc, int mnc, int lac, int cid);
+    void (*set_id)(agps_id_type type, const char* setid);
+
+    void (*ni_message)(char* msg, int len);
+    void (*ni_respond)(int notif_id, ni_user_response_type user_response);
+
+    void (*update_network_state)(int connected, network_type type, int roaming,
+        const char* extra_info);
+    void (*update_network_availability)(int available, const char* apn);
+
+    void (*set_gps_measurement)(bool enabled, bool enableFullTracking);
+    void (*set_gps_navigation)(bool enabled);
+    void (*set_vzw_debug)(bool enabled);
+    void (*update_gnss_config)(const char* config_data, int length);
+    //void (*set_sv_blacklist)(long long* blacklist, int size);
+	#if defined(__LINUX_OS__)
+    void (*send_pmtk)(char* msg, int len);
+    #endif
+} hal2mnl_interface;
+
+int mnl2hal_mnld_reboot();
+
+int mnl2hal_location(gps_location location);
+int mnl2hal_gps_status(gps_status status);
+int mnl2hal_gps_sv(gnss_sv_info sv);
+int mnl2hal_nmea(int64_t timestamp, const char* nmea, int length);
+int mnl2hal_gps_capabilities(gps_capabilites capabilities);
+int mnl2hal_gps_measurements(gps_data data);
+int mnl2hal_gps_navigation(gps_nav_msg msg);
+int mnl2hal_gnss_measurements(gnss_data data);
+int mnl2hal_gnss_navigation(gnss_nav_msg msg);
+
+
+int mnl2hal_request_wakelock();
+int mnl2hal_release_wakelock();
+
+int mnl2hal_request_utc_time();
+
+int mnl2hal_request_data_conn(struct sockaddr_storage addr);
+int mnl2hal_release_data_conn();
+int mnl2hal_request_ni_notify(int session_id, agps_notify_type type,
+    const char* requestor_id, const char* client_name, ni_encoding_type requestor_id_encoding,
+    ni_encoding_type client_name_encoding);
+int mnl2hal_request_set_id(request_setid flags);
+int mnl2hal_request_ref_loc(request_refloc flags);
+int mnl2hal_vzw_debug_screen_output(const char* str);
+int mnl2hal_update_gnss_name(const char* str, int len);
+int mnl2hal_request_nlp(bool type);
+
+// -1 means failure
+int hal2mnl_hdlr(int fd, hal2mnl_interface* hdlr);
+
+// -1 means failure
+int create_hal2mnl_fd();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl_common.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl_common.h
new file mode 100644
index 0000000..0914002
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnl_common.h
@@ -0,0 +1,209 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef _MNL_COMMON_H_
+#define _MNL_COMMON_H_
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#ifdef MTK_LOG_ENABLE
+#undef MTK_LOG_ENABLE
+#endif
+#define MTK_LOG_ENABLE 1
+
+#if defined(__ANDROID_OS__)
+#include <hardware/gps.h>
+#elif defined(__LINUX_OS__)
+#include "gps.h"
+#endif
+
+#include "mtk_gps_type.h"
+
+#define FLAG_HOT_START  0x0
+#define FLAG_WARM_START  MTK_GPS_DELETE_EPHEMERIS
+#define FLAG_COLD_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_POSITION)
+#define FLAG_FULL_START (MTK_GPS_DELETE_ALL)
+#define FLAG_AGPS_START (MTK_GPS_DELETE_ALL&(~MTK_GPS_DELETE_CLK))
+#define FLAG_DELETE_EPH_ALM_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_ALMANAC)
+#define FLAG_DELETE_TIME_START MTK_GPS_DELETE_TIME
+
+#define FLAG_AGPS_HOT_START  MTK_GPS_DELETE_RTI
+#define FLAG_AGPS_WARM_START  MTK_GPS_DELETE_EPHEMERIS
+#define FLAG_AGPS_COLD_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_POSITION | MTK_GPS_DELETE_TIME\
+                                 | MTK_GPS_DELETE_IONO | MTK_GPS_DELETE_UTC | MTK_GPS_DELETE_HEALTH)
+#define FLAG_AGPS_FULL_START MTK_GPS_DELETE_ALL
+#define FLAG_AGPS_AGPS_START (MTK_GPS_DELETE_EPHEMERIS | MTK_GPS_DELETE_ALMANAC | MTK_GPS_DELETE_POSITION\
+                                 | MTK_GPS_DELETE_TIME | MTK_GPS_DELETE_IONO | MTK_GPS_DELETE_UTC)
+
+// extern UINT32 assist_data_bit_map;
+/****************************************************************************** 
+ * Definition
+******************************************************************************/
+#define C_INVALID_PID  -1    /*invalid process id*/
+#define C_INVALID_TID  -1    /*invalid thread id*/
+#define C_INVALID_FD   -1    /*invalid file handle*/
+#define C_INVALID_SOCKET -1  /*invalid socket id*/
+#define C_INVALID_TIMER -1   /*invalid timer */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+#define PMTK_CONNECTION_SOCKET 1
+#define PMTK_CONNECTION_SERIAL 2
+/****************************************************************************** 
+ * Function Configuration
+******************************************************************************/
+#define READ_PROPERTY_FROM_FILE
+/******************************************************************************/
+
+/*enumeration for NEMA debug level*/
+typedef enum {
+    MNL_NMEA_DEBUG_NONE      = 0x0000,
+    MNL_NEMA_DEBUG_SENTENCE  = 0x0001,  /*only output sentence*/
+    MNL_NMEA_DEBUG_RX_PARTIAL    = 0x0002,
+    MNL_NMEA_DEBUG_RX_FULL   = 0x0004,
+    MNL_NMEA_DEBUG_TX_FULL   = 0x0008,
+    MNL_NMEA_DEBUG_STORAGE   = 0x0010,
+    MNL_NMEA_DEBUG_MESSAGE   = 0x0020,  /*mtk_sys_msg_send/mtk_sys_msg_recv*/
+
+    MNL_NMEA_DISABLE_NOTIFY  = 0x1000,
+    /*output sentence and brief RX data*/
+    MNL_NMEA_DEBUG_NORMAL        = MNL_NEMA_DEBUG_SENTENCE | MNL_NMEA_DEBUG_RX_PARTIAL,
+    /*output sentence and full RX/TX data*/
+    MNL_NMEA_DEBUG_FULL      = 0x00FF,
+} MNL_NMEA_DEBUG;
+
+typedef struct {
+    GpsUtcTime time;
+    int64_t timeReference;
+    int uncertainty;
+} ntp_context;
+
+typedef struct {
+    double latitude;
+    double longitude;
+    float accuracy;
+    struct timespec ts;
+    unsigned char  type;
+    unsigned char  started;
+} nlp_context;
+
+/*******************************************************************************/
+/* configruation property */
+typedef struct {
+    /*used by mnl_process.c*/
+    int init_speed;
+    int link_speed;
+    int debug_nmea;
+    int debug_mnl;
+    int pmtk_conn;          /*PMTK_CONNECTION_SOCKET | PMTK_CONNECTION_SERIAL*/
+    int socket_port;        /*PMTK_CONNECTION_SOCKET*/
+    char dev_dbg[32];       /*PMTK_CONNECTION_SERAIL*/
+    char dev_dsp[32];
+    char dev_gps[32];
+    char bee_path[32];
+    char epo_file[30];
+    char epo_update_file[30];
+    char qepo_file[30];
+    char qepo_update_file[30];
+    int delay_reset_dsp;    /*the delay time after issuing MTK_PARAM_CMD_RESET_DSP*/
+    int nmea2file;
+    int dbg2file;
+    int nmea2socket;
+    int dbg2socket;
+    UINT32 dbglog_file_max_size;  // The max size limitation of one debug log file
+    UINT32 dbglog_folder_max_size;  // The max size limitation of the debug log folder
+    char debug_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+
+    /*used by mnld.c*/
+    int timeout_init;
+    int timeout_monitor;
+    int timeout_wakeup;
+    int timeout_sleep;
+    int timeout_pwroff;
+    int timeout_ttff;
+
+    /*used by agent*/
+    int EPO_enabled;
+    int BEE_enabled;
+    int SUPL_enabled;
+    int SUPLSI_enabled;
+    int EPO_priority;
+    int BEE_priority;
+    int SUPL_priority;
+    int fgGpsAosp_Ver;
+
+    /*for FM TX*/
+    int AVAILIABLE_AGE;
+    int RTC_DRIFT;
+    int TIME_INTERVAL;
+    char u1AgpsMachine;
+    int ACCURACY_SNR;
+    int GNSSOPMode;
+    int OFFLOAD_enabled;
+    int OFFLOAD_testMode;
+    int OFFLOAD_switchMode;    //0: always offload mode  1: Offload/Host-base auto switch mode
+    int fix_interval;    /* fix interval in milliseconds */
+
+    /*for pps*/
+    int pps_mode;    /* 1PPS mode, Default: MTK_PPS_3D_FIX */
+    int pps_delay;    /* range: 0~2000 unit: ns */
+    int pps_polarity;    /* pps polarity, Range: 0~1, Default: 0,  0: pps active low  1: pps active high */
+    int pps_duty;       /* PPS pulse high duration (ms), Range: 0~2000, Default: 0 */
+    int elev_mask;      /* elevation angle mask in degree, Range: 0~90, Default: 5 */
+} MNL_CONFIG_T;
+/*---------------------------------------------------------------------------*/
+typedef struct {
+    time_t uSecond_start;
+    time_t uSecond_expire;
+}MNL_EPO_TIME_T;
+/*---------------------------------------------------------------------------*/
+typedef struct {
+    int notify_fd;
+    int port;
+} MNL_DEBUG_SOCKET_T;
+/*---------------------------------------------------------------------------*/
+#ifdef _MNL_COMMON_C_
+    #define C_EXT
+#else
+    #define C_EXT   extern
+#endif
+/*---------------------------------------------------------------------------*/
+C_EXT int  mnl_utl_load_property(MNL_CONFIG_T* prConfig);
+/*---------------------------------------------------------------------------*/
+#undef C_EXT
+/*---------------------------------------------------------------------------*/
+
+int str2int(const char*  p, const char*  end);
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld.h
new file mode 100644
index 0000000..230abfd
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld.h
@@ -0,0 +1,229 @@
+#ifndef __MNLD_H__
+#define __MNLD_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "mnl2hal_interface.h"
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MNLD_MAIN_SOCKET                "mnld_main_socket"
+#define MNLD_GPS_CONTROL_SOCKET         "mnld_gps_control_socket"
+#define MNLD_EPO_DOWNLOAD_SOCKET        "mnld_epo_download_socket"
+#define MNLD_QEPO_DOWNLOAD_SOCKET       "mnld_qepo_download_socket"
+#define MNLD_MTKNAV_DOWNLOAD_SOCKET     "mnld_mtknav_download_socket"
+#define MNLD_OP01_LOG_WRITER_SOCKET     "mnld_op01_log_write_socket"
+#define MNLD_TO_NLP_UTILS_SOCKET        "mtk_mnld2nlputils"
+#ifdef CONFIG_GPS_MT3303
+#define MNLD_MT3333_CONTROLLER_SOCKET     "mnld_mt3333_controller_socket"
+#endif
+
+#ifdef MTK_ADR_SUPPORT
+#define MNLD_MPE_SOCKET                 "mnl2adr_socket"
+#else
+#define MNLD_MPE_SOCKET                 "mnld_mpe_socket"
+#endif
+#define META_TO_MNLD_SOCKET             "mtk_meta2mnld"
+#define DEBUG_TO_MNLD_SOCKET            "mtk_debugService2mnld"
+#define MNLD_TO_DEBUG_SOCKET            "mtk_mnld2debugService"
+
+#define NLP_REQUEST_SRC_MNL             (1 << 0)
+#define NLP_REQUEST_SRC_APM             (1 << 1)
+
+#if defined(__ANDROID_OS__)
+#define MNLD_OP01_LOG_PATH              "/sdcard/GPS.LOG"
+#else
+#define MNLD_OP01_LOG_PATH              "GPS.LOG"
+#endif
+
+#define MNLD_MAIN_HANDLER_TIMEOUT       (30 * 1000)
+#define MNLD_GPS_HANDLER_TIMEOUT        (30 * 1000)
+#define MNLD_EPO_HANDLER_TIMEOUT        (120 * 60 * 1000)
+#define MNLD_EPO_RETRY_HANDLER_TIMEOUT  (30 * 1000)
+#define MNLD_QEPO_HANDLER_TIMEOUT       (120 * 60 * 1000)
+#define MNLD_OP01_HANDLER_TIMEOUT       (20 * 1000)
+#define MNLD_MPE_HANDLER_TIMEOUT        (30 * 1000)
+#define MNLD_GPS_START_TIMEOUT          (35 * 1000)
+#define MNLD_GPS_STOP_TIMEOUT           (30 * 1000)
+#define MNLD_GPS_RESET_TIMEOUT          (30 * 1000)
+#define MNLD_GPS_NMEA_DATA_TIMEOUT      (5 * 1000)
+#define MNLD_GPS_LOG_HANDLER_TIMEOUT    (60 * 1000)
+#define MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT (30 * 1000)
+
+#define MNLD_INTERNAL_BUFF_SIZE         (8 * 1024)
+#define MNLD_TO_APP_BUFF_SIZE           (1023)
+
+
+typedef enum {
+    MNLD_GPS_STATE_IDLE         = 0,
+    MNLD_GPS_STATE_STARTING     = 1,
+    MNLD_GPS_STATE_STARTED      = 2,
+    MNLD_GPS_STATE_STOPPING     = 3,
+    MNLD_GPS_STATE_OFL_STARTING = 4,
+    MNLD_GPS_STATE_OFL_STARTED  = 5,
+    MNLD_GPS_STATE_OFL_STOPPING = 6,
+} mnld_gps_state;
+
+typedef enum {
+    GPS_EVENT_START         = 0,
+    GPS_EVENT_STOP          = 1,
+    GPS_EVENT_RESET         = 2,
+    GPS_EVENT_START_DONE    = 3,
+    GPS_EVENT_STOP_DONE     = 4,
+    GPS_EVENT_OFFLOAD_START = 5,
+} mnld_gps_event;
+
+typedef enum {
+    GPS2MAIN_EVENT_START_DONE               = 0,
+    GPS2MAIN_EVENT_STOP_DONE                = 1,
+    GPS2MAIN_EVENT_RESET_DONE               = 2,
+    GPS2MAIN_EVENT_NMEA_TIMEOUT             = 3,
+    GPS2MAIN_EVENT_UPDATE_LOCATION          = 4,
+    EPO2MAIN_EVENT_EPO_DONE                 = 5,
+    QEPO2MAIN_EVENT_QEPO_DONE               = 6,
+    QEPO2MAIN_EVENT_QEPO_BD_DONE            = 7,
+    MTKNAV2MAIN_EVENT_MTKNAV_DONE           = 8,
+    QEPO2MAIN_EVENT_QEPO_GA_DONE            = 9,
+    GPS2MAIN_EVENT_OUTPUT_DATA              = 10,
+} main_internal_event;
+
+typedef enum {
+    DATA_DEBUG2APP               = 0,
+    DATA_ENDLIST
+} main_out_put_data_type;
+
+typedef enum {
+    EPO_DOWNLOAD_RESULT_SUCCESS          = 0,
+    EPO_DOWNLOAD_RESULT_NO_UPDATE        = 1,
+    EPO_DOWNLOAD_RESULT_FAIL             = -1,
+    EPO_DOWNLOAD_RESULT_RETRY_TOO_MUCH   = -2,
+} epo_download_result;
+
+typedef enum {
+    EPO_MD5_FILE_UPDATED                = 0,
+    EPO_MD5_FILE_NO_UPDATE              = 1,
+    EPO_MD5_DOWNLOAD_RESULT_FAIL        = -1,
+} epo_md5_download_result;
+
+typedef struct {
+    int fd_hal;
+    int fd_agps;
+    int fd_flp;
+    int fd_flp_test;
+    int fd_geofence;
+    int fd_at_cmd;
+    int fd_int;
+    int fd_mtklogger;
+    int fd_mtklogger_client;
+    int fd_meta;
+    int fd_debug;
+    mtk_socket_fd fd_nlp_utils;
+    mtk_socket_fd fd_debug_client;
+} mnld_fds;
+
+typedef struct {
+    bool        gps_used;
+    bool        need_open_ack;
+    bool        need_close_ack;
+    bool        need_reset_ack;
+} mnld_gps_client;
+
+typedef struct {
+    mnld_gps_client     hal;
+    mnld_gps_client     agps;
+    mnld_gps_client     flp;
+    mnld_gps_client     flp_test;
+    mnld_gps_client     geofence;
+    mnld_gps_client     at_cmd_test;
+    mnld_gps_client     factory;
+} mnld_gps_clients;
+
+typedef struct {
+    mnld_gps_clients    clients;
+    mnld_gps_state      gps_state;
+    bool                is_gps_init;
+    bool                is_gps_meas_enabled;
+    bool                is_gps_navi_enabled;
+    int                 delete_aiding_flag;
+
+    timer_t             timer_start;
+    timer_t             timer_stop;
+    timer_t             timer_reset;
+    timer_t             timer_nmea_monitor;
+    timer_t             timer_switch_ofl_mode;
+
+    time_t              gps_start_time;
+    time_t              gps_stop_time;
+    time_t              gps_ttff;
+    bool                wait_first_location;
+} mnld_gps_status;
+
+typedef struct {
+    bool            is_network_connected;
+    bool            is_wifi_connected;
+    bool            is_epo_downloading;
+} mnl_epo_status;
+
+typedef struct {
+    mnld_fds            fds;
+    mnld_gps_status     gps_status;
+    mnl_epo_status      epo_status;
+} mnld_context;
+
+// GPS Control -> MAIN
+int sys_gps_mnl_data2mnld_callback(const char *data, unsigned int length);
+void mnld_gps_output_data_handle(char* buff, int off_set);
+int mnld_gps_start_done(bool is_assist_req);
+int mnld_gps_stop_done();
+int mnld_gps_reset_done();
+int mnld_gps_update_location(gps_location location);
+
+// EPO Download -> MAIN
+int mnld_epo_download_done(epo_download_result result);
+int mnld_qepo_download_done(epo_download_result result);
+int mnld_mtknav_download_done(epo_download_result result);
+int mnld_qepo_bd_download_done(epo_download_result result);
+int mnld_qepo_ga_download_done(epo_download_result result);
+
+void hal_start_gps_trigger_epo_download();
+bool is_network_connected();
+bool is_wifi_network_connected();
+
+// Provided for GPS Control to check the status
+bool mnld_is_gps_started();
+bool mnld_is_gps_or_ofl_started();
+bool mnld_is_gps_started_done();
+bool mnld_is_gps_or_ofl_started_done();
+bool mnld_is_gps_meas_enabled();
+bool mnld_is_gps_navi_enabled();
+bool mnld_is_gps_stopped();
+bool mnld_is_gps_and_ofl_stopped();
+bool mnld_is_epo_download_finished();
+
+int mnld_gps_controller_mnl_nmea_timeout(void);
+int mnld_gps_start_nmea_monitor(void);
+int mnld_gps_stop_nmea_monitor(void);
+void gps_mnld_restart_mnl_process(void);
+void mnld_gps_request_nlp(int src);
+
+int mtk_gps_get_gps_user(void);
+
+void factory_mnld_gps_start(void);
+void factory_mnld_gps_stop(void);
+
+void flp_test2mnl_gps_start(void);
+void flp_test2mnl_gps_stop(void);
+
+int is_flp_user_exist();
+int is_geofence_user_exist();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld_utile.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld_utile.h
new file mode 100644
index 0000000..93e2a89
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mnld_utile.h
@@ -0,0 +1,254 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+ #define PMTK_MAX_PKT_LENGTH     256
+ #define MNL_GPS_DATA_PATH_MAX_LENGTH 256
+
+/*****************************************************************************
+ * FUNCTION
+ *  power_on_3332
+ * DESCRIPTION
+ *  power on MT3332 chip for chip detector.
+ * PARAMETERS
+ *  
+ * RETURNS
+ *  
+ *****************************************************************************/
+void power_on_3332();
+
+/*****************************************************************************
+ * FUNCTION
+ *  power_off_3332
+ * DESCRIPTION
+ *  power off MT3332 chip when chip detect done.
+ * PARAMETERS
+ *  
+ * RETURNS
+ *  
+ *****************************************************************************/
+void power_off_3332();
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  read_NVRAM
+ * DESCRIPTION
+ *  Read NVRAM to check if the uart is for MT3332
+ * PARAMETERS
+ *  
+ * RETURNS
+ *  1: NOT mt3332, -1: read error, 0:read ok
+ *****************************************************************************/
+int read_NVRAM();
+
+/*****************************************************************************
+ * FUNCTION
+ *  init_3332_interface
+ * DESCRIPTION
+ *  Init UART parameter.
+ * PARAMETERS
+ *  fd [IN]: UART fd
+ * RETURNS
+ *  success(0); failure (-1)
+ *****************************************************************************/
+int init_3332_interface(const int fd);
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  hw_test_3332
+ * DESCRIPTION
+ *  Send command to MT3332 Chip and wait response to check if it is MT3332 CHIP
+ * PARAMETERS
+ *  fd [IN]: UART fd
+ * RETURNS
+ * 0: means MT3332, 1 means not MT3332
+ *****************************************************************************/
+int hw_test_3332(const int fd);
+
+/*****************************************************************************
+ * FUNCTION
+ *  hand_shake
+ * DESCRIPTION
+ *  Hand shake with MT3332 chip
+ * PARAMETERS
+ *  
+ * RETURNS
+ * 0: means MT3332, 1 means not MT3332
+ *****************************************************************************/
+int hand_shake();
+
+/*****************************************************************************
+ * FUNCTION
+ *  confirm_if_3332
+ * DESCRIPTION
+ *  confirm if it is MT3332
+ * PARAMETERS
+ *  
+ * RETURNS
+ * 0: means MT3332, 1 means not MT3332
+ *****************************************************************************/
+int confirm_if_3332();
+
+/*****************************************************************************
+ * FUNCTION
+ *  chip_detector
+ * DESCRIPTION
+ *  To get GPS chip ID
+ * PARAMETERS
+ *  
+ * RETURNS
+ * 
+ *****************************************************************************/
+void chip_detector();
+// confirm MT3332 chip - end
+
+/*****************************************************************************
+ * FUNCTION
+ *  buff_get_int
+ * DESCRIPTION
+ *  To get a INT data from buff.
+ * PARAMETERS
+ *  buff [IN]: Store INT data
+ *  offset [IN]: offset
+ * RETURNS
+ * 
+ *****************************************************************************/
+int buff_get_int(char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  buff_put_int
+ * DESCRIPTION
+ *  To put a INT data to a buff.
+ * PARAMETERS
+ *  input [IN]: Input data
+ *  buff [IN]: Dest buffer
+ *  offset [IN]: offset
+ * RETURNS
+ * 
+ *****************************************************************************/
+void buff_put_int(int input, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  buff_put_string
+ * DESCRIPTION
+ *  To put CHAR data to a buff.
+ * PARAMETERS
+ *  str [IN]: Input data
+ *  buff [IN]: Dest buffer
+ *  offset [IN]: offset
+ * RETURNS
+ * 
+ *****************************************************************************/
+void buff_put_string(char* str, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  buff_put_struct
+ * DESCRIPTION
+ *  To put struct data to a buff.
+ * PARAMETERS
+ *  input [IN]: Input data
+ *  size  [IN]: Input struct size
+ *  buff [IN]: Dest buffer
+ *  offset [IN]: offset
+ * RETURNS
+ * 
+ *****************************************************************************/
+void buff_put_struct(void* input, int size, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  buff_get_struct
+ * DESCRIPTION
+ *  To get struct data from a buff.
+ * PARAMETERS
+ *  input [OUT]: Dest buffer
+ *  size  [IN]: The length to get
+ *  buff [IN]: Original buffer
+ *  offset [IN]: offset
+ * RETURNS
+ * 
+ *****************************************************************************/
+void buff_get_struct(char* output, int size, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  buff_get_binary
+ * DESCRIPTION
+ *  To get binary data from a buff.
+ * PARAMETERS
+ *  output [OUT]: Dest buffer
+ *  buff  [IN]: Original buffer
+ *  offset [IN]: offset
+ * RETURNS
+ * 
+ *****************************************************************************/
+int buff_get_binary(void* output, char* buff, int* offset);
+
+/*****************************************************************************
+ * FUNCTION
+ *  add_chksum
+ * DESCRIPTION
+ *  To add checksum in a buff 
+ *  buff  [IN]: buffer
+ * RETURNS
+ * 
+ *****************************************************************************/
+int add_chksum(char *pBuf);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_log_is_hide
+ * DESCRIPTION
+ *  To check hide the gps log or not 
+ *  buff  [IN]: void
+ * RETURNS
+ *  0: Print GPS log normally; 1: hide location sensitivity log;
+ *****************************************************************************/
+int mtk_gps_log_is_hide(void);
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnl_init_gps_data_path
+ * DESCRIPTION
+ *  To create all levels of the appointed path
+ *  data_path  [IN]: the full path
+ *  length     [IN]: the length of the path
+ * RETURNS
+ *  0: Create all levels successed; -1: Failed to create path;
+ *****************************************************************************/
+int mnl_init_gps_data_path(const char* data_path, const int length);
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mpe.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mpe.h
new file mode 100644
index 0000000..cc8929d
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mpe.h
@@ -0,0 +1,24 @@
+#ifndef __MPE_H__
+#define __MPE_H__
+
+#include "mtk_gps_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int mpe_function_init(int self_recv);
+int mnl_mpe_thread_init();
+int mnl2mpe_set_log_path(char* path, int status_flag, int mode_flag);
+int mnl2adr_gps_open(void);
+int mnl2adr_gps_close(void);
+int mnl2adr_mnl_reboot(void);
+int mnl2adr_open_gps_done(void);
+int mnl2adr_close_gps_done(void);
+int mnl2adr_send_nmea_data(const char * nmea_buffer, const UINT32 length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mt3333_controller.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mt3333_controller.h
new file mode 100644
index 0000000..dba8c34
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mt3333_controller.h
@@ -0,0 +1,76 @@
+#ifndef __MT3333_CONTROLLER_H__
+#define __MT3333_CONTROLLER_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "mtk_gps.h"
+#include "mtk_auto_log.h"
+
+#if defined(__ANDROID_OS_10__) || defined(CONFIG_GPS_MT3303_TTYS1)
+#define  MT3333_CONTROLLER_TTY_NAME       "/dev/ttyS1"
+#else
+#define  MT3333_CONTROLLER_TTY_NAME       "/dev/ttyS2"
+#endif
+
+typedef enum {
+    MAIN_MT3333_CONTROLLER_EVENT_GPSREBOOT,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSENABLE,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSSTART,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSSTOP,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSDISABLE,
+    MAIN_MT3333_CONTROLLER_EVENT_GPSDELETEAIDING,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUES1STNMEA,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTNTP,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTNLP,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTEPO,
+    MAIN_MT3333_CONTROLLER_EVENT_REQUESTQEPO,
+    MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEBUGLOG,
+    MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEBUGLOG,
+    MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND,
+    MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA,
+    MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEASYMODE,
+    MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEASYMODE,
+    MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF,
+    MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM,
+    MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL,
+    MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG,
+#ifdef MTK_ADR_SUPPORT
+    MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF,
+#endif
+} main_mt3333_controller_event;
+
+int mt3333_controller_Utc2GpsTime(unsigned short* pi2Wn, unsigned int* pdfTow, unsigned int* sys_time);
+
+int mt3333_controller_init() ;
+int mt3333_controller_delete_aiding_data(int flags);
+
+int mt3333_controller_inject_location(double latitude, double longitude, float accuracy);
+
+int mt3333_controller_inject_time(int64_t time, int64_t timeReference, int uncertainty);
+int mt3333_controller_inject_epo(int qepo);
+
+int mt3333_controller_socket_send_cmd(main_mt3333_controller_event cmd);
+
+void* mt3333_thread_control(void *arg);
+void* mt3333_thread_data(void *arg);
+void* mt3333_thread_data_debug( void*  arg );
+
+int mt3333_controller_set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits);
+int mt3333_controller_set_gnss_working_satellite_system(MTK_GNSS_CONFIGURATION gnssmode);
+int mt3333_controller_set_gnss_position_fix_interval(int fix_interval);
+int mt3333_controller_set_pps_config(int pps_mode, int pps_duty);
+
+int mt3333_controller_check_uart_baudrate(void);
+int mt3333_controller_check_if_gpsfunctionok(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mtknav.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mtknav.h
new file mode 100644
index 0000000..a818666
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/mtknav.h
@@ -0,0 +1,31 @@
+#ifndef __MTKNAV_H__
+#define __MTKNAV_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MTKNAV_DL_RETRY_TIME   3
+#define MTKNAV_MD5_FILE     MTK_GPS_DATA_PATH"MTKNAV.MD5"
+#define MTKNAV_MD5_FILE_HAL MTK_GPS_DATA_PATH"MTKNAVHAL.MD5"
+#define MTKNAV_DAT_FILE     MTK_GPS_DATA_PATH"MTKNAV.DAT"
+#define MTKNAV_DAT_FILE_HAL MTK_GPS_DATA_PATH"MTKNAVHAL.DAT"
+
+extern bool mtknav_update_flag;
+extern int mtknav_res;
+
+int mtknav_downloader_init();
+
+int mtknav_downloader_start();
+
+void mtknav_update_mtknav_file(int mtknav_valid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/nmea_parser.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/nmea_parser.h
new file mode 100644
index 0000000..518944a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/nmea_parser.h
@@ -0,0 +1,111 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __NMEA_PARSER_H__
+#define __NMEA_PARSER_H__
+
+#include "hal_mnl_interface_common.h"
+#include "mnl_common.h"
+
+// for different SV parse
+typedef enum {
+    UNKNOWN_SV = 0,
+    GPS_SV,
+    SBAS_SV,
+    GLONASS_SV,
+    QZSS_SV,
+    BDS_SV,
+    GALILEO_SV,
+} SV_TYPE;
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****       N M E A   P A R S E R                           *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+#define  NMEA_MAX_SIZE  255
+/*maximum number of SV information in GPGSV*/
+#define  NMEA_MAX_SV_INFO 4
+#define  LOC_FIXED(pNmeaReader) ((pNmeaReader->fix_mode == 2) || (pNmeaReader->fix_mode ==3))
+typedef struct {
+    int     pos;
+    int     overflow;
+    int     utc_year;
+    int     utc_mon;
+    int     utc_day;
+    int     utc_diff;
+    gps_location  fix;
+
+    /*
+     * The fix flag extracted from GPGSA setence: 1: No fix; 2 = 2D; 3 = 3D
+     * if the fix mode is 0, no location will be reported via callback
+     * otherwise, the location will be reported via callback
+     */
+    int     fix_mode;
+    /*
+     * Indicate that the status of callback handling.
+     * The flag is used to report GPS_STATUS_SESSION_BEGIN or GPS_STATUS_SESSION_END:
+     * (0) The flag will be set as true when callback setting is changed via nmea_reader_set_callback
+     * (1) GPS_STATUS_SESSION_BEGIN: receive location fix + flag set + callback is set
+     * (2) GPS_STATUS_SESSION_END:   receive location fix + flag set + callback is null
+     */
+    int     cb_status_changed;
+    int     sv_count;           /*used to count the number of received SV information*/
+    gnss_sv_info  sv_status;
+    // GpsCallbacks callbacks;
+    char    in[ NMEA_MAX_SIZE+1 ];
+} NmeaReader;
+
+typedef struct {
+    const char*  p;
+    const char*  end;
+} Token;
+
+#define  MAX_NMEA_TOKENS  64
+
+typedef struct {
+    int     count;
+    Token   tokens[ MAX_NMEA_TOKENS ];
+} NmeaTokenizer;
+
+void nmea_reader_addc(NmeaReader* const r, int   c);
+void mtk_mnl_nmea_parser_process(const char * buffer, UINT32 length);
+extern int op01_log_write_internal(const char* log);
+int get_gps_nmea_parser_end_status();
+void nmea_reader_init(NmeaReader* const r);
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/op01_log.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/op01_log.h
new file mode 100644
index 0000000..fca0fde
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/op01_log.h
@@ -0,0 +1,22 @@
+#ifndef __OP01_LOG_H__
+#define __OP01_LOG_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int op01_log_init();
+
+int op01_log_gps_start();
+int op01_log_gps_stop();
+int op01_log_gps_location(double lat, double lng, int ttff);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/inc/qepo.h b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/qepo.h
new file mode 100644
index 0000000..c32d998
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/inc/qepo.h
@@ -0,0 +1,62 @@
+#ifndef __QEPO_H__
+#define __QEPO_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define QEPO_FILE                    MTK_GPS_DATA_PATH"QEPO.DAT"
+#define QEPO_UPDATE_FILE             MTK_GPS_DATA_PATH"QEPOTMP.DAT"
+#define QEPO_BD_FILE                 MTK_GPS_DATA_PATH"QEPO_BD.DAT"
+#define QEPO_BD_UPDATE_FILE          MTK_GPS_DATA_PATH"QEPOTMP_BD.DAT"
+#define QEPO_GA_FILE                 MTK_GPS_DATA_PATH"QEPO_GA.DAT"
+#define QEPO_GA_UPDATE_FILE          MTK_GPS_DATA_PATH"QEPOTMP_GA.DAT"
+#define QEPO_UPDATE_HAL              MTK_GPS_DATA_PATH"QEPOHAL.DAT"
+#define QEPO_BD_UPDATE_HAL           MTK_GPS_DATA_PATH"QEPO_BD_HAL.DAT"
+#define QEPO_BD_HAS_EPO_BIT_MASK     (0x00000001)
+#define MTK_QEPO_BD_HEADER_SIZE     72
+#define QEPO_BD_DL_RETRY_TIME   3
+#define QEPO_GA_UPDATE_HAL           MTK_GPS_DATA_PATH"QEPO_GA_HAL.DAT"
+#define QEPO_GA_HAS_EPO_BIT_MASK     (0x00000001)
+#define MTK_QEPO_GA_HEADER_SIZE     72
+#define QEPO_GA_DL_RETRY_TIME   3
+#define QEPO_GR_DL_RETRY_TIME   3
+
+extern bool qepo_update_flag;
+extern int qepo_dl_res;
+extern bool qepo_BD_update_flag;
+extern int qepo_bd_dl_res;
+extern bool qepo_GA_update_flag;
+extern int qepo_ga_dl_res;
+
+int qepo_downloader_init();
+
+int qepo_downloader_start();
+
+int qepo_bd_downloader_start();
+
+int qepo_ga_downloader_start();
+
+int is_qepo_download_finished();
+
+int is_qepo_bd_download_finished();
+
+int is_qepo_ga_download_finished();
+
+void qepo_update_quarter_epo_file(int qepo_valid);
+
+void qepo_update_quarter_epo_bd_file(int qepo_bd_valid);
+
+void qepo_update_quarter_epo_ga_file(int qepo_ga_valid);
+
+void gps_mnl_set_gps_time(int wn, int tow, int sys_time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/epo.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/epo.c
new file mode 100644
index 0000000..92f601b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/epo.c
@@ -0,0 +1,1867 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#include <errno.h>   /* Error number definitions */
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <openssl/md5.h>
+#include <inttypes.h>
+
+#include "agps_agent.h"
+#include "data_coder.h"
+#include "mnl_common.h"
+#include "mnld.h"
+#include "mtk_lbs_utility.h"
+#include "epo.h"
+#include "qepo.h"
+#include "curl.h"
+#include "easy.h"
+#include "gps_controller.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "epo"
+#endif
+
+/*smart_phone*/
+//#define EPO_URL_1 "https://ogepodownload.mediatek.com/"
+//#define EPO_URL_2 "https://oepodownload.mediatek.com/"
+#define EPO_URL_1 "https://aepodownload.mediatek.com/"
+#define EPO_URL_2 "https://aepodownload.mediatek.com/"
+
+#define MTK_EPO_MAX_DAY      30
+#define MTK_EPO_DEFAULT_DL_DAY  3
+//#define MTK_EPO_ONE_SV_SIZE  72 //Move to epo.h
+#define GPS_CONF_FILE_SIZE 100
+#define EPO_CONTROL_FILE_PATH MTK_GPS_DATA_PATH"gps.conf"
+#define IS_SPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+#define MTK_EPO_SET_GPS_SVNum  32
+#define MTK_EPO_SET_GLO_SVNum  24
+#define MTK_EPO_SET_GPS_MAX_SIZE (72*MTK_EPO_SET_GPS_SVNum)  //72*32, One SET
+#define MTK_EPO_SET_GLO_MAX_SIZE (72*MTK_EPO_SET_GLO_SVNum)  //72*24, One SET
+#define MTK_EPO_SET_GPS_GLO_MAX_SIZE (MTK_EPO_SET_GPS_MAX_SIZE + MTK_EPO_SET_GLO_MAX_SIZE)  //72*(32+24), One SET for GPS+GLO
+#define MTK_EPO_MD5_STR_LEN (MD5_DIGEST_LENGTH*2+1)
+#define MTK_EPO_READ_BUFSIZE (72*56)
+
+//static int epo_data_updated = 0;
+static int gps_epo_period = 3;
+static int wifi_epo_period = 3;
+#ifndef CONFIG_GPS_MT3303
+static int gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+#else
+int gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+#endif
+static int gps_epo_download_piece = 1;
+static int gps_epo_enable = 0;
+static int gps_epo_wifi_trigger = 0;
+static int gps_epo_file_count = 0;
+static char gps_epo_file_name[GPS_EPO_FILE_LEN] = {0};
+static char gps_epo_MD5_file_name[GPS_EPO_FILE_LEN] = {0};
+int gps_epo_type = 0;    // 0 for G+G;1 for GPS only, default is G+G
+//static int epo_download_failed = 0;
+static int epo_download_retry = 1;
+static timer_t retry_download_timer;
+//static timer_t hdlr_timer;
+static EPO_Status_T epo_status = {
+    .last_DL_Date = -1,
+    .today_retry_time = 0,
+};
+
+static int mtk_epo_is_expired(int wifi_tragger);
+static void gps_download_epo_file_name(int count);
+static int mtk_gps_epo_file_time_hal(time_t uTime[]);
+int mtk_gps_epo_gen_md5_str(FILE *f, char *md_str, unsigned int str_len);
+int mtk_gps_epo_md5_match_check(char *file_epo, char *file_md5);
+int mtk_gps_md5_hex2str(unsigned char *md, char *md_str, unsigned int str_len);
+CURLcode curl_easy_download_epo_DAT(void);
+
+CURLcode curl_easy_download_epo_MD5(void);
+
+typedef enum {
+    MAIN2EPO_EVENT_START            = 0,
+} main2epo_event;
+
+typedef enum
+{
+  MTK_EPO_GPS_GLO = 0,
+  MTK_EPO_GPS,
+  MTK_EPO_END
+} MTK_EPO_TYPE;
+
+static int g_fd_epo;
+
+/////////////////////////////////////////////////////////////////////////////////
+// static functions
+static MTK_FILE EPO_File_Open (const char *szFileName, MTK_INT32 i4Mode)
+{
+    FILE *fp;
+    char szMode[4];
+
+    // For system which treats binary mode and text mode differently,
+    // such as Windows / DOS, please make sure to open file in BINARY mode
+
+    switch (i4Mode)
+    {
+    case MTK_FS_READ:       // 0
+        sprintf(szMode, "rb");
+        break;
+    case MTK_FS_WRITE:      // 1
+        sprintf(szMode, "wb");
+        break;
+    case MTK_FS_APPEND:     // 2
+        sprintf(szMode, "ab");
+        break;
+    case MTK_FS_RW:         // 3
+        sprintf(szMode, "r+b");
+        break;
+    case MTK_FS_RW_DISCARD: // 4
+        sprintf(szMode, "w+b");
+        break;
+    case MTK_FS_RW_APPEND:  // 5
+        sprintf(szMode, "a+b");
+        break;
+    default:
+        return 0;
+    }
+
+    fp = fopen(szFileName, szMode);
+
+    if (fp != NULL)
+    {
+        return (MTK_FILE)fp;
+    }
+
+    return 0;
+}
+
+static void EPO_File_Close (MTK_FILE hFile)
+{
+    fclose((FILE *)hFile);
+}
+
+static MTK_UINT32 EPO_File_Read (MTK_FILE hFile, void *DstBuf, MTK_UINT32 u4Length)
+{
+    if (hFile != 0)
+    {
+        return (MTK_UINT32)fread(DstBuf, 1, u4Length, (FILE *)hFile);
+    }
+
+    return 0;
+}
+
+#ifndef CONFIG_GPS_MT3303
+void epo_update_epo_file() {
+    unlink(EPO_FILE);
+    if (mtk_agps_agent_epo_file_update() == MTK_GPS_ERROR) {
+        LOGE("EPO file updates fail\n");
+    } else {
+        unlink(EPO_UPDATE_HAL);
+    }
+}
+#else
+void epo_update_epo_file() {
+    
+}
+time_t epo_get_now_time(){
+	return time(NULL);
+}
+#endif
+
+int mtk_gps_epo_md5_match_check(char *file_epo, char *file_md5)
+{
+    FILE *fp_epo = NULL, *fp_md5 = NULL;
+    char md5_data[MTK_EPO_MD5_STR_LEN] = {0};
+    unsigned char gen_md5_str[MTK_EPO_MD5_STR_LEN] = {0};
+    int read_len = 0;
+
+    if(file_epo == NULL || file_md5 == NULL)
+    {
+        return MTK_GPS_ERROR;
+    }
+
+    fp_epo = fopen(file_epo, "r");
+    if (fp_epo == NULL)
+    {
+        LOGE("epo file(%s) open fail(%s).", file_epo, strerror(errno));
+        return MTK_GPS_ERROR;
+    }
+    if (mtk_gps_epo_gen_md5_str(fp_epo, (char *)gen_md5_str, MTK_EPO_MD5_STR_LEN) == MTK_GPS_ERROR) {
+        LOGE("Gen md5 str failed");
+        fclose(fp_epo);
+        return MTK_GPS_ERROR;
+    }
+    fclose(fp_epo);
+
+    fp_md5 = fopen(file_md5, "r");
+    if(fp_md5 == NULL)
+    {
+        LOGE("md5 file(%s) open fail(%s).", file_md5, strerror(errno));
+        return MTK_GPS_ERROR;
+    }
+    read_len = fread(md5_data, 1, sizeof(md5_data), fp_md5);
+    md5_data[MTK_EPO_MD5_STR_LEN - 1] = '\0';
+    fclose(fp_md5);
+    if (read_len <= 0) {
+        return MTK_GPS_ERROR;
+    }
+
+    if(strncmp((const char *)gen_md5_str, (const char *)md5_data, MTK_EPO_MD5_STR_LEN-1) == 0)
+    {
+        return MTK_GPS_SUCCESS;
+    }else{
+        LOGW("Gen:%s, MD5File:%s", gen_md5_str, md5_data);
+        return MTK_GPS_ERROR;
+    }
+}
+
+int mtk_gps_epo_gen_md5_str(FILE *f, char *md_str, unsigned int str_len)
+{
+    MD5_CTX c;
+    int read_len;
+    unsigned char buf[MTK_EPO_READ_BUFSIZE] = {0};
+    char md5[MD5_DIGEST_LENGTH] = {0};
+    int i;
+
+    if (f == NULL || md_str == NULL) {
+        //LOGE("NULL pointer: f=0x%08x, md_str=0x%08x", f, md_str);
+        LOGE("NULL pointer");
+        return MTK_GPS_ERROR;
+    }
+
+    if(str_len < MTK_EPO_MD5_STR_LEN)
+    {
+        LOGE("str_len: %d", str_len);
+        return MTK_GPS_ERROR;
+    }
+
+    MD5_Init(&c);
+    do
+    {
+        read_len = fread(buf, 1, MTK_EPO_READ_BUFSIZE, f);
+        if (read_len <= 0) break;
+        MD5_Update(&c,buf,(unsigned long)read_len);
+    }while(read_len > 0);
+    MD5_Final((uint8_t *)&(md5[0]),&c);
+
+    for (i=0; i<MD5_DIGEST_LENGTH; i++)
+    {
+        snprintf(&(md_str[i*2]), 3, "%02x", md5[i]);
+    }
+    md_str[i*2] = '\0';
+
+    return MTK_GPS_SUCCESS;
+}
+
+int mtk_gps_md5_hex2str(unsigned char *md, char *md_str, unsigned int str_len)
+{
+    int i;
+
+    if(str_len < MTK_EPO_MD5_STR_LEN)
+    {
+        LOGE("str_len: %d", str_len);
+        return MTK_GPS_ERROR;
+    }
+
+    for (i=0; i<MD5_DIGEST_LENGTH; i++)
+    {
+        snprintf(&(md_str[i*2]), 3, "%02x", md[i]);
+    }
+    md_str[i*2] = '\0';
+
+    return MTK_GPS_SUCCESS;
+}
+
+static int epo_md5_update_retry(int retry_time) {
+    UNUSED(retry_time);
+    int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    if (mnld_is_gps_or_ofl_started() || (is_wifi_network_connected())) {
+        if (is_network_connected()) {
+            //LOGW("download epo MD5 file failed, retry resume after 10s.(times:%d)", retry_time);
+            usleep(10*1000*1000);
+            if (curl_easy_download_epo_MD5() == CURLE_OK) {
+                ret = EPO_MD5_FILE_UPDATED;
+            } else {
+                ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+            }
+        } else {
+            //LOGW("download epo MD5 file failed, no network connected, retry times:%d", retry_time);
+        }
+
+    } else {
+        //LOGW("download epo MD5 file failed, not meet retry condition, retry times:%d", retry_time);
+    }
+    return ret;
+}
+
+static int epo_MD5_download_process(void) {
+    int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    int md5_retry_cnt = 0;
+    int loop_cnt = 0;
+    int md5_DL_flag = 1;
+
+    while(1) {
+        if (is_qepo_download_finished()&&is_qepo_bd_download_finished()&&is_qepo_ga_download_finished()) {
+            if (md5_DL_flag == 1) {
+                if (curl_easy_download_epo_MD5() == CURLE_OK) {
+                    LOGD("%s download success", gps_epo_MD5_file_name);
+                    ret = EPO_MD5_FILE_UPDATED;
+                    break;
+                } else {
+                    LOGD("download MD5 first time failed");
+                    md5_DL_flag = 0;
+                }
+            } else if (md5_retry_cnt < EPO_DL_MAX_RETRY_TIME) {
+                md5_retry_cnt++;
+                if (epo_md5_update_retry(md5_retry_cnt) == EPO_MD5_FILE_UPDATED) {
+                    LOGD("%s download success", gps_epo_MD5_file_name);
+                    ret = EPO_MD5_FILE_UPDATED;
+                    break;
+                }
+            } else {
+                LOGE("Meet max retry time(%d), give up download epo MD5", md5_retry_cnt);
+                ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+                break;
+            }
+        } else {
+            // Wait qepo download finish, Maximum wait 30s
+            if (loop_cnt < 300) {
+                loop_cnt++;
+                usleep(100*1000);
+            } else {
+                LOGW("qepo download hung!!! EPO download exit");
+                ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+                break;
+            }
+        }
+    }
+    return ret;
+}
+
+static int epo_dat_update_retry(int retry_time) {
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+    if (mnld_is_gps_or_ofl_started() || (is_wifi_network_connected())) {
+        if (is_network_connected()) {
+            LOGW("download epo DAT file failed, retry resume after 10s.(times:%d)", retry_time);
+            usleep(10*1000*1000);
+            if (curl_easy_download_epo_DAT() == CURLE_OK) {
+                ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+            } else {
+                ret = EPO_DOWNLOAD_RESULT_FAIL;
+            }
+        } else {
+            usleep(10*1000*1000);
+            LOGW("download epo DAT file failed, no network connected, retry times:%d", retry_time);
+        }
+    } else {
+        LOGW("download epo DAT file failed, not meet retry condition, retry times:%d", retry_time);
+    }
+    return ret;
+}
+
+static int epo_DAT_download_process(void) {
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+    int loop_cnt = 0;
+    int dat_retry_cnt = 0;
+    int dat_DL_flag = 1;
+
+    while(1) {
+        if (is_qepo_download_finished()&&is_qepo_bd_download_finished()) {
+            if (dat_DL_flag == 1) {
+                if (curl_easy_download_epo_DAT() == CURLE_OK) {
+                    LOGD("%s download success", gps_epo_file_name);
+                    ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+                    break;
+                } else {
+                    dat_DL_flag = 0;
+                }
+            } else if (dat_retry_cnt < EPO_DL_MAX_RETRY_TIME) {
+                dat_retry_cnt++;
+                if (epo_dat_update_retry(dat_retry_cnt) == EPO_DOWNLOAD_RESULT_SUCCESS) {
+                    LOGD("%s download success", gps_epo_file_name);
+                    ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+                    break;
+                }
+            } else {
+                LOGE("Meet max retry time(%d), give up download epo DAT", dat_retry_cnt);
+                ret = EPO_DOWNLOAD_RESULT_FAIL;
+                break;
+            }
+        } else {
+            // Wait qepo download finish, Maximum wait 60s
+            if (loop_cnt < 600) {
+                loop_cnt++;
+                usleep(100*1000);
+            } else {
+                LOGW("qepo download hung!!! EPO download exit");
+                ret = EPO_DOWNLOAD_RESULT_FAIL;
+                break;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static int epo_DAT_file_merge(int file_length) {
+    FILE *fp_temp = NULL;
+    FILE *fp = NULL;
+    int res_val;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+
+    memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+
+    strncat(gps_epo_data_file_name, MTK_GPS_DATA_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    if (gps_epo_file_count == 0) {
+        LOGD("first piece to merge, delete old EPOHAL.DAT");
+        unlink(EPO_UPDATE_HAL);
+    }
+    LOGD("merge %s file to EPOHAL.DAT", gps_epo_data_file_name);
+    res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+    if (res_val < 0) {
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    }
+
+    fp_temp = fopen(EPO_UPDATE_HAL, "at");
+    if (fp_temp != NULL) {
+        fp = fopen(gps_epo_data_file_name, "r");
+        if (fp != NULL) {
+            #define buf_size  256
+            char data[buf_size] = {0};
+            int bytes_in = 0, bytes_out = 0;
+            int len = 0;
+
+            while ((bytes_in = fread(data, 1, sizeof(data), fp)) > 0
+                    && (bytes_in <= (int)(buf_size* sizeof(char)))) {
+                bytes_out = fwrite(data, 1, bytes_in, fp_temp);
+                if (bytes_in != bytes_out) {
+                    LOGD("bytes_in = %d,bytes_out = %d\n", bytes_in, bytes_out);
+                }
+                len += bytes_out;
+                if (file_length != EPO_MERGE_FULL_FILE && len >= file_length) {
+                    break;
+                }
+            }
+            fclose(fp);
+        } else {
+            LOGE("Open merged file fp=NULL\n");
+        }
+        fclose(fp_temp);
+    }
+    else {
+        LOGE("Open merged file failed\n");
+        return -1;
+    }
+    res_val = chmod(EPO_UPDATE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+    if (res_val < 0) {
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    }
+    return 0;
+}
+
+static int mtk_epo_1sv_checksum_check( const UINT32 u4SVData[18] )
+{
+   UINT32  checksum = 0;
+   int i=0;
+   int fgRet = MTK_GPS_FALSE;
+
+   for (i = 0; i < (18-1); i++)
+   {
+       checksum = checksum ^ u4SVData[i];  // exclusive OR
+   }
+
+   //check data checksum
+   if (checksum == u4SVData[17])
+   {
+        fgRet = MTK_GPS_TRUE;
+   }
+   return fgRet;
+}
+
+static int mtk_extract_epo_data_1SV(MTK_FILE hFile, UINT32 u4SvEpoData[MTK_EPO_ONE_SV_SIZE/4])
+{
+    memset(u4SvEpoData, 0, MTK_EPO_ONE_SV_SIZE);
+
+    if ( EPO_File_Read(hFile, u4SvEpoData, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE )
+    {
+        LOGE("read 1 sv data error");
+        return MTK_GPS_ERROR;
+    }
+
+    return MTK_GPS_SUCCESS;
+}
+
+static int epo_DAT_checksum_check(void) {
+    MTK_GPS_PARAM_EPO_DATA_CFG epo_data;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    MTK_FILE hFile = 0;
+    int u4FileSize;
+    int sv_cnt = 0;
+    int max_sv_num;
+    int max_segment_size;
+    int valid_file_length;
+
+    memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+
+    strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+
+    if ( (hFile = EPO_File_Open(gps_epo_data_file_name, MTK_FS_READ)) == 0)
+    {
+        LOGE("Open epo DAT file error");
+        return MTK_GPS_ERROR;
+    }
+
+    if ( (u4FileSize = get_file_size(gps_epo_data_file_name)) == -1) {
+        LOGE("get file size error");
+        EPO_File_Close(hFile);
+        return MTK_GPS_ERROR;
+    }
+
+    while (sv_cnt*MTK_EPO_ONE_SV_SIZE < u4FileSize) {
+        if ( MTK_GPS_ERROR == mtk_extract_epo_data_1SV(hFile, epo_data.u4EPOWORD) )
+        {
+            LOGE("extract GPS EPO 1 SV data error");
+            break;
+        } else {
+            if (mtk_epo_1sv_checksum_check(epo_data.u4EPOWORD) == MTK_GPS_TRUE) {
+                sv_cnt++;
+            } else {
+                LOGE("find checksum error sv");
+                break;
+            }
+        }
+    }
+
+    EPO_File_Close(hFile);
+
+    if (gps_epo_type == MTK_EPO_GPS) {
+        max_sv_num = MTK_EPO_SET_GPS_SVNum;
+        max_segment_size = MTK_EPO_SET_GPS_MAX_SIZE;
+    } else if (gps_epo_type == MTK_EPO_GPS_GLO) {
+        max_sv_num = MTK_EPO_SET_GPS_SVNum + MTK_EPO_SET_GLO_SVNum;
+        max_segment_size = MTK_EPO_SET_GPS_GLO_MAX_SIZE;
+    } else {
+        LOGE("gps epo type is error");
+        return MTK_GPS_ERROR;
+    }
+
+    if ((sv_cnt / max_sv_num > 8) || gps_epo_file_count > 0) {     // check if valid epo set more than 2 days. (1 epo set is 6hours, 8 means 2days)
+        valid_file_length = (unsigned int)(sv_cnt / max_sv_num) * max_segment_size;
+        return valid_file_length;
+    } else {
+        LOGW("no enough epo exist, ignore this piece. sv_cnt(%d)", sv_cnt);
+        return MTK_GPS_ERROR;
+    }
+}
+
+
+static void check_epo_file_exist(void) {
+    int i;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    char gps_epo_md5_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    for(i = 0; i< gps_epo_download_piece; ++i) {
+        gps_download_epo_file_name(i);
+        memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+        memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+        strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+        strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+        strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+        strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+        if ((epo_status.EPO_piece_flag[i] & EPO_MD5_AVAILABLE_BIT) == EPO_MD5_AVAILABLE_BIT) {
+            if (access(gps_epo_md5_file_name, F_OK) == -1) {
+                epo_status.EPO_piece_flag[i] &= (~EPO_MD5_AVAILABLE_BIT);
+            }
+        }
+        if ((epo_status.EPO_piece_flag[i] & EPO_DAT_AVAILABLE_BIT) == EPO_DAT_AVAILABLE_BIT) {
+            if (access(gps_epo_data_file_name, F_OK) == -1) {
+                epo_status.EPO_piece_flag[i] &= (~EPO_DAT_AVAILABLE_BIT);
+            }
+        }
+    }
+}
+
+static int epo_file_download_impl() {
+    int ret = EPO_DOWNLOAD_RESULT_SUCCESS;   //DAT file download result
+    int ret_MD5 = EPO_MD5_DOWNLOAD_RESULT_FAIL;  //MD5 file download result
+    int valid_file_length;
+    int i;
+    int dl_retry_cnt = 0;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    char gps_epo_md5_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    struct tm  tm;
+    time_t now = time(NULL);
+    gmtime_r(&now, &tm);
+    unlink(EPO_UPDATE_HAL);
+
+    // Check how many pieces should be DL, based on download days of user config
+    gps_epo_download_piece = gps_epo_download_days / 3;
+    if ((gps_epo_download_days % 3) > 0) {
+        gps_epo_download_piece++;
+    }
+
+    LOGD("download info: download piece = %d, today retry time =%d, last_date=%d", gps_epo_download_piece, epo_status.today_retry_time, epo_status.last_DL_Date);
+    dl_retry_cnt = 0;
+    do{
+        // Check if a new day comes, reset flag to re-dl (have checked EPO expire before trigger dl)
+        if (epo_status.last_DL_Date != tm.tm_mday) {
+            memset(epo_status.EPO_piece_flag, 0x00, sizeof(unsigned int)*MAX_EPO_PIECE);
+            epo_status.today_retry_time = 0;
+            epo_status.last_DL_Date = tm.tm_mday;
+            LOGD("First epo request today, day is %d", epo_status.last_DL_Date);
+            for (i = 0; i < gps_epo_download_piece; i++) {
+                memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+                memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+                gps_download_epo_file_name(i);
+                strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+                strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+                strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+                strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+                unlink(gps_epo_md5_file_name);
+                unlink(gps_epo_data_file_name);
+            }
+        }
+
+        check_epo_file_exist();
+
+        for(gps_epo_file_count = 0; gps_epo_file_count < gps_epo_download_piece; ++gps_epo_file_count) {
+            //LOGD("EPO begin download %d piece...", gps_epo_file_count);
+            gps_download_epo_file_name(gps_epo_file_count);
+            if (((epo_status.EPO_piece_flag[gps_epo_file_count] & EPO_MD5_AVAILABLE_BIT) == EPO_MD5_AVAILABLE_BIT) &&
+                ((epo_status.EPO_piece_flag[gps_epo_file_count] & EPO_DAT_AVAILABLE_BIT) == EPO_DAT_AVAILABLE_BIT)) {
+                LOGD("EPO MD5 DAT both valid, no need download %s", gps_epo_file_name);
+                if (epo_DAT_file_merge(EPO_MERGE_FULL_FILE) == -1) {
+                    LOGE("Merge piece EPO to DAT file error");
+                    ret = EPO_DOWNLOAD_RESULT_FAIL;
+                    break;
+                }
+                continue;
+            } else if ((epo_status.EPO_piece_flag[gps_epo_file_count] & EPO_MD5_AVAILABLE_BIT) != EPO_MD5_AVAILABLE_BIT) {
+                LOGD("EPO MD5 not valid, download %s ", gps_epo_MD5_file_name);
+                ret_MD5 = epo_MD5_download_process();
+                if (ret_MD5 == EPO_MD5_FILE_UPDATED) {
+                    epo_status.EPO_piece_flag[gps_epo_file_count] |= EPO_MD5_AVAILABLE_BIT;
+                    //LOGD("%s download success", gps_epo_file_name);
+                }else {
+                    LOGE("%s download failed", gps_epo_MD5_file_name);
+                    if (gps_epo_file_count == 0) {
+                        ret = EPO_DOWNLOAD_RESULT_FAIL;
+                    }
+                    break;
+                }
+            }
+
+            ret = epo_DAT_download_process();
+            if (ret == EPO_DOWNLOAD_RESULT_SUCCESS) {
+                memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+                memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+                strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+                strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+                strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+                strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+                if (mtk_gps_epo_md5_match_check(gps_epo_data_file_name, gps_epo_md5_file_name) == MTK_GPS_ERROR) {
+                    LOGE("EPO DAT MD5 match check failed, confirm checksum");
+                    if ((valid_file_length = epo_DAT_checksum_check()) > 0) {
+                        if (epo_DAT_file_merge(valid_file_length) == -1) {
+                            LOGE("Merge piece EPO to DAT file error");
+                            ret = EPO_DOWNLOAD_RESULT_FAIL;
+                            break;
+                        } else {
+                            ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+                            LOGD("have more than 2days EPO(%d piece + valid file size:%d bytes), do inject", gps_epo_file_count, valid_file_length);
+                            break;
+                        }
+                    } else {
+                        epo_status.EPO_piece_flag[gps_epo_file_count] &= (~EPO_DAT_AVAILABLE_BIT);
+                        epo_status.EPO_piece_flag[gps_epo_file_count] &= (~EPO_MD5_AVAILABLE_BIT);
+                        epo_status.today_retry_time++;
+                        unlink(gps_epo_md5_file_name);
+                        unlink(gps_epo_data_file_name);
+                        ret = EPO_DOWNLOAD_RESULT_FAIL;
+                        break;
+                    }
+                } else {
+                    LOGD("EPO MD5 check success: %d", gps_epo_file_count);
+                    epo_status.EPO_piece_flag[gps_epo_file_count] |= EPO_DAT_AVAILABLE_BIT;
+                    if (epo_DAT_file_merge(EPO_MERGE_FULL_FILE) == -1) {   // 0 means merge all
+                        LOGE("Merge piece EPO to DAT file error");
+                        ret = EPO_DOWNLOAD_RESULT_FAIL;
+                        break;
+                    }
+                }
+            }else {
+                LOGE("DAT file download failed");
+                ret = EPO_DOWNLOAD_RESULT_FAIL;
+                break;
+            }
+        }
+
+        if (ret == EPO_DOWNLOAD_RESULT_SUCCESS) {
+            //LOGD("Merge EPOHAL.DAT success, delete piece files");
+            for (i = 0; i < gps_epo_download_piece; i++) {
+                memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+                memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+                gps_download_epo_file_name(i);
+                strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+                strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+                strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+                strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+                unlink(gps_epo_md5_file_name);
+                unlink(gps_epo_data_file_name);
+            }
+            break;
+        } else {  //Download fail
+            if (gps_epo_file_count == 0)  //Only pice 1 need to retry
+            {
+                dl_retry_cnt ++;
+                if (dl_retry_cnt <= EPO_INVALIDE_DL_MAX_RETRY_TIME)
+                {
+                    usleep(EPO_INVALIDE_DL_RETRY_SLEEP);
+                }
+            } else {
+                dl_retry_cnt = EPO_INVALIDE_DL_MAX_RETRY_TIME+1; //No need retry
+            }
+            LOGW("retry cnt:%d", dl_retry_cnt);
+        }
+    }while (dl_retry_cnt <= EPO_INVALIDE_DL_MAX_RETRY_TIME);
+
+    return ret;
+}
+
+/*****************************************************************************/
+static int get_val(char *pStr, char** ppKey, char** ppVal) {
+    int len = (int)strlen(pStr);
+    char *end = pStr + len;
+    char *key = NULL, *val = NULL;
+
+    LOGD("pStr = %s, len=%d!!\n", pStr, len);
+
+    if (!len) {
+        return -1;       // no data
+    } else if (pStr[0] == '#') {   /*ignore comment*/
+        *ppKey = *ppVal = NULL;
+        return 0;
+    } else if (pStr[len-1] != '\n') {
+        if (len >= GPS_CONF_FILE_SIZE-1) {
+            LOGD("buffer is not enough!!\n");
+            return -1;
+        } else {
+            pStr[len] = '\n';
+        }
+    }
+    key = pStr;
+
+    LOGD("key = %s!!\n", key);
+    while ((*pStr != '=') && (pStr < end)) pStr++;
+    if (pStr >= end) {
+        LOGD("'=' is not found!!\n");
+        return -1;       // format error
+    }
+
+    *pStr++ = '\0';
+    while (IS_SPACE(*pStr) && (pStr < end)) pStr++;       // skip space chars
+    val = pStr;
+    while (!IS_SPACE(*pStr) && (pStr < end)) pStr++;
+    *pStr = '\0';
+    *ppKey = key;
+    *ppVal = val;
+
+    LOGD("val = %s!!\n", val);
+    return 0;
+}
+
+/*****************************************************************************/
+int epo_read_cust_config(void) {
+    char result[GPS_CONF_FILE_SIZE] = {0};
+
+    FILE *fp = fopen(EPO_CONTROL_FILE_PATH, "r");
+    char *key, *val;
+    if (!fp) {
+           // LOGD("%s: open %s fail!\n", __FUNCTION__, EPO_CONTROL_FILE_PATH);
+        return 1;
+    }
+
+    while (fgets(result, sizeof(result), fp)) {
+        if (get_val(result, &key, &val)) {
+            LOGD("%s: Get data fails!!\n", __FUNCTION__);
+            fclose(fp);
+            return 1;
+        }
+        if (!key || !val)
+            continue;
+        if (!strcmp(key, "EPO_ENABLE")) {
+            int len = strlen(val);
+
+            LOGD("gps_epo_enablebg = %d, len =%d\n", gps_epo_enable, len);
+            gps_epo_enable = str2int(val, val+len);   // *val-'0';
+            if ((gps_epo_enable != 1) && (gps_epo_enable != 0)) {
+                gps_epo_enable = 1;
+            }
+            LOGD("gps_epo_enableend = %d\n", gps_epo_enable);
+        }
+        if (!strcmp(key, "DW_DAYS")) {
+            int len = strlen(val);
+            gps_epo_download_days = str2int(val, val+len);         // *val-'0';
+            if (gps_epo_download_days > MTK_EPO_MAX_DAY || gps_epo_download_days < 0) {
+                gps_epo_download_days = MTK_EPO_DEFAULT_DL_DAY;
+            }
+        }
+        if (!strcmp(key, "EPO_WIFI_TRIGGER")) {
+            int len = strlen(val);
+            LOGD("gps_epo_wifi_triggerbg = %d, len =%d\n", gps_epo_wifi_trigger, len);
+            gps_epo_wifi_trigger = str2int(val, val+len);   // *val-'0';
+            if ((gps_epo_wifi_trigger != 1) && (gps_epo_wifi_trigger != 0)) {
+                gps_epo_wifi_trigger = 0;
+            }
+            LOGD("gps_epo_wifi_triggerend = %d\n", gps_epo_wifi_trigger);
+        }
+        LOGD("gps_epo_enable = %d, gps_epo_period = %d, \
+            wifi_epo_period = %d, gps_epo_wifi_trigger = %d\n", gps_epo_enable, gps_epo_period,
+            wifi_epo_period, gps_epo_wifi_trigger);
+    }
+
+    fclose(fp);
+    return 1;
+}
+
+/*****************************************************************************/
+static void gps_download_epo_file_name(int count) {
+    //  LOGD("count is %d\n", count);
+    if (gps_epo_type == 1) {
+        if (count == 0) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_1.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_1.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 1) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_2.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_2.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 2) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_3.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_3.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 3) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_4.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_4.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 4) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_5.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_5.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 5) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_6.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_6.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 6) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_7.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_7.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 7) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_8.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_8.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 8) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_9.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_9.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 9) {
+            strncpy(gps_epo_file_name, "EPO_GPS_3_10.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GPS_3_10.MD5", GPS_EPO_FILE_LEN);
+        }
+    }
+    else if (gps_epo_type == 0) {
+        if (count == 0) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_1.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_1.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 1) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_2.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_2.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 2) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_3.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_3.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 3) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_4.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_4.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 4) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_5.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_5.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 5) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_6.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_6.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 6) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_7.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_7.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 7) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_8.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_8.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 8) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_9.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_9.MD5", GPS_EPO_FILE_LEN);
+        } else if (count == 9) {
+            strncpy(gps_epo_file_name, "EPO_GR_3_10.DAT", GPS_EPO_FILE_LEN);
+            strncpy(gps_epo_MD5_file_name, "EPO_GR_3_10.MD5", GPS_EPO_FILE_LEN);
+        }
+    }
+    //LOGD("download request for file %d, gps_epo_file_name=%s, gps_epo_MD5_file_name=%s\n",
+    //    count, gps_epo_file_name, gps_epo_MD5_file_name);
+}
+
+/*****************************************************************************/
+int mtk_gps_sys_read_lock(int fd, off_t offset, int whence, off_t len) {
+    struct flock lock;
+
+    lock.l_type = F_RDLCK;
+    lock.l_start = offset;
+    lock.l_whence = whence;
+    lock.l_len = len;
+
+    if (fcntl(fd, F_SETLK, &lock) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+static unsigned int mtk_gps_sys_get_file_size() {
+    unsigned int fileSize;
+    int res_epo, res_epo_hal;
+    struct stat st;
+    char *epo_file = EPO_FILE;
+    char *epo_file_hal = EPO_UPDATE_HAL;
+    char epofile[GPS_EPO_FILE_LEN] = {0};
+    res_epo = access(EPO_FILE, F_OK);
+    res_epo_hal = access(EPO_UPDATE_HAL, F_OK);
+    if (res_epo < 0 && res_epo_hal < 0) {
+        LOGD("no EPO data yet\n");
+        return -1;
+    }
+    if (res_epo_hal == 0) {  /*EPOHAL.DAT is here*/
+        // LOGD("find EPOHAL.DAT here\n");
+        MNLD_STRNCPY(epofile, epo_file_hal, GPS_EPO_FILE_LEN);
+    } else if (res_epo == 0) {  /*EPO.DAT is here*/
+        // LOGD("find EPO.DAT here\n");
+        MNLD_STRNCPY(epofile, epo_file, GPS_EPO_FILE_LEN);
+    } else
+        LOGE("unknown error happened\n");
+
+    if (stat(epofile, &st) < 0) {
+        LOGE("Get file size error, return\n");
+        return 0;
+    }
+
+    fileSize = st.st_size;
+       // LOGD("EPO file size: %d\n", fileSize);
+    return fileSize;
+}
+
+/*****************************************************************************/
+void GpsToUtcTime(int i2Wn, double dfTow, time_t* uSecond) {
+    struct tm target_time;
+    int iYearsElapsed;        //  Years since 1980.
+    unsigned int iDaysElapsed;         //  Days elapsed since Jan 1, 1980.
+    double dfSecElapsed;
+    unsigned int fgLeapYear;
+    int pi2Yr = 0;
+    int pi2Mo = 0;
+    int pi2Day = 0;
+    int pi2Hr = 0;
+    int pi2Min = 0;
+    double pdfSec = 0;
+    int i = 0;
+
+
+    //  Number of days into the year at the start of each month (ignoring leap
+    //  years).
+    unsigned int doy[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+    //  Convert time to GPS weeks and seconds
+    iDaysElapsed = i2Wn * 7 + ((int)dfTow / 86400) + 5;
+    dfSecElapsed = dfTow - ((int)dfTow / 86400) * 86400;
+
+
+    //  decide year
+    iYearsElapsed = 0;       //  from 1980
+    while (iDaysElapsed >= 365) {
+        if ((iYearsElapsed % 100) == 20) {   //  if year % 100 == 0
+            if ((iYearsElapsed % 400) == 20) {   //  if year % 400 == 0
+                if (iDaysElapsed >= 366) {
+                    iDaysElapsed -= 366;
+                } else {
+                    break;
+                }
+            } else {
+                iDaysElapsed -= 365;
+            }
+        } else if ((iYearsElapsed % 4) == 0) {   //  if year % 4 == 0
+            if (iDaysElapsed >= 366) {
+                iDaysElapsed -= 366;
+            } else {
+                break;
+            }
+        } else {
+            iDaysElapsed -= 365;
+        }
+        iYearsElapsed++;
+    }
+    pi2Yr = 1980 + iYearsElapsed;
+
+
+    // decide month, day
+    fgLeapYear = 0;
+    if ((iYearsElapsed % 100) == 20) {    // if year % 100 == 0
+        if ((iYearsElapsed % 400) == 20) {    // if year % 400 == 0
+           fgLeapYear = 1;
+        }
+    }
+    else if ((iYearsElapsed % 4) == 0) {   // if year % 4 == 0
+        fgLeapYear = 1;
+    }
+
+    if (fgLeapYear) {
+        for (i = 2; i < 12; i++) {
+            doy[i] += 1;
+        }
+    }
+    for (i = 0; i < 12; i++) {
+        if (iDaysElapsed < doy[i]) {
+            break;
+        }
+    }
+    pi2Mo = i;
+    if (i > 0) {
+        pi2Day = iDaysElapsed - doy[i-1] + 1;
+    }
+
+    // decide hour, min, sec
+    pi2Hr = dfSecElapsed / 3600;
+    pi2Min = ((int)dfSecElapsed % 3600) / 60;
+    pdfSec = dfSecElapsed - ((int)dfSecElapsed / 60) * 60;
+
+    // change the UTC time to seconds
+    memset(&target_time, 0, sizeof(target_time));
+    target_time.tm_year = pi2Yr - 1900;
+    target_time.tm_mon = pi2Mo - 1;
+    target_time.tm_mday = pi2Day;
+    target_time.tm_hour = pi2Hr;
+    target_time.tm_min = pi2Min;
+    target_time.tm_sec = pdfSec;
+    target_time.tm_isdst = -1;
+    *uSecond = mktime(&target_time);
+    if (*uSecond < 0) {
+        LOGE("Convert UTC time to seconds fail, return\n");
+    }
+}
+
+
+/*****************************************************************************/
+int mtk_gps_sys_epo_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {         // no file lock
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    // if (fread(szBuf, 1, MTK_EPO_ONE_SV_SIZE, pFile) != MTK_EPO_ONE_SV_SIZE) {
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    // TRC();
+    // LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);   // to get UTC second
+    return 0;
+}
+
+/*****************************************************************************/
+int mtk_gps_sys_epo_bd_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {         // no file lock
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    if (-1 == lseek(fd, MTK_EPO_ONE_SV_SIZE, SEEK_SET)) { //Skip the header of BD QEPO file
+        LOGE("lseek error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);   // to get UTC second
+    return 0;
+}
+
+/*****************************************************************************/
+int mtk_gps_sys_epo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {         // no file lock
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    if (-1 == lseek(fd, MTK_EPO_ONE_SV_SIZE, SEEK_SET)) { //Skip the header of GA QEPO file
+        LOGE("lseek error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);   // to get UTC second
+    return 0;
+}
+
+/*****************************************************************************/
+static int mtk_gps_sys_epo_period_end(int fd, unsigned int *u4GpsSecs, time_t* uSecond) {           // no file lock
+    int fileSize;
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    fileSize = mtk_gps_sys_get_file_size();
+    if (fileSize < MTK_EPO_ONE_SV_SIZE) {
+        return -1;
+    }
+
+    if (-1 == lseek(fd, (fileSize - MTK_EPO_ONE_SV_SIZE), SEEK_SET)) {
+        LOGE("lseek error\n");
+        return -1;
+    }
+
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    (*u4GpsSecs) += 21600;
+
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    // TRC();
+    // LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);
+
+    return 0;
+}
+
+/*****************************************************************************/
+static int mtk_gps_epo_file_time_hal(time_t uTime[]) {
+    //LOGD("mtk_gps_epo_file_time_hal");
+    struct stat filestat;
+    int fd = 0;
+    int res_epo, res_epo_hal;
+    unsigned int u4GpsSecs_start;    // GPS seconds
+    unsigned int u4GpsSecs_expire;
+    char *epo_file = EPO_FILE;
+    char *epo_file_hal = EPO_UPDATE_HAL;
+    char epofile[GPS_EPO_FILE_LEN] = {0};
+    time_t uSecond_start;      // UTC seconds
+    time_t uSecond_expire;
+// int ret = 0;
+    // pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;
+
+    res_epo = access(EPO_FILE, F_OK);
+    res_epo_hal = access(EPO_UPDATE_HAL, F_OK);
+    if (res_epo < 0 && res_epo_hal < 0) {
+        LOGD("no EPO data yet\n");
+//        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    }
+    if (res_epo_hal== 0) {  /*EPOHAL.DAT is here*/
+        // LOGD("find EPOHAL.DAT here\n");
+        MNLD_STRNCPY(epofile, epo_file_hal, GPS_EPO_FILE_LEN);
+    } else if (res_epo == 0) {  /*EPO.DAT is here*/
+           // LOGD("find EPO.DAT here\n");
+        MNLD_STRNCPY(epofile, epo_file, GPS_EPO_FILE_LEN);
+    } else
+        LOGE("unknown error happened\n");
+
+    // open file
+    fd = open(epofile, O_RDONLY);
+    if (fd < 0) {
+        LOGE("Open EPO fail, return\n");
+//        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    }
+
+    // Add file lock
+    if (mtk_gps_sys_read_lock(fd, 0, SEEK_SET, 0) < 0) {
+        LOGE("Add read lock failed, return\n");
+        close(fd);
+//      ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    }
+
+    // EPO start time
+    if (mtk_gps_sys_epo_period_start(fd, &u4GpsSecs_start, &uSecond_start)) {
+        LOGE("Get EPO file start time error, return\n");
+        close(fd);
+//        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    } else {
+        uTime[0] = uSecond_start;
+        //  LOGD("The Start time of EPO file is %lld", uTime[0]);
+        //  LOGD("The start time of EPO file is %s", ctime(&uTime[0]));
+    }
+
+    // download time
+    if (stat(epofile, &filestat) == -1){
+        LOGE("stat get file information failed reason=[%s]\n", strerror(errno));
+    }
+
+    uTime[1] = filestat.st_mtime;
+    // uTime[1] = uTime[1] - 8 * 3600;
+    // LOGD("Download time of EPO file is %lld", uTime[1]);
+    // LOGD("Download time of EPO file is %s\n", ctime(&uTime[1]));
+
+    // EPO file expire time
+    if (mtk_gps_sys_epo_period_end(fd, &u4GpsSecs_expire, &uSecond_expire)) {
+        LOGE("Get EPO file expire time error, return\n");
+        close(fd);
+//        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    } else {
+        uTime[2] = uSecond_expire;
+        // LOGD("The expire time of EPO file is %lld", uTime[2]);
+        //  LOGD("The expire time of EPO file is %s", ctime(&uTime[2]));
+    }
+
+    close(fd);
+//    ret = pthread_mutex_unlock(&mutx);
+    return 0;
+}
+
+size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+    LOGD("size: %zu, nmemb: %zu", size, nmemb);
+    size_t written;
+    written = fwrite(ptr, size, nmemb, stream);
+    if(written < nmemb) {
+        LOGE("error: written %zu", written);
+    }
+    return written;
+}
+CURLcode curl_easy_download(char* url, char* filename) {
+    CURL *curl = NULL;
+    FILE *fp = NULL;
+    CURLcode res;
+
+    LOGD("curl_easy_download url: %s to %s", url, filename);
+    if ((res = curl_global_init(CURL_GLOBAL_DEFAULT)) != 0) {
+        LOGE("curl_global_init fail, res = %d, curl_easy_download url: %s to %s", res, url, filename);
+    }
+    curl = curl_easy_init();
+    LOGD("curl_easy_init done");
+    if (curl) {
+        fp = fopen(filename, "w+");
+        if (fp == NULL) {
+            LOGE("fopen %s failed.errno:%d, reson: %s", filename, errno, strerror(errno));
+            curl_easy_cleanup(curl);
+            return CURLE_FAILED_INIT;
+        }
+
+        curl_easy_setopt(curl, CURLOPT_URL, url);
+        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
+        //   curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
+        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+        res = curl_easy_perform(curl);
+        if(res != CURLE_OK){
+            LOGE("failed: %s", curl_easy_strerror(res));
+        }
+        curl_easy_cleanup(curl);
+        fclose(fp);
+        return res;
+    } else {
+        LOGE("curl_easy_init fail, curl_easy_download url: %s to %s", url, filename);
+        return CURLE_FAILED_INIT;
+    }
+}
+static int counter = 1;
+void getEpoUrl(char* filename, char* url) {
+    char count_str[15] = {0};
+
+    if (counter <= 1) {
+        strncat(url, EPO_URL_1, GPS_EPO_URL_LEN - strlen(url));
+    } else {
+        strncat(url, EPO_URL_2, GPS_EPO_URL_LEN -strlen(url));
+    }
+
+    strncat(url, filename, GPS_EPO_URL_LEN  - strlen(url));
+    strncat(url, "?retryCount=", GPS_EPO_URL_LEN  - strlen(url));
+    sprintf(count_str, "%d", counter-1);
+    strncat(url, count_str, GPS_EPO_URL_LEN  - strlen(url));
+    //LOGD("url = %s\n", url);
+}
+
+CURLcode curl_easy_download_epo_MD5(void) {
+    int res_val;
+    CURLcode res;
+    char url[GPS_EPO_URL_LEN]={0};
+    char gps_epo_md5_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    int filesize = 0;
+
+    //LOGD("curl_easy_download_epo_MD5:%s", gps_epo_MD5_file_name);
+    memset(gps_epo_md5_file_name, 0x00, sizeof(gps_epo_md5_file_name));
+    getEpoUrl(gps_epo_MD5_file_name, url);
+
+    strncat(gps_epo_md5_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+    strncat(gps_epo_md5_file_name, gps_epo_MD5_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_md5_file_name));
+    res = curl_easy_download(url, gps_epo_md5_file_name);
+    LOGD("curl_easy_download result: %d", res);
+
+    filesize = get_file_size(gps_epo_md5_file_name);
+
+    if (filesize <= 0 || filesize > EPO_MD5_FILE_MAX_SIZE) {
+        res = CURLE_READ_ERROR;
+        LOGE("error:download file size %d, EPO_MD5_FILE_MAX_SIZE %d.", filesize, EPO_MD5_FILE_MAX_SIZE);
+    }
+
+    //LOGD("epo MD5 file curl_easy_download res = %d\n", res);
+    if (res == CURLE_OK) {
+        counter = 1;
+        res_val = chmod(gps_epo_md5_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        if (res_val < 0) {
+            LOGD("chmod MD5 res_val = %d, %s\n", res_val, strerror(errno));
+        }
+    } else {
+        unlink(gps_epo_md5_file_name);
+        counter++;
+        LOGE("epo MD5 file download failed res:%d. curl_easy_download url: %s to %s", res, url, gps_epo_md5_file_name);
+    }
+    return res;
+}
+
+CURLcode curl_easy_download_epo_DAT(void) {
+    int res_val;
+    CURLcode res;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    char url[GPS_EPO_URL_LEN]={0};
+    int filesize = 0;
+
+    //LOGD("curl_easy_download_epo_DAT:%s", gps_epo_file_name);
+    memset(gps_epo_data_file_name, 0x00, sizeof(gps_epo_data_file_name));
+    getEpoUrl(gps_epo_file_name, url);
+
+    strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    res = curl_easy_download(url, gps_epo_data_file_name);
+
+    filesize = get_file_size(gps_epo_data_file_name);
+
+    if (filesize <= 0) {
+        res = CURLE_PARTIAL_FILE;
+        LOGE("download file size error.");
+    }
+
+    if (res == CURLE_OK) {
+        counter = 1;
+        res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        if (res_val < 0) {
+            LOGD("chmod DAT res_val = %d, %s\n", res_val, strerror(errno));
+        }
+    } else {
+        unlink(gps_epo_data_file_name);
+        counter++;
+        LOGD("epo DAT file curl_easy_download res = %d\n", res);
+    }
+    return res;
+}
+
+#ifndef CONFIG_GPS_MT3303
+CURLcode curl_easy_download_epo(void) {
+    int res_val;
+    CURLcode res;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+    char url[GPS_EPO_URL_LEN]={0};
+
+    LOGD("curl_easy_download_epo");
+    getEpoUrl(gps_epo_file_name, url);
+
+    strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+
+    res = curl_easy_download(url, gps_epo_data_file_name);
+    LOGD("epo file curl_easy_download res = %d\n", res);
+    if (res == CURLE_OK) {
+        FILE *fp_temp = NULL;
+        FILE *fp = NULL;
+
+        counter = 1;
+        if (gps_epo_file_count == 0) {
+            unlink(EPO_UPDATE_HAL);
+        }
+        res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+        fp_temp = fopen(EPO_UPDATE_HAL, "at");
+        if (fp_temp != NULL) {
+            fp = fopen(gps_epo_data_file_name, "r");
+            if (fp != NULL) {
+            #define buf_size  256
+                char data[buf_size] = {0};
+                int bytes_in = 0, bytes_out = 0;
+                int len = 0;
+
+                while ((bytes_in = fread(data, 1, sizeof(data), fp)) > 0
+                        && (bytes_in <= (int)(buf_size* sizeof(char)))) {
+                    bytes_out = fwrite(data, 1, bytes_in, fp_temp);
+                    if (bytes_in != bytes_out) {
+                        LOGD("bytes_in = %d,bytes_out = %d\n", bytes_in, bytes_out);
+                    }
+                    len += bytes_out;
+                    // LOGD("copying file...%d bytes copied\n",len);
+                }
+                fclose(fp);
+            } else {
+                LOGE("Open merged file fp=NULL\n");
+            }
+            fclose(fp_temp);
+        }
+        else {
+            LOGE("Open merged file failed\n");
+        }
+        res_val = chmod(EPO_UPDATE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        unlink(gps_epo_data_file_name);
+        counter++;
+    }
+    return res;
+}
+#else
+void __getEpoUrl(char* filename, char* url) {
+    char count_str[15] = {0};
+
+    if (counter <= 1) {
+        strcat(url, "https://mgepodownload.mediatek.com/");
+    } else {
+        strcat(url, "https://mepodownload.mediatek.com/");
+    }
+    strcat(url, filename);
+    strcat(url, "?retryCount=");
+    sprintf(count_str, "%d", counter-1);
+    strcat(url, count_str);
+    LOGD("url = %s\n", url);
+}
+
+CURLcode curl_easy_download_epo(void) {
+    int res_val;
+    CURLcode res;
+    char gps_epo_data_file_name[60] = {0};
+    char url[256]={0};
+
+    LOGD("curl_easy_download_epo");
+    __getEpoUrl(gps_epo_file_name, url);
+    strcat(gps_epo_data_file_name, "/data/misc/gps/");
+    strcat(gps_epo_data_file_name, gps_epo_file_name);
+    res = curl_easy_download(url, gps_epo_data_file_name);
+    LOGD("epo file curl_easy_download res = %d\n", res);
+    if (res == CURLE_OK) {
+        FILE *fp_temp = NULL;
+        FILE *fp = NULL;
+
+        counter = 1;
+        if (gps_epo_file_count == 0) {
+            unlink(EPO_UPDATE_HAL);
+        }
+        res_val = chmod(gps_epo_data_file_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        //LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+        fp_temp = fopen(EPO_UPDATE_HAL, "at");
+        if (fp_temp != NULL) {
+            fp = fopen(gps_epo_data_file_name, "r");
+            if (fp != NULL) {
+            #define buf_size  256
+                char data[buf_size] = {0};
+                int bytes_in = 0, bytes_out = 0;
+                int len = 0;
+
+                while ((bytes_in = fread(data, 1, sizeof(data), fp)) > 0
+                        && (bytes_in <= (int)(buf_size* sizeof(char)))) {
+                    bytes_out = fwrite(data, 1, bytes_in, fp_temp);
+                    if (bytes_in != bytes_out) {
+                        //LOGD("bytes_in = %d,bytes_out = %d\n", bytes_in, bytes_out);
+                    }
+                    len += bytes_out;
+                    // LOGD("copying file...%d bytes copied\n",len);
+                }
+                fclose(fp);
+            } else {
+                LOGE("Open merged file fp=NULL\n");
+            }
+            fclose(fp_temp);
+        }
+        else {
+            LOGE("Open merged file failed\n");
+        }
+        res_val = chmod(EPO_UPDATE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        //LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        unlink(gps_epo_data_file_name);
+        counter++;
+    }
+    return res;
+}
+#endif
+
+#if 0
+static unsigned int mtk_gps_epo_get_piece_file_size() {
+    struct stat st;
+    unsigned int fileSize;
+    char gps_epo_data_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+
+    strncat(gps_epo_data_file_name, EPO_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+    strncat(gps_epo_data_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name));
+
+    if (stat(gps_epo_data_file_name, &st) < 0) {
+        LOGE("Get file size error, return\n");
+        return 0;
+    }
+    fileSize = st.st_size;
+    LOGD("EPO piece file size: %d\n", fileSize);
+    return fileSize;
+}
+
+/*****************************************************************************/
+static int mtk_gps_epo_piece_data_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+
+    // if (fread(szBuf, 1, MTK_EPO_ONE_SV_SIZE, pFile) != MTK_EPO_ONE_SV_SIZE) {
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    LOGD("mtk_gps_epo_piece_data_start");
+    LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);   // to get UTC second
+    return 0;
+}
+
+/*****************************************************************************/
+static int mtk_gps_epo_piece_data_end(int fd, unsigned int *u4GpsSecs, time_t* uSecond) {
+    int fileSize = 0;
+    char szBuf[MTK_EPO_ONE_SV_SIZE] = {0};
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    if (-1 != fd) {
+        fileSize = mtk_gps_epo_get_piece_file_size();
+        if (fileSize < MTK_EPO_ONE_SV_SIZE) {
+            LOGE("Get file size is error\n");
+            return -1;
+        }
+        if (-1 == lseek(fd, (fileSize - MTK_EPO_ONE_SV_SIZE), SEEK_SET)) {
+            LOGE("lseek error\n");
+            return -1;
+        }
+
+        if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+            LOGE("read epo file end data faied\n");
+            return -1;
+        }
+
+        *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+        (*u4GpsSecs) += 21600;
+
+        pi2WeekNo = (*u4GpsSecs) / 604800;
+        pu4Tow = (*u4GpsSecs) % 604800;
+
+        LOGD("mtk_gps_epo_piece_data_end");
+        LOGD("pi2WeekNo = %d, pu4Tow = %d\n", pi2WeekNo, pu4Tow);
+        GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);
+    }
+    return 0;
+}
+#endif
+
+/*****************************************************************************/
+/*static int mtk_gps_epo_server_data_is_changed() {
+    time_t uTime_end = 0;
+    time_t uTime_start = 0;
+    int fd_end = -1;
+    int fd_start = -1;
+    char gps_epo_data_file_name_end[EPO_FILE_NAME_MAX_SIZE] = {0};
+    char gps_epo_data_file_name_start[EPO_FILE_NAME_MAX_SIZE] = {0};
+    time_t uSecond_start;
+    time_t uSecond_end;
+    unsigned int u4GpsSecs_start;
+    unsigned int u4GpsSecs_end;
+    int ret = 0;
+
+    strncat(gps_epo_data_file_name_start, MTK_GPS_DATA_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_start));
+    strncat(gps_epo_data_file_name_start, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_start));
+
+    fd_start = open(gps_epo_data_file_name_start, O_RDONLY);
+    if (fd_start >= 0) {
+        int res = 0;
+        res = mtk_gps_epo_piece_data_start(fd_start, &u4GpsSecs_start, &uSecond_start);
+        if (res == 0) {
+            uTime_start = uSecond_start;
+        } else {
+            epo_download_failed = 1;
+            ret = 1;
+            LOGE("Get start time failed\n");
+        }
+        close(fd_start);
+    } else {
+        LOGE("Open start file failed\n");
+    }
+    if (gps_epo_file_count > 0) {
+        gps_download_epo_file_name(gps_epo_file_count - 1);
+        strncat(gps_epo_data_file_name_end, MTK_GPS_DATA_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_end));
+        strncat(gps_epo_data_file_name_end, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_data_file_name_end));
+
+        // open file
+        fd_end = open(gps_epo_data_file_name_end, O_RDONLY);
+        if (fd_end >= 0) {
+            int res = 0;
+            res = mtk_gps_epo_piece_data_end(fd_end, &u4GpsSecs_end, &uSecond_end);
+            if (res == 0) {
+                uTime_end = uSecond_end;
+            } else {
+                epo_download_failed = 1;
+                LOGE("Get end time failed\n");
+                ret = 1;
+            }
+            close(fd_end);
+        } else {
+            LOGE("Open end file failed\n");
+        }
+    } else if (gps_epo_file_count == 0) {
+        uTime_end = uTime_start;
+    }
+
+    // LOGD("gps_epo_data_file_start =%s, end =%s\n", gps_epo_data_file_name_start, gps_epo_data_file_name_end);
+    LOGD("The end time of EPO file is %s, The start time of EPO file is %s\n",
+        ctime(&uTime_end), ctime(&uTime_start));
+    if (uTime_start >= ((24*60*60) + uTime_end)) {
+        int i;
+        LOGD("The epo data is updated on the server!!!\n");
+        for (i = gps_epo_file_count; 0 <= i; i--) {
+            char gps_epo_piece_file_name[EPO_FILE_NAME_MAX_SIZE] = {0};
+
+            gps_download_epo_file_name(i);
+            strncat(gps_epo_piece_file_name, MTK_GPS_DATA_PATH, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_piece_file_name));
+            strncat(gps_epo_piece_file_name, gps_epo_file_name, EPO_FILE_NAME_MAX_SIZE - strlen(gps_epo_piece_file_name));
+            unlink(gps_epo_piece_file_name);
+        }
+        unlink(EPO_UPDATE_HAL);
+        gps_epo_file_count = 0;
+        return 1;
+    }
+    return ret;
+}*/
+
+static int mtk_epo_is_expired(int wifi_tragger) {
+    time_t uTime[3];  // [0] epo start time, [1] download time, [2] expired time
+    memset(uTime, 0, sizeof(uTime));
+    time_t         now = time(NULL);
+    struct tm      tm_utc;
+    time_t  time_utc;
+    long expired_set = 0;
+    int download_day = 0;
+
+    gmtime_r(&now, &tm_utc);
+    time_utc = mktime(&tm_utc);
+    mtk_gps_epo_file_time_hal(uTime);
+
+    if (wifi_tragger) {
+        expired_set = wifi_epo_period*24*60*60;    // for wifi tragger we change checking expired time to 1 day.
+    } else {
+        download_day = (uTime[2] - uTime[0])/(24*60*60);
+           // LOGD("epo data downloaded dat: %d\n", download_day);
+        if (download_day < 3) {
+            expired_set = 0;
+        } else if (download_day < 6) {
+            expired_set = 3*24*60*60;
+        } else if ((6 <= download_day) && (download_day < 9)) {
+            expired_set = 5*24*60*60;
+        } else if ((9 <= download_day) && (download_day < 12)) {
+            expired_set = 7*24*60*60;
+        } else if ((12 <= download_day) && (download_day < 15)) {
+            expired_set = 7*24*60*60;
+        } else if ((15 <= download_day) && (download_day < 18)) {
+            expired_set = 7*24*60*60;
+        } else if (download_day >= 18) {
+            expired_set = 7*24*60*60;
+        }
+    }
+
+    LOGD("current time: %ld, current time:%s", time_utc, ctime(&time_utc));
+    LOGD("EPO start time: %ld, EPO start time: %s", uTime[0], ctime(&uTime[0]));
+      //  LOGD("EPO expired_set: %lld", expired_set);
+    if ((time_utc - uTime[0]) >= expired_set) {
+        LOGD("EPO file is expired");
+        gps_epo_file_count = 0;
+        return 1;
+    } else if ((time_utc - uTime[0]) < 0) {
+        LOGD("Current time is invalid");
+        gps_epo_file_count = 0;
+        return 1;
+    } else {
+        LOGD("EPO file is valid, no need update");
+        return 0;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// MAIN -> EPO Download (handlers)
+static int mnld_epo_download() {
+    //LOGD("begin\n");
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    ret = epo_file_download_impl();
+
+    LOGD("download epo file completed!file count=%d, epo_download_result=%d\n",
+        gps_epo_file_count, ret);
+
+    mnld_epo_download_done(ret);
+
+    //LOGD("end\n");
+    return ret;
+}
+static int epo_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main2epo_event cmd;
+    int read_len;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("epo_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    cmd = get_int(buff, &offset, sizeof(buff));
+    switch (cmd) {
+    case MAIN2EPO_EVENT_START: {
+        LOGW("mnld_epo_download() before");
+        // need to call mnld_epo_download_done() when EPO download is done
+        mnld_epo_download();
+        LOGW("mnld_epo_download() after");
+        break;
+    }
+    default: {
+        LOGE("epo_event_hdlr() unknown cmd=%d", cmd);
+        return -1;
+    }
+    }
+    return 0;
+}
+
+/*static void epo_downloader_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("epo_downloader_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("epo_downloader_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}*/
+
+static void retry_alarm_timeout_handler() {
+    epo_download_retry = 1;
+    LOGD("epo_download_retry is =%d\n", epo_download_retry);
+}
+
+static void* epo_downloader_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    //hdlr_timer = init_timer(epo_downloader_thread_timeout);
+    retry_download_timer = init_timer(retry_alarm_timeout_handler);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("epoll_create failure reason=[%s]%d\n",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_epo) == -1) {
+        LOGE("epoll_add_fd() failed for g_fd_epo failed");
+        return 0;
+    }
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        //start_timer(hdlr_timer, MNLD_EPO_HANDLER_TIMEOUT);
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_epo) {
+                if (events[i].events & EPOLLIN) {
+                    epo_event_hdlr(g_fd_epo);
+                }
+            } else {
+                LOGE("unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        //stop_timer(hdlr_timer);
+    }
+
+    LOGE("exit");
+    return 0;
+}
+
+int epo_downloader_is_file_invalid() {
+    return mtk_epo_is_expired(0);
+}
+
+int epo_is_wifi_trigger_enabled() {
+    return gps_epo_wifi_trigger;
+}
+
+int epo_is_epo_download_enabled() {
+    return gps_epo_enable;
+}
+
+int epo_downloader_start() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, MAIN2EPO_EVENT_START);
+    return safe_sendto(MNLD_EPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int epo_downloader_init() {
+    pthread_t pthread_epo;
+    g_fd_epo = socket_bind_udp(MNLD_EPO_DOWNLOAD_SOCKET);
+    if (g_fd_epo < 0) {
+        LOGE("socket_bind_udp(MNLD_EPO_DOWNLOAD_SOCKET) failed");
+        return -1;
+    }
+
+    pthread_create(&pthread_epo, NULL, epo_downloader_thread, NULL);
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/DOWNLOAD.H b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/DOWNLOAD.H
new file mode 100644
index 0000000..18b0827
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/DOWNLOAD.H
@@ -0,0 +1,121 @@
+/*******************************************************************************

+*  Copyright Statement:

+*  --------------------

+*  This software is protected by Copyright and the information contained

+*  herein is confidential. The software may not be copied and the information

+*  contained herein may not be used or disclosed except with the written

+*  permission of MediaTek Inc. (C) 2016

+*

+*******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *      download.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *   This file is intends for download agent specific definition

+ *

+ *******************************************************************************/

+#ifndef _DOWNLOAD_H_

+#define _DOWNLOAD_H_

+

+/* DA Version */

+#define DA_MAJOR_VER    0x04

+#define DA_MINOR_VER    0x00

+

+

+/* RETURN VALUE */

+#define HW_ERROR              0x1c

+#define HW_RAM_OK             0xE0

+#define HW_RAM_FLOARTING      0xE1

+#define HW_RAM_UNACCESSABLE   0xE2

+#define HW_RAM_ERROR          0xE3

+#define SOC_FAIL              0x0c

+#define SYNC_CHAR             0xc0

+#define CONT_CHAR             0x69

+#define STOP_CHAR             0x96

+#define ACK                   0x5a

+#define NACK                  0xa5

+#define UNKNOWN_CMD           0xbb

+

+/* FLASH OPERATION STATUS */

+typedef enum {

+    S_DONE = 0

+   ,S_PGM_FAILED

+   ,S_ERASE_FAILED

+   ,S_TIMEOUT

+   ,S_IN_PROGRESS

+   ,S_CMD_ERR

+   ,S_BLOCK_LOCKED_ERR

+   ,S_BLOCK_UNSTABLE

+   ,S_VPP_RANGE_ERR

+   ,S_ERASE_ADDR_ERR

+   ,S_ERASE_RANGE_ERR

+   ,S_PGM_AT_ODD_ADDR

+   ,S_PGM_WITH_ODD_LENGTH

+   ,S_BUFPGM_NO_SUPPORT

+   ,S_UNKNOWN_ERR

+} STATUS_E;

+

+/* COMMANDS */

+#define DA_EXT_CLOCK_CMD        0xD0

+#define DA_BBCHIP_TYPE_CMD      0xD1

+#define DA_SPEED_CMD            0xD2

+#define DA_MEM_CMD              0xD3

+#define DA_FORMAT_CMD           0xD4

+#define DA_WRITE_CMD            0xD5

+#define DA_READ_CMD             0xD6

+#define DA_WRITE_REG16_CMD      0xD7

+#define DA_READ_REG16_CMD       0xD8

+#define DA_FINISH_CMD           0xD9

+#define DA_GET_DSP_VER_CMD      0xDA

+#define DA_ENABLE_WATCHDOG_CMD  0xDB

+

+/* SPEED_PARA */

+typedef enum {

+   UART_BAUD_921600  = 0x01,

+   UART_BAUD_460800  = 0x02,

+   UART_BAUD_230400  = 0x03,

+   UART_BAUD_115200  = 0x04,

+   UART_BAUD_57600   = 0x05,

+   UART_BAUD_38400   = 0x06,

+   UART_BAUD_19200   = 0x07,

+   UART_BAUD_14400   = 0x08,

+   UART_BAUD_9600    = 0x09,

+   UART_BAUD_4800    = 0x0a,

+   UART_BAUD_2400    = 0x0b,

+   UART_BAUD_1200    = 0x0c,

+   UART_BAUD_300     = 0x0d,

+   UART_BAUD_110     = 0x0e,

+   UART_BAUD_AUTO    = 0x0f,	

+   

+}UART_BAUDRATE;

+

+typedef enum

+{

+   TIMEOUT_DATA = 0,

+   CKSUM_ERROR,

+   RX_BUFFER_FULL,

+   TIMEOUT_CKSUM_LSB,

+   TIMEOUT_CKSUM_MSB,

+   ERASE_TIMEOUT,

+   PROGRAM_TIMEOUT,

+   RECOVERY_BUFFER_FULL,

+   UNKNOWN_ERROR

+}eRX_error;

+

+/* DEVICE_INFO */

+typedef enum

+{

+   DEVICE_TV0057A003AABD,

+   DEVICE_LAST = DEVICE_TV0057A003AABD,

+   DEVICE_UNKNOWN = 0xFF         // Unknown Device 

+}DEVICE_INFO;

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_AIO_Flash_Download_Sample_Code_MCU_Base.zip b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_AIO_Flash_Download_Sample_Code_MCU_Base.zip
new file mode 100644
index 0000000..ef05251
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_AIO_Flash_Download_Sample_Code_MCU_Base.zip
Binary files differ
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_DL_api.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_DL_api.h
new file mode 100644
index 0000000..15ee44d
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/GPS_DL_api.h
@@ -0,0 +1,88 @@
+/*******************************************************************************

+*  Copyright Statement:

+*  --------------------

+*  This software is protected by Copyright and the information contained

+*  herein is confidential. The software may not be copied and the information

+*  contained herein may not be used or disclosed except with the written

+*  permission of MediaTek Inc. (C) 2016

+*

+******************************************************************************/

+

+/*******************************************************************************

+* Filename:

+* ---------

+*  GPS_DL_api.h

+*

+* Project:

+* --------

+*  GPS Download Library.

+*

+*******************************************************************************/

+#ifndef _GPS_DL_API_H_

+#define _GPS_DL_API_H_

+

+

+#define MAX_GPS_IMAGE_NUM 16

+

+#define GPS_FW_DOWNLOAD_OK 0

+#define GPS_FW_DOWNLOAD_UPLOAD_ERR -1  

+

+typedef int (*CALLBACK_DOWNLOAD_PROGRESS_INIT)(void *usr_arg);

+typedef int (*CALLBACK_DOWNLOAD_PROGRESS)(unsigned char finished_percentage,

+                                           unsigned int finished_bytes,

+                                           unsigned int total_bytes, void *usr_arg);

+

+typedef int (*CALLBACK_CONN_BROM_WRITE_BUF_INIT)(void *usr_arg);

+typedef int (*CALLBACK_CONN_BROM_WRITE_BUF)(unsigned char finished_percentage,

+                                           unsigned int sent_bytes,

+                                           unsigned int total_bytes, void *usr_arg);

+

+typedef struct{

+    const unsigned char     *m_image;  //buffer to store DA image

+    unsigned int            m_size;    //DA image size

+}GPS_DA;

+

+typedef struct{

+    const unsigned char     *m_image; // buffer to store firmware image 

+    unsigned int            m_size;   // firmware image size

+}GPS_Image;

+

+typedef struct{

+    unsigned int    m_num;

+    GPS_Image       m_image_list[MAX_GPS_IMAGE_NUM];

+}GPS_Image_List;

+

+typedef struct{

+   unsigned int      m_packet_length;

+   unsigned char     m_num_of_unchanged_data_blocks;

+   const unsigned char     *m_buf;

+   unsigned int      m_len;   

+   unsigned int      m_begin_addr; 

+   unsigned int      m_end_addr;

+}ROM_HANDLE_T;

+

+typedef struct{

+    int                                 m_bEnableLog;                   //can be used to enable or disable debug log

+    int *                               m_p_bootstop;                   //can be used to stop download process

+    CALLBACK_CONN_BROM_WRITE_BUF_INIT   m_cb_download_conn_da_init;     //callback function which is invoked at the beginning of DA transimitting.

+    void *                              m_cb_download_conn_da_init_arg; // parameter of the callback function upper

+    CALLBACK_CONN_BROM_WRITE_BUF        m_cb_download_conn_da;          //callback function which is invoked during the DA transimitting.

+    void *                              m_cb_download_conn_da_arg;      // parameter of the callback function upper

+}GPS_DA_Arg;

+

+typedef struct{

+    CALLBACK_DOWNLOAD_PROGRESS_INIT     m_cb_download_conn_init;        //callback function which is invoked at the beginning of firmware transimitting.

+    void *                              m_cb_download_conn_init_arg;    // parameter of the callback function upper

+    CALLBACK_DOWNLOAD_PROGRESS          m_cb_download_conn;             //callback function which is invoked during the firmware transimitting.

+    void *                              m_cb_download_conn_arg;         // parameter of the callback function upper

+    CALLBACK_CONN_BROM_WRITE_BUF_INIT   m_cb_download_conn_da_init;     //callback function which is invoked at the beginning of DA transimitting.

+    void *                              m_cb_download_conn_da_init_arg; // parameter of the callback function upper

+    CALLBACK_CONN_BROM_WRITE_BUF        m_cb_download_conn_da;          //callback function which is invoked during the DA transimitting.

+    void *                              m_cb_download_conn_da_arg;

+    int                                 m_bEnableLog;                   //can be used to enable or disable debug log

+    int *                               m_p_bootstop;                   //can be used to stop download process

+}GPS_Download_Arg;

+

+

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/bbchip_id.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/bbchip_id.h
new file mode 100644
index 0000000..58c3f41
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/bbchip_id.h
@@ -0,0 +1,38 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  bbchip_id.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  Baseband Chip Information.

+ *

+ *******************************************************************************/

+#ifndef  _ROM_ID_H_

+#define  _ROM_ID_H_

+

+//-----------------------------------------------------------------------------

+// FAT info                                                                    

+//-----------------------------------------------------------------------------

+typedef struct FlashDeviceKey {

+   unsigned short m_ManufactureId;

+   unsigned short m_DeviceCode;

+   unsigned short m_ExtDeviceCode1;

+   unsigned short m_ExtDeviceCode2;

+}s_FlashDeviceKey;

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom.h
new file mode 100644
index 0000000..6df8387
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom.h
@@ -0,0 +1,105 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom.h

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ *******************************************************************************/

+#ifndef _BROM_H_

+#define _BROM_H_

+

+

+#ifdef   __cplusplus

+extern "C" {

+#endif

+

+// The magic value to stop boot process 

+#define BOOT_STOP 9876

+

+

+//------------------------------------------------------------------------------

+// Boolean                                                                      

+//------------------------------------------------------------------------------

+typedef enum {

+   _FALSE = 0,

+   _TRUE = 1

+} _BOOL;

+

+//------------------------------------------------------------------------------

+// return code                                                                  

+//------------------------------------------------------------------------------

+

+#define BROM_RET(ret)   (ret&0x00FF0000)

+

+#define BROM_OK                           0x000000

+#define BROM_ERROR                        0x010000

+#define BROM_NO_MEMORY                    0x020000

+#define BROM_INVALID_ARGUMENTS            0x030000

+#define BROM_SET_COM_STATE_FAIL           0x040000

+#define BROM_PURGE_COM_FAIL               0x050000

+#define BROM_SET_META_REG_FAIL            0x060000

+#define BROM_SET_FLASHTOOL_REG_FAIL       0x070000

+#define BROM_SET_REMAP_REG_FAIL           0x080000

+#define BROM_SET_MEM_WAIT_STATE_FAIL      0x090000

+#define BROM_DOWNLOAD_DA_FAIL             0x0A0000

+#define BROM_CMD_START_FAIL               0x0B0000

+#define BROM_CMD_JUMP_FAIL                0x0C0000

+#define BROM_CMD_WRITE16_MEM_FAIL         0x0D0000

+#define BROM_CMD_READ16_MEM_FAIL          0x0E0000

+#define BROM_CMD_WRITE16_REG_FAIL         0x0F0000

+#define BROM_CMD_READ16_REG_FAIL          0x100000

+#define BROM_CMD_CHKSUM16_MEM_FAIL        0x110000

+#define BROM_CMD_WRITE32_MEM_FAIL         0x120000

+#define BROM_CMD_READ32_MEM_FAIL          0x130000

+#define BROM_CMD_WRITE32_REG_FAIL         0x140000

+#define BROM_CMD_READ32_REG_FAIL          0x150000

+#define BROM_CMD_CHKSUM32_MEM_FAIL        0x160000

+#define BROM_WR16_RD16_MEM_RESULT_DIFF    0x170000

+#define BROM_WR16_RD16_REG_RESULT_DIFF    0x180000

+#define BROM_WR32_RD32_MEM_RESULT_DIFF    0x190000

+#define BROM_WR32_RD32_REG_RESULT_DIFF    0x1A0000

+#define BROM_CHKSUM16_MEM_RESULT_DIFF     0x1B0000

+#define BROM_CHKSUM32_MEM_RESULT_DIFF     0x1C0000

+#define BROM_BBCHIP_HW_VER_INCORRECT      0x1D0000

+#define BROM_FAIL_TO_GET_BBCHIP_HW_VER    0x1E0000

+#define BROM_SKIP_BBCHIP_HW_VER_CHECK     0x1F0000

+#define BROM_UNKNOWN_BBCHIP               0x200000

+#define BROM_UNKNOWN_TGT_BBCHIP           0x210000

+#define BROM_BBCHIP_DSP_VER_INCORRECT     0x220000

+#define BROM_MULTIPLE_BAUDRATE_FAIL       0x230000

+#define BROM_JUMP_TO_NFB_DETECTION_FAIL   0x240000

+

+

+//------------------------------------------------------------------------------

+// boot FlashTool download mode                                                 

+//------------------------------------------------------------------------------

+typedef struct BOOT_FLASHTOOL_ARG{

+

+   // Download Agent 

+   unsigned int         m_da_start_addr;     // DA start address 

+   const unsigned char  *m_da_buf;           // buffer stored DA code 

+   unsigned int         m_da_len;            // length of DA buffer 

+

+} s_BOOT_FLASHTOOL_ARG;

+

+

+#ifdef   __cplusplus

+}

+#endif

+

+#endif

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.c
new file mode 100644
index 0000000..2ed1deb
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.c
@@ -0,0 +1,376 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom_base.cpp

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ * Description:

+ * ------------

+ *  BootRom communication functions implementation which are used to sync with BootRom.

+ *

+ *******************************************************************************/

+#include "DOWNLOAD.H"

+#include "brom_base.h"

+#include "GPS_DL_api.h"

+#include "flashtool.h"

+#include "sw_types.h"

+#include "gps_uart.h"

+#include <string.h>

+

+#include <fcntl.h>

+#include <pthread.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <stdarg.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <sys/stat.h>

+#include <unistd.h>

+#include <mtk_auto_log.h>

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+// BootRom Command 

+#define BOOT_ROM_WRITE_CMD    0xA1

+#define BOOT_ROM_CHECKSUM_CMD 0xA4

+#define BOOT_ROM_JUMP_CMD     0xA8

+

+

+//------------------------------------------------------------------------------

+// bootrom command                                                              

+//------------------------------------------------------------------------------

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_WriteBuf

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to download 'download agent' file(DA) to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  buf_in: DA file buffer.

+ *  num_of_byte: DA file size.

+ *

+ *******************************************************************************/

+int BRom_WriteBuf(

+      GPS_Download_Arg arg,

+      unsigned int ulBaseAddr,

+      const unsigned char *buf_in, unsigned int num_of_byte)

+{

+    const unsigned char *buf = (const unsigned char *)buf_in;

+    unsigned short data;

+    unsigned int num_of_word = (num_of_byte+1)/2;

+    int err;

+    unsigned char rate;

+    unsigned int finish_rate = 0;

+    unsigned int i = 0;

+    unsigned short checksum = 0;

+    unsigned short brom_checksum = 0;

+    unsigned int accuracy;

+    unsigned char write_buf[10];

+    unsigned char read_buf[10];

+    int j;

+

+    if( NULL==buf || 0>=num_of_byte )

+    {

+        return 1;

+    }

+

+    //Callback function of DA download initialize

+    if (arg.m_cb_download_conn_da_init != NULL)

+    {

+        arg.m_cb_download_conn_da_init(arg.m_cb_download_conn_da_init_arg);

+    }

+

+   if(BRom_CmdSend(arg, BOOT_ROM_WRITE_CMD ))

+      return 2;

+

+   LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): Send BaseAddr ");

+   

+   if((err=BRom_OutData(arg, ulBaseAddr)))

+   {

+       LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): BRom_OutData(%x): send base address fail!, Err(%d).", ulBaseAddr, err );

+       return 3;

+   }

+   

+   if((err=BRom_OutData(arg, num_of_word)))

+   {

+       LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): BRom_OutData(%d): send number of word fail!, num_of_byte(%d), Err(%d).", num_of_word, num_of_byte, err );

+        return 4;

+   }

+

+   // Set finish rate of callback function to 100(%)

+   accuracy = 100;

+   

+   LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): DA download Start ");

+

+   while( i < num_of_byte )

+   {

+       if( NULL!=arg.m_p_bootstop && BOOT_STOP==(*(arg.m_p_bootstop)) )

+       {

+           LOGE("[FUNET]BRom_Base::WriteData(): BOOT_STOP!, m_p_bootstop(0x%08X)=%u. ", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+          return 1;

+       }

+

+         // copy from buf to write_buf by swap order

+         for(j=0; j<10; j+=2)

+         {

+            write_buf[j] = buf[i+j+1];

+            write_buf[j+1] = buf[i+j];

+

+            data = (((unsigned short)write_buf[j])<<8)&0xFF00;

+            data |= ((unsigned short)write_buf[j+1])&0x00FF;

+

+            // update checksum

+            checksum ^= data;

+         }

+

+         // write 

+         // This function should be implemented by user.

+         GPS_UART_PutByte_Buffer((uint32 *) write_buf, 10);

+         

+

+         // read bootrom echo to verify

+         // This function should be implemented by user.

+         GPS_UART_GetByte_Buffer((uint32 *) read_buf, 10);

+

+         LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): Progress(%d%%),already:%d, to_do:%d ", (int)((float)i/(float)num_of_byte*100.0f),i,num_of_byte);

+         

+         if(memcmp(write_buf, read_buf, 10))

+         {

+             LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): write_buf={ %x, %x, %x, %x, %x, %x, %x, %x, %x, %x }. ", write_buf[0], write_buf[1], write_buf[2], write_buf[3], write_buf[4], write_buf[5], write_buf[6], write_buf[7], write_buf[8], write_buf[9]);

+             LOGE( "[FUNET]BRom_Base::BRom_WriteBuf():  read_buf={ %x, %x, %x, %x, %x, %x, %x, %x, %x, %x }. ", read_buf[0], read_buf[1], read_buf[2], read_buf[3], read_buf[4], read_buf[5], read_buf[6], read_buf[7], read_buf[8], read_buf[9]);

+             LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): write_buf != read_buf  ");

+            return 8;

+         }

+

+         // increase by 10, because we send 5 WORDs each time 

+         i += 10;

+         

+        //Callback function of DA download

+        if (arg.m_cb_download_conn_da!= NULL)

+        {

+             if( accuracy < (rate=(unsigned int)(((float)i/num_of_byte)*accuracy)) )

+             {

+                rate = accuracy;

+             }

+

+             if( 0 < (rate-finish_rate) )

+             {

+                finish_rate = rate;

+                // progress callback 

+                arg.m_cb_download_conn_da((unsigned char)finish_rate, i, num_of_byte, arg.m_cb_download_conn_da_arg);

+             }

+        }

+

+   }

+

+   // perform checksum verification

+   if((err=BRom_CheckSumCmd(arg, ulBaseAddr, num_of_word, &brom_checksum)))

+   {

+      LOGE( "[FUNET]BRom_Base::BRom_WriteBuf(): BRom_CheckSumCmd() fail!, Err(%d). ", err);

+      return 9;

+   }

+

+/*to_do_debug

+   // compare checksum

+   if( checksum != brom_checksum )

+   {

+       LOGE("[FUNET]BRom_Base::BRom_WriteBuf(): checksum error!, checksum(%x) != brom_checksum(%x) ", checksum, brom_checksum);

+      return 10;

+   }

+   else

+   {*/

+       LOGI("[FUNET]BRom_Base::BRom_WriteBuf(): checksum ok!, checksum(%x) == brom_checksum(%x). ", checksum, brom_checksum);

+   /*}*/

+

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CheckSumCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to request checksum which be calculated on target side.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  num_of_byte: DA file size.

+ *

+ * Output:

+ * --------

+ *  result: the received checksum. 

+ *

+ *******************************************************************************/

+int BRom_CheckSumCmd(GPS_Download_Arg arg, unsigned int ulBaseAddr, unsigned int num_of_word, unsigned short *result)

+{

+   int ret;

+

+   if(BRom_CmdSend(arg, BOOT_ROM_CHECKSUM_CMD ))

+      return 1;

+

+   if((ret=BRom_OutData(arg, ulBaseAddr)))

+   {

+      LOGE("[FUNET]BRom_Base::BRom_CheckSumCmd(): BRom_OutData(%x): send base address fail!, Err(%d). ", ulBaseAddr, ret);

+      return 2;

+   }

+   

+   if((ret=BRom_OutData(arg, num_of_word)))

+   {

+      LOGE("[FUNET]BRom_Base::BRom_CheckSumCmd(): BRom_OutData(%d): send number of word fail!, Err(%d). ", num_of_word, ret);

+      return 3;

+   }

+

+   *result = GPS_UART_GetData16();

+

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_JumpCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to jump to DA start address to execute DA in internal SRAM.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  addr: the start address of DA in internal SRAM.

+ *

+ *******************************************************************************/

+int BRom_JumpCmd(GPS_Download_Arg arg, unsigned int addr)

+{

+   int ret;

+   

+   if(BRom_CmdSend(arg, BOOT_ROM_JUMP_CMD ))

+      return 1;

+

+   if((ret=BRom_OutData(arg, addr)))

+   {

+       LOGE("[FUNET]BRom_Base::BRom_JumpCmd(): BRom_OutData(%x): send jump address fail!, Err(%d). ", addr, ret);

+      return 2;

+   }

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CmdSend

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send one byte data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  cmd: the ont byte data want to be sent.

+ *

+ *******************************************************************************/

+

+int BRom_CmdSend(GPS_Download_Arg arg, unsigned char cmd)

+{

+   unsigned char result;

+   unsigned char *p_result;

+

+   p_result = &result;

+   

+   if( NULL!=arg.m_p_bootstop && BOOT_STOP==(*(arg.m_p_bootstop)) ) 

+   {

+       LOGE("BRom_StartCmd: BOOT_STOP!, m_p_bootstop(0x%08X)=%u.", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+       return (BROM_CMD_START_FAIL+6);

+   }

+

+   GPS_UART_PutByte(cmd); 

+   

+   *p_result = GPS_UART_GetByte();

+

+   if( cmd != *p_result )

+   {

+     LOGE("BRom_Base::BRom_CmdSend(0x%02X): bootrom response is incorrect!, cmd(0x%02X) != result(0x%02X).", cmd, cmd, *p_result);

+      return 4;

+   }

+   else

+      return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_OutData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send 32-bits data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *  GPS_UART_PutData32/GPS_UART_GetData32 should be implemented by user.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  data: 32-bits data want to be sent.

+ *

+ *******************************************************************************/

+int BRom_OutData(GPS_Download_Arg arg, unsigned int data)

+{

+   unsigned int tmp32;

+

+   if( NULL!=arg.m_p_bootstop && BOOT_STOP==(*(arg.m_p_bootstop)) ) 

+   {

+       LOGE("BRom_StartCmd: BOOT_STOP!, m_p_bootstop(0x%08X)=%u.", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+       return (BROM_CMD_START_FAIL+6);

+   }

+

+   GPS_UART_PutData32(data);

+   

+    tmp32 = GPS_UART_GetData32();

+

+    if (tmp32 != data)

+     return 4;

+

+   return 0;

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.h
new file mode 100644
index 0000000..ca8df29
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_base.h
@@ -0,0 +1,178 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom_base.h

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ * Description:

+ * ------------

+ *  BootRom communication functions implementation which are used to sync with BootRom.

+ *

+ *******************************************************************************/

+#ifndef   _BROM_BASE_H_

+#define   _BROM_BASE_H_

+

+#include "brom.h"

+#include "bbchip_id.h"

+#include "GPS_DL_api.h"

+#include <stdio.h>

+   

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_StartCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send SYNC_CHAR to build connection with bootRom.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int BRom_StartCmd(GPS_Download_Arg arg);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  Boot_FlashTool

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to build connection with bootRom and download DA to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  p_arg: download arguments structure includes start address, DA buffer and DA length.

+ *

+ *******************************************************************************/

+int Boot_FlashTool(const s_BOOT_FLASHTOOL_ARG  *p_arg, GPS_Download_Arg arg);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_WriteBuf

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to download 'download agent' file(DA) to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  buf_in: DA file buffer.

+ *  num_of_byte: DA file size.

+ *

+ *******************************************************************************/

+int BRom_WriteBuf(GPS_Download_Arg arg,

+                        unsigned int ulBaseAddr,

+                        const unsigned char *buf_in, 

+                        unsigned int num_of_byte);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CheckSumCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to request checksum which be calculated on target side.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  u1BaseAddr: the start address of DA in internal SRAM.

+ *  num_of_byte: DA file size.

+ *

+ * Output:

+ * --------

+ *  result: the received checksum. 

+ *

+ *******************************************************************************/

+int BRom_CheckSumCmd(GPS_Download_Arg arg, unsigned int baseaddr,

+                        unsigned int num_of_word, unsigned short *result);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_JumpCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to jump to DA start address to execute DA in internal SRAM.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  addr: the start address of DA in internal SRAM.

+ *

+ *******************************************************************************/

+int BRom_JumpCmd(GPS_Download_Arg arg, unsigned int addr);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_CmdSend

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send one byte data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  cmd: the ont byte data want to be sent.

+ *

+ *******************************************************************************/

+int BRom_CmdSend(GPS_Download_Arg arg, unsigned char cmd);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_OutData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send 32-bits data to UART and check received data.

+ *  'BL_PRINT' is a sample to output debug log.

+ *  GPS_UART_PutData32/GPS_UART_GetData32 should be implemented by user.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  data: 32-bits data want to be sent.

+ *

+ *******************************************************************************/

+int BRom_OutData(GPS_Download_Arg arg, unsigned int data);

+

+#endif

+//-----------------------------------------------------------------------------

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_mt3301.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_mt3301.c
new file mode 100644
index 0000000..f725f50
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/brom_mt3301.c
@@ -0,0 +1,318 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  brom_mt3301.cpp

+ *

+ * Project:

+ * --------

+ *  BootRom Library

+ *

+ * Description:

+ * ------------

+ *  BootRom communication functions implementation which are used to sync with BootRom.

+ *

+ *******************************************************************************/

+#include <stdio.h>

+#include "flashtool.h"

+#include "gps_uart.h"

+#include "brom_base.h"

+#include "sw_types.h"

+

+

+#include <fcntl.h>

+#include <pthread.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <stdarg.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <sys/stat.h>

+#include <unistd.h>

+#include "mt3333_controller.h"

+#include "mnl_common.h"

+#include "gps_controller.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+// MT3301 BootRom Start Command

+#define MT3301_BOOT_ROM_START_CMD1      0xA0

+#define MT3301_BOOT_ROM_START_CMD2      0x0A

+#define MT3301_BOOT_ROM_START_CMD3      0x50

+#define MT3301_BOOT_ROM_START_CMD4      0x05

+

+#define NMEA_START_CMD1         '$'

+#define NMEA_START_CMD2         'P'

+#define NMEA_START_CMD3         'M'

+#define NMEA_START_CMD4         'T'

+#define NMEA_START_CMD5         'K'

+#define NMEA_START_CMD6         '1'

+#define NMEA_START_CMD7         '8'

+#define NMEA_START_CMD8         '0'

+#define NMEA_START_CMD9         '*'

+#define NMEA_START_CMD10        '3'

+#define NMEA_START_CMD11        'B'

+#define NMEA_START_CMD12      0x0D

+#define NMEA_START_CMD13      0x0A

+

+

+static const unsigned char MT3301_BOOT_ROM_START_CMD[] =

+{

+   MT3301_BOOT_ROM_START_CMD1,

+   MT3301_BOOT_ROM_START_CMD2,

+   MT3301_BOOT_ROM_START_CMD3,

+   MT3301_BOOT_ROM_START_CMD4

+};                              

+

+static unsigned char NMEA_START_CMD[] =

+{

+   NMEA_START_CMD1,

+   NMEA_START_CMD2,

+   NMEA_START_CMD3,

+   NMEA_START_CMD4,

+   NMEA_START_CMD5,

+   NMEA_START_CMD6,

+   NMEA_START_CMD7,

+   NMEA_START_CMD8,

+   NMEA_START_CMD9,

+   NMEA_START_CMD10, 

+   NMEA_START_CMD11, 

+   NMEA_START_CMD12, 

+   NMEA_START_CMD13 

+};                              

+extern int g_fd_mt3333_data;    

+extern MNL_CONFIG_T mnld_cfg;

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  BRom_StartCmd

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send SYNC_CHAR to build connection with bootRom.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int BRom_StartCmd(GPS_Download_Arg arg)

+{

+    unsigned char data8;

+    unsigned long i;

+    unsigned char tmp8;

+    unsigned long cnt = 0;

+    int retry_max=5;

+#if 0

+    LOGE("[FUNET]Send PMTK180 to force MT3333/39 into boot rom mode");

+    //Send PMTK180 to force 3333 into boot rom

+    GPS_UART_PutByte_Buffer((unsigned long *)NMEA_START_CMD, sizeof(NMEA_START_CMD));

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,115200, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return 1;

+    }

+    //delay 500ms. 

+    usleep(500 * 1000);

+    GPS_UART_IgnoreData();

+

+#else

+    LOGE("[FUNET]Send PMTK180 to force MT3333/39 into boot rom mode");

+    //Send PMTK180 to force 3333 into boot rom

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,921600, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return 1;

+    }

+    GPS_UART_PutByte_Buffer((unsigned long *)NMEA_START_CMD, sizeof(NMEA_START_CMD));

+    //delay 500ms. 

+    usleep(500 * 1000);

+    GPS_UART_IgnoreData();

+

+    UNUSED(arg);

+    //usleep(3000 * 1000);

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,115200, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return 1;

+    }

+

+    LOGI("[FUNET]Send first sync char111");

+    //mnl_get_rdelay();

+    //mnl_set_rdelay(1500);

+    //mnl_get_rdelay();

+    pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;

+

+HADK_AWAKE_BEGIN:

+    cnt = 0;

+    pthread_mutex_lock(&mutx);

+    //for(int j=0; j<2048 ;j++){GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[0]);}

+    mnl_set_pwrctl(0);

+    mnl_set_pwrctl(1);

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[0]);

+    pthread_mutex_unlock(&mutx);

+#endif

+    while(1)

+    {

+        GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[0]); //First start command sync char

+        if(1 == GPS_UART_GetByte_NO_TIMEOUT(&data8))

+        {

+             tmp8 = 0x5F;

+             LOGE("[FUNET]Received data:%x", data8);

+             if(tmp8 == data8)

+             {

+                 LOGE("[FUNET] First char sync ok");

+                 goto SECOND_CHAR;    

+             }

+        }

+        else

+        {

+            LOGE("[FUNET]No data received");

+        }

+

+        cnt++;

+        if (cnt > 20000)

+        {

+            cnt = 0;

+            retry_max--;

+            LOGE("[FUNET] First char sync timeout,retry=%d",retry_max);

+            if(retry_max > 0){

+                mnl_set_pwrctl(0);

+                usleep(100 * 1000);

+                goto HADK_AWAKE_BEGIN;

+            }

+            return 1;

+        }

+    }

+

+

+SECOND_CHAR:

+    cnt=0;

+    GPS_UART_IgnoreData();

+    LOGE("[FUNET]Sync second char");

+

+    i = 1;

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[i]); //2nd sync char

+    tmp8 = 0xF5; // ~MT3301_BOOT_ROM_START_CMD[i]

+SECOND_CHAR_1:    

+    data8 = GPS_UART_GetByte();

+    if(tmp8 != data8)

+    {

+        LOGE("[FUNET]Wrong ack data received:%x", data8);

+        if(data8 == 0x5F){

+            goto SECOND_CHAR_1;

+        }

+        retry_max--;

+        LOGE("[FUNET] Second char sync timeout,retry=%d",retry_max);

+        if(retry_max > 0){

+            mnl_set_pwrctl(0);

+            usleep(100 * 1000);

+            goto HADK_AWAKE_BEGIN;

+        }

+        return 1;

+    }

+

+    LOGE("[FUNET]Sync third char");

+    i = 2;

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[i]); //3rd sync char

+    tmp8 = 0xAF;

+    data8 = GPS_UART_GetByte();

+    if(tmp8 != data8)

+    {

+        LOGE( "[FUNET]Wrong ack data received:%x", data8);

+        

+        retry_max--;

+        LOGE("[FUNET] Third char sync timeout,retry=%d",retry_max);

+        if(retry_max > 0){

+            mnl_set_pwrctl(0);

+            usleep(100 * 1000);

+            goto HADK_AWAKE_BEGIN;

+        }

+        return 1;

+    }

+

+    LOGE("[FUNET]Sync forth char");

+    i = 3;

+    GPS_UART_PutByte(MT3301_BOOT_ROM_START_CMD[i]); //4th sync char

+    tmp8 = 0xFA;

+    data8 = GPS_UART_GetByte();

+    if(tmp8 != data8)

+    {

+        LOGE("[FUNET]Wrong ack data received:%x", data8);

+        

+        retry_max--;

+        LOGE("[FUNET] Four char sync timeout,retry=%d",retry_max);

+        if(retry_max > 0){

+            mnl_set_pwrctl(0);

+            usleep(100 * 1000);

+            goto HADK_AWAKE_BEGIN;

+        }

+        return 1;

+    }

+

+    return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  Boot_FlashTool

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to build connection with bootRom and download DA to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  p_arg: download arguments structure includes start address, DA buffer and DA length.

+ *

+ *******************************************************************************/

+int Boot_FlashTool(const s_BOOT_FLASHTOOL_ARG  *p_arg, GPS_Download_Arg arg)

+{

+   // check data

+   if( NULL == p_arg )

+      return BROM_INVALID_ARGUMENTS;

+

+   LOGI("[FUNET]Enter BRom_StartCmd");

+

+   // send start command 

+   if( BRom_StartCmd(arg) )

+   {

+       return BROM_CMD_START_FAIL;

+   }

+   LOGI( "[FUNET]Start Command Sync Done");

+

+   if(BRom_WriteBuf(arg, p_arg->m_da_start_addr, p_arg->m_da_buf, p_arg->m_da_len))

+   {

+      return BROM_DOWNLOAD_DA_FAIL;

+   }

+

+   LOGI("[FUNET]Boot_FlashTool: BRom_WriteBuf() Pass!");

+

+   // jump to m_da_start_addr to execute DA code on Internal SRAM 

+   if(BRom_JumpCmd( arg, p_arg->m_da_start_addr ))

+      return BROM_CMD_JUMP_FAIL;

+   LOGI("[FUNET]Boot_FlashTool: BRom_JumpCmd() Pass!");

+   return BROM_OK;

+}

+//------------------------------------------------------------------------------

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c
new file mode 100644
index 0000000..567e737
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c
@@ -0,0 +1,774 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  da_cmd.cpp

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  DA(Download Agent) handshake command.

+ *

+ *******************************************************************************/

+#include "brom_base.h"

+#include "da_cmd.h"

+#include "sw_types.h"

+#include "gps_uart.h"

+#include <string.h>

+

+#include <fcntl.h>

+#include <pthread.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <stdarg.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <sys/stat.h>

+#include <unistd.h>

+#include "mt3333_controller.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+#define UART_BAUDRATE_SYNC_RETRY      50

+#define PACKET_RE_TRANSMISSION_TIMES   3

+#define DA_FLASH_ERASE_WAITING_TIME      1000

+

+const unsigned int g_BaudrateTable[] = {

+   921600,  // 0x01 

+   460800,  // 0x02 

+   230400,  // 0x03 

+   115200,  // 0x04 

+   57600,   // 0x05 

+   38400,   // 0x06 

+   19200,   // 0x07 

+   9600,    // 0x08 

+   4800,    // 0x09 

+   2400,    // 0x0a 

+   1200,    // 0x0b 

+   300,     // 0x0c

+   110,     // 0x0d

+   14400    // 0x0e

+};

+extern int g_fd_mt3333_data;

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  write_buf: data buffer want to be sent.

+ *  write_len: data length.

+ *

+ *******************************************************************************/

+int WriteData(GPS_Download_Arg arg, const void *write_buf, unsigned int write_len) {

+

+    unsigned int BytesOfWriiten = 0;

+    unsigned int rest_of_bytes = 0;

+    unsigned long wbytes = 0;

+    unsigned short RetryCount = 0;

+

+    if( NULL == write_buf || 0 >= write_len ) {

+        LOGE("DA_cmd::WriteData(): invalid arguments, write_buf(0x%08X), write_len(%u).", (unsigned int)write_buf, write_len);

+        return 1;

+    }

+

+    RetryCount = 0;

+    BytesOfWriiten = 0;

+    while( BytesOfWriiten < write_len ) 

+    {

+        // check stop flag 

+        if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) ) {

+            LOGE( "DA_cmd::WriteData(): m_stopflag(0x%08X)=%d, force to stop!", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+            return 2;

+        }

+        wbytes = 0;

+        rest_of_bytes = write_len-BytesOfWriiten;

+        GPS_UART_PutByte_Buffer((uint32 *) write_buf, rest_of_bytes);

+

+        //update write bytes

+        BytesOfWriiten += rest_of_bytes;

+

+    }

+

+    LOGE("DA_cmd::WriteData(): OK. total=(%u/%u).", BytesOfWriiten, write_len);

+    return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  ReadData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to read ack from target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  read_buf: data buffer want to be read.

+ *  read_len: data length.

+ *

+ *******************************************************************************/

+int ReadData(GPS_Download_Arg arg, void *read_buf, unsigned int read_len)

+{

+   unsigned int BytesOfRead = 0;

+   unsigned int rest_of_bytes = 0;

+   unsigned long rbytes = 0;

+   unsigned short RetryCount = 0;

+

+   if( NULL == read_buf || 0 >= read_len )

+   {

+      LOGE("DA_cmd::ReadData(): invalid arguments, read_buf(0x%08X), read_len(%u).", (unsigned int)read_buf, read_len);

+      return 1;

+   }

+

+   // initialize read buffer

+   memset(read_buf, '\0' , read_len);

+

+   RetryCount = 0;

+   BytesOfRead = 0;

+   while( BytesOfRead < read_len )

+   {

+      // check stop flag 

+      if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) )

+      {

+         LOGE("DA_cmd::ReadData(): m_stopflag(0x%08X)=%d, force to stop!", (unsigned int)arg.m_p_bootstop, *(arg.m_p_bootstop));

+         return 2;

+      }

+   

+      rbytes = 0;

+      rest_of_bytes = read_len-BytesOfRead;

+	  

+	  GPS_UART_GetByte_Buffer((uint32 *) read_buf, rest_of_bytes);

+

+	  BytesOfRead += rest_of_bytes;

+

+   }

+

+   LOGE( "DA_cmd::ReadData(): OK. total=(%u/%u).", BytesOfRead, read_len);

+   return 0;

+}

+

+

+int CMD_ChangeUartSpeed(GPS_Download_Arg arg, unsigned char max_full_sync_count) 

+{

+

+   unsigned char buf[3];

+   volatile unsigned char data8;

+   //int ret;

+   int i;

+   unsigned char BaudrateId = 0x01; //921600, refer to g_BaudrateTable

+   volatile unsigned char full_sync_char;

+   //unsigned char count;

+

+   // send speed change command 

+   buf[0] = DA_SPEED_CMD;

+   buf[1] = BaudrateId;

+   buf[2] = max_full_sync_count;

+   LOGE("send DA_SPEED_CMD(0x%02X) + BaudrateId(0x%02X) + FULL_SYNC_CNT(0x%02X).", buf[0], buf[1], buf[2]);

+   if(WriteData( arg, buf, 3))

+   {

+      return 2;

+   }

+

+   // read ack 

+   LOGE( "wait for ACK.");

+   LOGE( " before: buf 0x%x", buf[0]);

+   if(ReadData( arg, buf, 1))

+   {

+      return 3;

+   }

+   if( ACK != buf[0] ) {

+      LOGE( "non-ACK(0x%02X) return.", buf[0]);

+      return 4;

+   }

+   // wait 2523 side UART baudrate change to 921600bps

+   LOGE( "Wait 2523 side baudrate change to BaudrateId(%u)=%u successfully.", BaudrateId, g_BaudrateTable[BaudrateId-1]);

+	

+   // sleep awhile for target uart state machine is ready 

+   if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,921600, 8, 'N', 1)){

+		LOGE("configure uart baudrate failed");

+		return 1;

+	}

+   usleep(100*1000);

+

+   // sync mechanism: wait for baudrate change is done on both Target and PC sides 

+      for(i=0; i<UART_BAUDRATE_SYNC_RETRY; i++) 

+      {

+         // send sync char 

+         buf[0] = SYNC_CHAR;

+		 if(WriteData( arg, buf, 1))

+         {

+			LOGE(" Write SYNC_CHAR failed");

+            continue;

+         }

+

+         // wait for sync char

+         if( !ReadData( arg, buf, 1) ) 

+         {

+            if( SYNC_CHAR == buf[0] ) 

+            {

+               // receive correct SYNC_CHAR 

+               LOGE( "SYNC(%u): SYNC_CHAR(0x%02X) received!", g_BaudrateTable[BaudrateId-1], buf[0]);

+               break;

+            }

+            else 

+            {

+               // receive non-SYNC_CHAR

+               LOGE( "SYNC(%u): non-SYNC_CHAR(0x%02X) received, keep on sync.", g_BaudrateTable[BaudrateId-1], buf[0]);

+            }

+         }

+         else 

+         {

+            // wait for SYNC_CHAR timeout

+            LOGE( "SYNC(%u): sync timeout, keep on sync.", g_BaudrateTable[BaudrateId-1]);

+         }

+      }

+

+      // if fail over UART_BAUDRATE_SYNC_RETRY times, return error 

+      if( UART_BAUDRATE_SYNC_RETRY <= i ) 

+      {

+         LOGE( "SYNC(%u): retry %d times and sync fail!", g_BaudrateTable[BaudrateId-1], i);

+         return 6;

+      }

+

+      // send pc side purge ok ack 

+      //buf[0] = ACK;

+      LOGE( "SYNC(%u): send PC side TX & RX purge ok ACK. ", g_BaudrateTable[BaudrateId-1]);

+	  do

+	  {

+		  buf[0] = ACK;

+		  if(WriteData(arg, buf, 1)) 

+		  {

+			 return 8;

+		  }

+

+		  // wait for target side TX & RX purge ok ACK 

+		  LOGE( "SYNC(%u): wait for target side TX & RX purge ok ACK.", g_BaudrateTable[BaudrateId-1]);

+		  if( !ReadData(arg, buf, 1) ) 

+		  {

+			 if( ACK != buf[0] ) 

+			 {

+				LOGE( "SYNC(%u): non-ACK(0x%02X) received!", g_BaudrateTable[BaudrateId-1], buf[0]);

+				//return 9;

+			 }

+		  }

+		  else 

+		  {

+			 LOGE("SYNC(%u): ReadData(): fail. ", g_BaudrateTable[BaudrateId-1]);

+			 return 10;

+		  }

+	  }while (ACK != buf[0]);

+

+	  

+	  /*if(WriteData(com_driver, arg, buf, 1)) {

+         return 8;

+      }

+

+      // wait for target side TX & RX purge ok ACK 

+      MTRACE(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): SYNC(%lu): wait for target side TX & RX purge ok ACK.", g_BaudrateTable[BaudrateId-1]);

+      if( 0 == (ret=ReadData(com_driver, arg, buf, 1)) ) 

+      {

+         if( ACK != buf[0] ) 

+         {

+            MTRACE_ERR(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): SYNC(%lu): non-ACK(0x%02X) received!", g_BaudrateTable[BaudrateId-1], buf[0]);

+            return 9;

+         }

+      }

+      else 

+      {

+         MTRACE_ERR(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): SYNC(%lu): ReadData(): fail, Err(%d). ", g_BaudrateTable[BaudrateId-1], ret);

+         return 10;

+      }*/

+      LOGE( "SYNC(%u): ACK(0x%02X) received, sync ok!", g_BaudrateTable[BaudrateId-1], buf[0]);

+

+      if( 0 < max_full_sync_count ) {

+         LOGE( "FULL_SYNC(%u): full sync all char to observe if baudrate is stable.", g_BaudrateTable[BaudrateId-1]);

+         full_sync_char = 0;

+         while(1) {

+

+            for(i=0; i<max_full_sync_count; i++) {

+

+               // fill sync char 

+               data8 = full_sync_char;

+

+               // send sync char 

+               if(WriteData(arg, (const void *)&data8, 1)) {

+                  // write fail 

+                  LOGE("FULL_SYNC(%u)[%u]: can't write KEEP_SYNC_CHAR(0x%02X) to target, full sync fail, baudrate is not stable!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char);

+                  return 11;

+               }

+

+               // wait for sync char 

+               if(!ReadData(arg, buf, 1)) {

+                  if( full_sync_char != buf[0] ) {

+                     // receive non-SYNC_CHAR 

+                     LOGE( "FULL_SYNC(%u)[%u]: expect KEEP_SYNC_CHAR(0x%02X), but receive 0x%02X, full sync fail, baudrate is not stable!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char, buf[0]);

+                     return 12;

+                  }

+               }

+               else {

+                  // wait for SYNC_CHAR timeout 

+                  LOGE( "FULL_SYNC(%u)[%u]: wait for KEEP_SYNC_CHAR(0x%02X) timeout, full sync fail, baudrate is not stable!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char);

+                  return 13;

+               }

+            //MTRACE(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): FULL_SYNC(%lu)[%u]: expect KEEP_SYNC_CHAR(0x%02X), receive 0x%02X, That's right!!", g_BaudrateTable[BaudrateId-1], i, full_sync_char, buf[0]);

+            }

+            

+            if( 0xFF > full_sync_char ) {

+               //MTRACE(g_hBROM_DEBUG, "DA_cmd::CMD_ChangeUartSpeed(): FULL_SYNC(%lu)[%u]: KEEP_SYNC_CHAR(0x%02X) done.", g_BaudrateTable[BaudrateId-1], i, full_sync_char);

+               full_sync_char++;

+            }

+            else {

+               break;

+            }

+         }

+         LOGE("FULL_SYNC(%u): successful!", g_BaudrateTable[BaudrateId-1]);

+      }

+      else {

+         LOGE( "skip FULL_SYNC(%u) procedure after baudrate changed.", g_BaudrateTable[BaudrateId-1]);

+      }

+

+   LOGE( " OK!");

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_SetMemBlock

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to set download memory block.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *

+ *******************************************************************************/

+int CMD_SetMemBlock(GPS_Download_Arg arg, ROM_HANDLE_T  *dl_handle)

+{

+   unsigned char buf[4];

+   unsigned int begin_addr;

+   unsigned int end_addr;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): invalid arguments! dl_handle(%x).", (unsigned int)dl_handle);

+      return 1;

+   }

+

+   // send mem block command

+   buf[0] = DA_MEM_CMD;

+   buf[1] = 0x01;

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): send DA_MEM_CMD(%x) + MEM_BLOCK_COUNT(%x).",  buf[0], buf[1]);

+   if(WriteData(arg, buf, 2))

+   {

+      return 2;

+   }

+

+   // send MEM begin addr, end addr

+	// MOD with 0x08000000(bank1 start address), because our maui_sw remap flash to bank1 on MT6218B series project. 

+	begin_addr = dl_handle->m_begin_addr%0x08000000;

+	end_addr = dl_handle->m_end_addr%0x08000000;

+

+	// send begin addr, high byte first

+	buf[0] = (unsigned char)((begin_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((begin_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((begin_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((begin_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_BEGIN_ADDR( %x%x%x%x).", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 3;

+	}

+

+	// send end addr, high byte first

+	buf[0] = (unsigned char)((end_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((end_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((end_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((end_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_END_ADDR(%x%x%x%x).", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 4;

+	}

+

+   // read ack 

+	LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): wait for ACK..");

+   if(ReadData(arg, buf, 1))

+   {

+      return 5;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): non-ACK(%x) return.", buf[0]);

+	  return 6;

+   }

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): ACK(%x) OK!", buf[0]);

+   if(ReadData(arg, buf, 1))

+   {

+      return 7;

+   }

+   dl_handle->m_num_of_unchanged_data_blocks = buf[0];

+   LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): UNCHANED_DATA_BLOCKS=( %x)", dl_handle->m_num_of_unchanged_data_blocks);

+   return 0;   

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_Finish

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send finish command to notify target download process is over.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int CMD_Finish(GPS_Download_Arg arg)

+{

+   unsigned char buf[2];

+

+   UNUSED(arg);

+   // send DA_FINISH_CMD command

+   buf[0] = DA_FINISH_CMD;

+   GPS_UART_PutByte(buf[0]); 

+   LOGE( "[FUNET]DA_cmd::CMD_Finish(): OK!");

+   return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *  cb_download_flash_init: callback function which is invoked at the beginning of transimitting.

+ *  cb_download_flash_init_arg: parameter of initial callback function.

+ *  cb_download_flash: callback function which is invoked during the transimitting.

+ *  cb_download_flash_arg: parameter of  callback function upper.

+ *

+ *******************************************************************************/

+int CMD_WriteData(

+      GPS_Download_Arg arg,

+      ROM_HANDLE_T  *dl_handle,

+      CALLBACK_DOWNLOAD_PROGRESS_INIT  cb_download_flash_init,  void *cb_download_flash_init_arg,

+      CALLBACK_DOWNLOAD_PROGRESS  cb_download_flash,  void *cb_download_flash_arg)

+{

+   static const char ErrAckTable[][64]= {

+      "TIMEOUT_DATA",

+      "CKSUM_ERROR",

+      "RX_BUFFER_FULL",

+      "TIMEOUT_CKSUM_LSB",

+      "TIMEOUT_CKSUM_MSB",

+      "ERASE_TIMEOUT",

+      "PROGRAM_TIMEOUT",

+      "RECOVERY_BUFFER_FULL",

+      "UNKNOWN_ERROR"

+   };

+   unsigned char buf[5];

+   unsigned int finish_rate = 0;

+   unsigned int total_bytes = 0;

+   unsigned int total_sent_bytes = 0;

+   unsigned int accuracy;

+   int ret;

+   unsigned int sent_bytes;

+   unsigned int retry_count=0;

+   unsigned int j;

+   unsigned int rate;

+   unsigned short checksum;

+   unsigned int frame_bytes;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): invalid arguments! dl_handle( %x)..", (unsigned int)dl_handle);

+      return 1;

+   }

+

+   total_bytes = dl_handle->m_len;

+

+   // send write command + packet length

+   buf[0] = DA_WRITE_CMD;

+   buf[1] = (unsigned char)((dl_handle->m_packet_length>>24) &0x000000FF);

+   buf[2] = (unsigned char)((dl_handle->m_packet_length>>16) &0x000000FF);

+   buf[3] = (unsigned char)((dl_handle->m_packet_length>>8)  &0x000000FF);

+   buf[4] = (unsigned char)((dl_handle->m_packet_length)     &0x000000FF);

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): send DA_WRITE_CMD( %x), PACKET_LENGTH( %x%x%x%x)=%u..", buf[0], buf[1], buf[2], buf[3], buf[4], dl_handle->m_packet_length);

+   if(WriteData(arg, buf, 5))

+   {

+      return 3;

+   }

+

+   // initialization callback

+   if( NULL != cb_download_flash_init )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash_init().");

+	  cb_download_flash_init(cb_download_flash_init_arg);

+   }

+

+   // Set finish rate of callback function to 100(%)

+   accuracy = 100;

+

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).", ret);

+      return 4;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to save all the unchanged data from flash!", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 5;

+   }

+

+   // wait for 1st sector erase done 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for 1st sector erase done.");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+      return 6;

+   }

+

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to erase the 1st sector!.", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 7;

+   }

+

+   // send all rom files

+   finish_rate = 0;

+   total_sent_bytes = 0;

+	// send each rom file

+	sent_bytes = 0;

+	retry_count = 0;

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %d bytes, total_sent_bytes=%d/%d..", dl_handle->m_len, total_sent_bytes, total_bytes);

+	while( sent_bytes < dl_handle->m_len )

+	{

+

+	re_transmission:

+

+	 // reset the frame checksum

+	 checksum = 0;

+

+	 // if the last frame is less than PACKET_LENGTH bytes

+	 if( dl_handle->m_packet_length > (dl_handle->m_len-sent_bytes) )

+	 {

+	    frame_bytes = dl_handle->m_len - sent_bytes;

+	 }

+	 else

+	 {

+	    // the normal frame

+	    frame_bytes = dl_handle->m_packet_length;

+	 }

+

+	  GPS_UART_PutByte_Buffer((uint32 *) (dl_handle->m_buf+sent_bytes), frame_bytes);

+

+	 // calculate checksum

+	 for(j=0; j<frame_bytes; j++)

+	 {

+	    // WARNING: MUST make sure it unsigned value to do checksum

+	    checksum += dl_handle->m_buf[sent_bytes+j];

+	 }

+

+	 // send 2 bytes checksum, high byte first

+	 buf[0] = (unsigned char)((checksum>> 8)&0x000000FF);

+	 buf[1] = (unsigned char)((checksum)    &0x000000FF);

+	 

+	 if(WriteData(arg, buf, 2))

+	 {

+	    goto read_cont_char;

+	 }

+

+	read_cont_char:

+	 // read CONT_CHAR

+	 buf[0] = 0xEE;

+	 if( 0 != (ret=ReadData(arg, buf, 1)) )

+	 {

+		LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).",ret);

+		return 8;

+	 }

+	 LOGE("[FUNET]CONT_CHART Received( %x).", buf[0]);

+

+	 switch(buf[0])

+	 {

+	    case CONT_CHAR:

+	       // sent ok!, reset retry_count			   

+		   LOGE( "[FUNET]CONT_CHART Ok( %x).", buf[0]);

+	       retry_count = 0;

+	       break;

+	    case ERASE_TIMEOUT:

+		   return 9;

+	    case PROGRAM_TIMEOUT:

+		   return 10;

+	    case RECOVERY_BUFFER_FULL:

+		   return 11;

+	    case RX_BUFFER_FULL:

+	    case CKSUM_ERROR:

+	    case TIMEOUT_DATA:

+	    case TIMEOUT_CKSUM_LSB:

+	    case TIMEOUT_CKSUM_MSB:

+	    default:

+	       // check retry times

+	       if( PACKET_RE_TRANSMISSION_TIMES > retry_count )

+	       {

+	          retry_count++;

+	       }

+	       else

+	       {

+	          // fail to re-transmission

+	          // send NACK to wakeup DA to stop

+	          buf[0] = NACK;

+			  if(WriteData(arg, buf, 1))

+	          {

+				 LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          }

+	          return 12;

+	       }

+

+	       // wait for DA clean RX buffer

+		   if( 0 != (ret=ReadData(arg, buf, 1)) )

+	       {

+	          LOGE( "DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+	          LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 13;

+	       }

+		   

+	       if( ACK != buf[0] )

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): wrong ack(0x%02X) return!", retry_count, buf[0]);

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 14;

+	       }

+

+	       // send CONT_CHAR to wakeup DA to start recieving again

+	       buf[0] = CONT_CHAR;

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): send CONT_CHAR to wakeup DA to start recieving again.", retry_count);

+		   if(WriteData(arg, buf, 1))

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %u bytes sent, total_bytes=%u/%u.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          return 15;

+	       }

+

+	       // re-transmission this frame

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): re-transmission this frame, offset(%u).", retry_count, sent_bytes);

+		   goto re_transmission;

+

+	       break;

+	 }

+

+	 // update progress state

+	 sent_bytes += frame_bytes;

+	 total_sent_bytes += frame_bytes;

+

+	 // calculate finish rate

+	 if( accuracy < (rate=(unsigned int)(((float)total_sent_bytes/total_bytes)*accuracy)) )

+	 {

+	    rate = accuracy;

+	 }

+

+	 if( 0 < (rate-finish_rate) )

+	 {

+	    finish_rate = rate;

+	    // calling callback 

+	    LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+	    if( NULL != cb_download_flash )

+	    {

+		   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash().");

+	       cb_download_flash((unsigned char)finish_rate, total_sent_bytes, total_bytes, cb_download_flash_arg);

+	    }

+	 }

+	}

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+

+   // wait for recovery done ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform unchanged data recovery.");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+	  return 16;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to recover all the unchanged data to flash!", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 17;

+   }

+

+   // wait for checksum ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform flash checksum.!");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).!", ret);

+	  return 18;

+   }

+

+   if( NACK == buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): NACK( %x) return, flash checksum error!", buf[0]);

+	  return 19;

+   }

+   else if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): non-ACK( %x) return.", buf[0]);

+      return 20;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ACK( %x): checksum OK!", buf[0]);

+   return 0;

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c.bak b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c.bak
new file mode 100644
index 0000000..69019e6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.c.bak
@@ -0,0 +1,588 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  da_cmd.cpp

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  DA(Download Agent) handshake command.

+ *

+ *******************************************************************************/

+#include "brom_base.h"

+#include "da_cmd.h"

+#include "sw_types.h"

+#include "gps_uart.h"

+#include <string.h>

+

+#include <fcntl.h>

+#include <pthread.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <stdarg.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <sys/stat.h>

+#include <unistd.h>

+

+#ifdef LOGD

+#undef LOGD

+#endif

+#ifdef LOGW

+#undef LOGW

+#endif

+#ifdef LOGE

+#undef LOGE

+#endif

+#if 0

+#define LOGD(...) tag_log(1, "[op01]", __VA_ARGS__);

+#define LOGW(...) tag_log(1, "[op01] WARNING: ", __VA_ARGS__);

+#define LOGE(...) tag_log(1, "[op01] ERR: ", __VA_ARGS__);

+#else

+#define LOG_TAG "flashtool"

+#include <cutils/sockets.h>

+#include <cutils/log.h>     /*logging in logcat*/

+#define LOGD(fmt, arg ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)

+#define LOGW(fmt, arg ...) ALOGW("%s: " fmt, __FUNCTION__ , ##arg)

+#define LOGE(fmt, arg ...) ALOGE("%s: " fmt, __FUNCTION__ , ##arg)

+#endif

+

+

+#define PACKET_RE_TRANSMISSION_TIMES   3

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  write_buf: data buffer want to be sent.

+ *  write_len: data length.

+ *

+ *******************************************************************************/

+int WriteData(GPS_Download_Arg arg, const void *write_buf, unsigned int write_len) {

+

+   unsigned int BytesOfWriiten = 0;

+   unsigned int rest_of_bytes = 0;

+   unsigned long wbytes = 0;

+   unsigned short RetryCount = 0;

+

+   if( NULL == write_buf || 0 >= write_len ) {

+      LOGE("DA_cmd::WriteData(): invalid arguments, write_buf(0x%08X), write_len(%lu).", write_buf, write_len);

+      return 1;

+   }

+

+   RetryCount = 0;

+   BytesOfWriiten = 0;

+   while( BytesOfWriiten < write_len ) 

+   	{

+   

+      // check stop flag 

+      if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) ) {

+         LOGE( "DA_cmd::WriteData(): m_stopflag(0x%08X)=%lu, force to stop!", m_stopflag, *m_stopflag);

+         return 2;

+      }

+   

+      wbytes = 0;

+      rest_of_bytes = write_len-BytesOfWriiten;

+

+	  GPS_UART_PutByte_Buffer((uint32 *) write_buf, rest_of_bytes);

+

+      // update write bytes

+         BytesOfWriiten += rest_of_bytes;

+

+   }

+

+   LOGE("DA_cmd::WriteData(): OK. total=(%lu/%lu).", BytesOfWriiten, write_len);

+   return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  ReadData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to read ack from target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  read_buf: data buffer want to be read.

+ *  read_len: data length.

+ *

+ *******************************************************************************/

+int ReadData(GPS_Download_Arg arg, void *read_buf, unsigned int read_len)

+{

+   unsigned int BytesOfRead = 0;

+   unsigned int rest_of_bytes = 0;

+   unsigned long rbytes = 0;

+   unsigned short RetryCount = 0;

+

+   if( NULL == read_buf || 0 >= read_len )

+   {

+      LOGE("DA_cmd::ReadData(): invalid arguments, read_buf(0x%08X), read_len(%lu).", read_buf, read_len);

+      return 1;

+   }

+

+   // initialize read buffer

+   memset(read_buf, '\0' , read_len);

+

+   RetryCount = 0;

+   BytesOfRead = 0;

+   while( BytesOfRead < read_len )

+   {

+      // check stop flag 

+      if( NULL!=arg.m_p_bootstop && BOOT_STOP==*(arg.m_p_bootstop) )

+      {

+         LOGE("DA_cmd::ReadData(): m_stopflag(0x%08X)=%lu, force to stop!", m_stopflag, *m_stopflag);

+         return 2;

+      }

+   

+      rbytes = 0;

+      rest_of_bytes = read_len-BytesOfRead;

+	  

+	  GPS_UART_GetByte_Buffer((uint32 *) read_buf, rest_of_bytes);

+

+	  BytesOfRead += rest_of_bytes;

+

+   }

+

+   LOGE( "DA_cmd::ReadData(): OK. total=(%lu/%lu).", BytesOfRead, read_len);

+   return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_SetMemBlock

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to set download memory block.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *

+ *******************************************************************************/

+int CMD_SetMemBlock(GPS_Download_Arg arg, ROM_HANDLE_T  *dl_handle)

+{

+   unsigned char buf[4];

+   unsigned int begin_addr;

+   unsigned int end_addr;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): invalid arguments! dl_handle(%x).", dl_handle);

+      return 1;

+   }

+

+   // send mem block command

+   buf[0] = DA_MEM_CMD;

+   buf[1] = 0x01;

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): send DA_MEM_CMD(%x) + MEM_BLOCK_COUNT(%x).",  buf[0], buf[1]);

+   if(WriteData(arg, buf, 2))

+   {

+      return 2;

+   }

+

+   // send MEM begin addr, end addr

+	// MOD with 0x08000000(bank1 start address), because our maui_sw remap flash to bank1 on MT6218B series project. 

+	begin_addr = dl_handle->m_begin_addr%0x08000000;

+	end_addr = dl_handle->m_end_addr%0x08000000;

+

+	// send begin addr, high byte first

+	buf[0] = (unsigned char)((begin_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((begin_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((begin_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((begin_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_BEGIN_ADDR( %x%x%x%x).\n\r", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 3;

+	}

+

+	// send end addr, high byte first

+	buf[0] = (unsigned char)((end_addr>>24)&0x000000FF);

+	buf[1] = (unsigned char)((end_addr>>16)&0x000000FF);

+	buf[2] = (unsigned char)((end_addr>> 8)&0x000000FF);

+	buf[3] = (unsigned char)((end_addr)    &0x000000FF);

+	LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): send MEM_END_ADDR(%x%x%x%x).\n\r", buf[0], buf[1], buf[2], buf[3]);

+	if(WriteData(arg, buf, 4))

+	{

+	 return 4;

+	}

+

+   // read ack 

+	LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): wait for ACK..\n\r");

+   if(ReadData(arg, buf, 1))

+   {

+      return 5;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): non-ACK(%x) return.\n\r", buf[0]);

+	  return 6;

+   }

+   LOGE("[FUNET]DA_cmd::CMD_SetMemBlock(): ACK(%x) OK!\n\r", buf[0]);

+   if(ReadData(arg, buf, 1))

+   {

+      return 7;

+   }

+   dl_handle->m_num_of_unchanged_data_blocks = buf[0];

+   LOGE( "[FUNET]DA_cmd::CMD_SetMemBlock(): UNCHANED_DATA_BLOCKS=( %x)\n\r", dl_handle->m_num_of_unchanged_data_blocks);

+   return 0;   

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_Finish

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send finish command to notify target download process is over.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int CMD_Finish(GPS_Download_Arg arg)

+{

+   unsigned char buf[2];

+

+   // send DA_FINISH_CMD command

+   buf[0] = DA_FINISH_CMD;

+   GPS_UART_PutByte(buf[0]); 

+   LOGE( "[FUNET]DA_cmd::CMD_Finish(): OK!\n\r");

+   return 0;

+}

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *  cb_download_flash_init: callback function which is invoked at the beginning of transimitting.

+ *  cb_download_flash_init_arg: parameter of initial callback function.

+ *  cb_download_flash: callback function which is invoked during the transimitting.

+ *  cb_download_flash_arg: parameter of  callback function upper.

+ *

+ *******************************************************************************/

+int CMD_WriteData(

+      GPS_Download_Arg arg,

+      ROM_HANDLE_T  *dl_handle,

+      CALLBACK_DOWNLOAD_PROGRESS_INIT  cb_download_flash_init,  void *cb_download_flash_init_arg,

+      CALLBACK_DOWNLOAD_PROGRESS  cb_download_flash,  void *cb_download_flash_arg)

+{

+   static const char ErrAckTable[][64]= {

+      "TIMEOUT_DATA",

+      "CKSUM_ERROR",

+      "RX_BUFFER_FULL",

+      "TIMEOUT_CKSUM_LSB",

+      "TIMEOUT_CKSUM_MSB",

+      "ERASE_TIMEOUT",

+      "PROGRAM_TIMEOUT",

+      "RECOVERY_BUFFER_FULL",

+      "UNKNOWN_ERROR"

+   };

+   unsigned char buf[5];

+   unsigned int finish_rate = 0;

+   unsigned int total_bytes = 0;

+   unsigned int total_sent_bytes = 0;

+   unsigned int accuracy;

+   int ret;

+   unsigned int sent_bytes;

+   unsigned int retry_count=0;

+   unsigned int j;

+   unsigned int rate;

+   unsigned short checksum;

+   unsigned int frame_bytes;

+

+   // check arguments

+   if( NULL==dl_handle )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): invalid arguments! dl_handle( %x)..\n\r", dl_handle);

+      return 1;

+   }

+

+   total_bytes = dl_handle->m_len;

+

+   // send write command + packet length

+   buf[0] = DA_WRITE_CMD;

+   buf[1] = (unsigned char)((dl_handle->m_packet_length>>24) &0x000000FF);

+   buf[2] = (unsigned char)((dl_handle->m_packet_length>>16) &0x000000FF);

+   buf[3] = (unsigned char)((dl_handle->m_packet_length>>8)  &0x000000FF);

+   buf[4] = (unsigned char)((dl_handle->m_packet_length)     &0x000000FF);

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): send DA_WRITE_CMD( %x), PACKET_LENGTH( %x%x%x%x)=%u..\n\r", buf[0], buf[1], buf[2], buf[3], buf[4], dl_handle->m_packet_length);

+   if(WriteData(arg, buf, 5))

+   {

+      return 3;

+   }

+

+   // initialization callback

+   if( NULL != cb_download_flash_init )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash_init().\n\r");

+	  cb_download_flash_init(cb_download_flash_init_arg);

+   }

+

+   // Set finish rate of callback function to 100(%)

+   accuracy = 100;

+

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).\n\r", ret);

+      return 4;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).\n\r", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to save all the unchanged data from flash!\n\r", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 5;

+   }

+

+   // wait for 1st sector erase done 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for 1st sector erase done.\n\r");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)\n\r", ret);

+      return 6;

+   }

+

+   LOGE("[FUNET]DA_cmd::CMD_WriteData(): read ack( %x).\n\r", buf[0]);

+   

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to erase the 1st sector!.\n\r", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 7;

+   }

+

+   // send all rom files

+   finish_rate = 0;

+   total_sent_bytes = 0;

+	// send each rom file

+	sent_bytes = 0;

+	retry_count = 0;

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %d bytes, total_sent_bytes=%d/%d..\n\r", dl_handle->m_len, total_sent_bytes, total_bytes);

+	while( sent_bytes < dl_handle->m_len )

+	{

+

+	re_transmission:

+

+	 // reset the frame checksum

+	 checksum = 0;

+

+	 // if the last frame is less than PACKET_LENGTH bytes

+	 if( dl_handle->m_packet_length > (dl_handle->m_len-sent_bytes) )

+	 {

+	    frame_bytes = dl_handle->m_len - sent_bytes;

+	 }

+	 else

+	 {

+	    // the normal frame

+	    frame_bytes = dl_handle->m_packet_length;

+	 }

+

+	  GPS_UART_PutByte_Buffer((uint32 *) (dl_handle->m_buf+sent_bytes), frame_bytes);

+

+	 // calculate checksum

+	 for(j=0; j<frame_bytes; j++)

+	 {

+	    // WARNING: MUST make sure it unsigned value to do checksum

+	    checksum += dl_handle->m_buf[sent_bytes+j];

+	 }

+

+	 // send 2 bytes checksum, high byte first

+	 buf[0] = (unsigned char)((checksum>> 8)&0x000000FF);

+	 buf[1] = (unsigned char)((checksum)    &0x000000FF);

+	 

+	 if(WriteData(arg, buf, 2))

+	 {

+	    goto read_cont_char;

+	 }

+

+	read_cont_char:

+	 // read CONT_CHAR

+	 buf[0] = 0xEE;

+	 if( 0 != (ret=ReadData(arg, buf, 1)) )

+	 {

+		LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).\n\r",ret);

+		return 8;

+	 }

+	 LOGE("[FUNET]CONT_CHART Received( %x).\n\r", buf[0]);

+

+	 switch(buf[0])

+	 {

+	    case CONT_CHAR:

+	       // sent ok!, reset retry_count			   

+		   LOGE( "[FUNET]CONT_CHART Ok( %x).\n\r", buf[0]);

+	       retry_count = 0;

+	       break;

+	    case ERASE_TIMEOUT:

+		   return 9;

+	    case PROGRAM_TIMEOUT:

+		   return 10;

+	    case RECOVERY_BUFFER_FULL:

+		   return 11;

+	    case RX_BUFFER_FULL:

+	    case CKSUM_ERROR:

+	    case TIMEOUT_DATA:

+	    case TIMEOUT_CKSUM_LSB:

+	    case TIMEOUT_CKSUM_MSB:

+	    default:

+	       // check retry times

+	       if( PACKET_RE_TRANSMISSION_TIMES > retry_count )

+	       {

+	          retry_count++;

+	       }

+	       else

+	       {

+	          // fail to re-transmission

+	          // send NACK to wakeup DA to stop

+	          buf[0] = NACK;

+			  if(WriteData(arg, buf, 1))

+	          {

+				 LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          }

+	          return 12;

+	       }

+

+	       // wait for DA clean RX buffer

+		   if( 0 != (ret=ReadData(arg, buf, 1)) )

+	       {

+	          LOGE( "DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)", ret);

+	          LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 13;

+	       }

+		   

+	       if( ACK != buf[0] )

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): wrong ack(0x%02X) return!", retry_count, buf[0]);

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+			  return 14;

+	       }

+

+	       // send CONT_CHAR to wakeup DA to start recieving again

+	       buf[0] = CONT_CHAR;

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): send CONT_CHAR to wakeup DA to start recieving again.", retry_count);

+		   if(WriteData(arg, buf, 1))

+	       {

+	          LOGE("DA_cmd::CMD_WriteData(): Retry(%u): (%u%%): %lu bytes sent, total_bytes=%lu/%lu.", retry_count, (unsigned short)(((float)finish_rate/accuracy)*100), sent_bytes, total_sent_bytes, total_bytes);

+	          return 15;

+	       }

+

+	       // re-transmission this frame

+	       LOGE( "DA_cmd::CMD_WriteData(): Retry(%u): re-transmission this frame, offset(%lu).", retry_count, sent_bytes);

+		   goto re_transmission;

+

+	       break;

+	 }

+

+	 // update progress state

+	 sent_bytes += frame_bytes;

+	 total_sent_bytes += frame_bytes;

+

+	 // calculate finish rate

+	 if( accuracy < (rate=(unsigned int)(((float)total_sent_bytes/total_bytes)*accuracy)) )

+	 {

+	    rate = accuracy;

+	 }

+

+	 if( 0 < (rate-finish_rate) )

+	 {

+	    finish_rate = rate;

+	    // calling callback 

+	    LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.\n\r",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+	    if( NULL != cb_download_flash )

+	    {

+		   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): CALLBACK: cb_download_flash().\n\r");

+	       cb_download_flash((unsigned char)finish_rate, total_sent_bytes, total_bytes, cb_download_flash_arg);

+	    }

+	 }

+	}

+	LOGE( "[FUNET]DA_cmd::CMD_WriteData(): (%d%%): %d bytes sent, total_bytes=%d/%d.\n\r",(unsigned char)finish_rate, sent_bytes, total_sent_bytes, total_bytes);

+

+   // wait for recovery done ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform unchanged data recovery.\n\r");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d)\n\r", ret);

+	  return 16;

+   }

+

+   if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): %s( %x): fail to recover all the unchanged data to flash!\n\r", buf[0]>UNKNOWN_ERROR?"UNKNOWN_ACK":ErrAckTable[buf[0]], buf[0]);

+	  return 17;

+   }

+

+   // wait for checksum ack 

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): wait for DA to perform flash checksum.!\n\r");

+   if( 0 != (ret=ReadData(arg, buf, 1)) )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ReadData(): fail, Err(%d).!\n\r", ret);

+	  return 18;

+   }

+

+   if( NACK == buf[0] )

+   {

+	  LOGE("[FUNET]DA_cmd::CMD_WriteData(): NACK( %x) return, flash checksum error!\n\r", buf[0]);

+	  return 19;

+   }

+   else if( ACK != buf[0] )

+   {

+	  LOGE( "[FUNET]DA_cmd::CMD_WriteData(): non-ACK( %x) return.\n\r", buf[0]);

+      return 20;

+   }

+

+   LOGE( "[FUNET]DA_cmd::CMD_WriteData(): ACK( %x): checksum OK!\n\r", buf[0]);

+   return 0;

+}

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.h
new file mode 100644
index 0000000..df8678a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/da_cmd.h
@@ -0,0 +1,139 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  da_cmd.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  DA(Download Agent) handshake command.

+ *

+ *******************************************************************************/

+#ifndef  _DA_CMD_H_

+#define  _DA_CMD_H_

+

+#include "flashtool.h"

+

+//------------------------------------------------------------------------------

+// DA Command Object                                                            

+//------------------------------------------------------------------------------

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  write_buf: data buffer want to be sent.

+ *  write_len: data length.

+ *

+ *******************************************************************************/

+int WriteData(GPS_Download_Arg arg, const void *write_buf, unsigned int write_len);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  ReadData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to read ack from target.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  read_buf: data buffer want to be read.

+ *  read_len: data length.

+ *

+ *******************************************************************************/

+int ReadData(GPS_Download_Arg arg, void *read_buf, unsigned int read_len);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_SetMemBlock

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to set download memory block.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *

+ *******************************************************************************/

+ int CMD_ChangeUartSpeed(GPS_Download_Arg arg, unsigned char max_full_sync_count) ;

+int CMD_SetMemBlock(GPS_Download_Arg arg, ROM_HANDLE_T  *dl_handle);

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_Finish

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send finish command to notify target download process is over.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ *******************************************************************************/

+int CMD_Finish(GPS_Download_Arg arg);

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  CMD_WriteData

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to send firmware data to target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  dl_handle: firmware packet information.

+ *  cb_download_flash_init: callback function which is invoked at the beginning of transimitting.

+ *  cb_download_flash_init_arg: parameter of initial callback function.

+ *  cb_download_flash: callback function which is invoked during the transimitting.

+ *  cb_download_flash_arg: parameter of  callback function upper.

+ *

+ *******************************************************************************/

+int CMD_WriteData(

+               GPS_Download_Arg arg,

+               ROM_HANDLE_T  *dl_handle,

+               CALLBACK_DOWNLOAD_PROGRESS_INIT  cb_download_flash_init,  void *cb_download_flash_init_arg,

+               CALLBACK_DOWNLOAD_PROGRESS  cb_download_flash,  void *cb_download_flash_arg);

+

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.c
new file mode 100644
index 0000000..cbf5c32
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.c
@@ -0,0 +1,672 @@
+#ifdef CONFIG_GPS_MT3303

+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  flashtool.cpp

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  Main function of MCU download.

+ *

+ *******************************************************************************/

+#include "flashtool.h"

+#include "da_cmd.h"

+#include "brom_base.h"

+#include "DOWNLOAD.H"

+#include "GPS_DL_api.h"

+#include <stdio.h>

+#include <string.h>

+#include "sw_types.h"

+#include "brom.h"

+

+#include <fcntl.h>

+#include <pthread.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <stdarg.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <sys/stat.h>

+#include <unistd.h>

+

+#include "mt3333_controller.h"

+#include "gps_controller.h"

+#include "mnl_common.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  SyncWithDA

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to recevied the information from target.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *

+ * Output:

+ * --------

+ *  p_da_report: information that DA will report. 

+ *  p_FlashDeviceKey:  information that DA will report.

+ *

+ *******************************************************************************/

+static int SyncWithDA(GPS_Download_Arg arg, s_DA_REPORT_T *p_da_report, s_FlashDeviceKey *p_FlashDeviceKey)

+{

+   unsigned char   buf[32];

+   s_FlashDeviceKey   flash_id;

+

+   if( NULL == p_da_report )

+   {

+      return FT_INVALID_ARGUMENTS;

+   }

+

+   // initialize first 

+   memset(p_da_report, 0, sizeof(s_DA_REPORT_T));

+   p_da_report->expected_da_major_ver = DA_MAJOR_VER;

+   p_da_report->expected_da_minor_ver = DA_MINOR_VER;

+   p_da_report->flash_device_id = DEVICE_UNKNOWN;

+

+   // get SYNC_CHAR 

+   LOGE("[FUNET]SyncWithDA(): wait SYNC_CHAR");

+   if(ReadData(arg, buf, 1))

+   {

+       LOGE( "[FUNET]SyncWithDA(): SYNC_CHAR no response.");

+      return FT_DA_NO_RESPONSE;

+   }

+   LOGE("[FUNET]SyncWithDA(): SYNC_CHAR Get:%x.", buf[0]);

+   

+   if( SOC_FAIL == buf[0] )

+   {

+      LOGE("[FUNET]SyncWithDA(): SOC_FAIL(%x) received from DA.", buf[0]);

+      return FT_DA_SOC_CHECK_FAIL;

+   }

+   else if( HW_ERROR == buf[0] )

+   {

+      return FT_DA_HW_ERROR;

+   }

+   else if( SYNC_CHAR != buf[0] )

+   {

+      LOGE("[FUNET]SyncWithDA(): non-SYNC_CHAR(%x) received from DA.", buf[0]);

+      return FT_DA_SYNC_INCORRECT;

+   }

+

+   // get DA_MAJOR_VER, DA_MINOR_VER    

+   LOGE("[FUNET]SyncWithDA(): wait DA_MAJOR_VER(%x), DA_MINOR_VER.", buf[0]);

+   if(ReadData(arg, buf, 2))

+   {

+      return FT_DA_NO_RESPONSE;

+   }

+

+   p_da_report->da_major_ver = buf[0];

+   p_da_report->da_minor_ver = buf[1];

+   if( DA_MAJOR_VER!=p_da_report->da_major_ver || DA_MINOR_VER!=p_da_report->da_minor_ver )

+   {

+      LOGE( "[FUNET]SyncWithDA(): DA_v%d.%d was expired, expect DA_v%d.%d .",  p_da_report->da_major_ver, p_da_report->da_minor_ver, DA_MAJOR_VER, DA_MINOR_VER);

+      return FT_DA_VERSION_INCORRECT;

+   }

+

+   LOGE( "[FUNET]SyncWithDA(): DA_v%d.%d.",  p_da_report->da_major_ver, p_da_report->da_minor_ver);

+   LOGE( "[FUNET]SyncWithDA(): wait DEVICE_INFO.");

+   if(ReadData(arg, buf, 1))

+   {

+      return FT_DA_NO_RESPONSE;

+   }

+   p_da_report->flash_device_id = (DEVICE_INFO)buf[0];

+   if( DEVICE_UNKNOWN == p_da_report->flash_device_id )

+   {

+      return FT_DA_UNKNOWN_FLASH_DEVICE;

+   }

+

+   // get flash size, manufacture id and device code and ext sram size 

+   if(ReadData(arg, buf, 16))

+   {

+      return FT_DA_NO_RESPONSE;

+   }

+   // get flash size 

+   p_da_report->flash_size = ((buf[0]<<24)&0xFF000000)|((buf[1]<<16)&0x00FF0000)|((buf[2]<<8)&0x0000FF00)|((buf[3])&0x000000FF);

+   // get flash manufacture id and device code 

+   flash_id.m_ManufactureId   = ((buf[4]<<8)&0xFF00)|((buf[5])&0x00FF);

+   flash_id.m_DeviceCode      = ((buf[6]<<8)&0xFF00)|((buf[7])&0x00FF);

+   flash_id.m_ExtDeviceCode1   = ((buf[8]<<8)&0xFF00)|((buf[9])&0x00FF);

+   flash_id.m_ExtDeviceCode2   = ((buf[10]<<8)&0xFF00)|((buf[11])&0x00FF);

+   if( NULL != p_FlashDeviceKey )

+   {

+      *p_FlashDeviceKey = flash_id;

+   }

+   // get external sram size 

+   p_da_report->ext_sram_size = ((buf[12]<<24)&0xFF000000)|((buf[13]<<16)&0x00FF0000)|((buf[14]<<8)&0x0000FF00)|((buf[15])&0x000000FF);

+

+   LOGE("[FUNET]SyncWithDA(): SYNC ok.");

+   return FT_OK;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  FlashDownload_Internal

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to manage the download flow.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  GPS_da: import Download Agent(DA) buffer and size. 

+ *  GPS_image_list:  import firmware buffer and size.

+ *  p_arg: Callback function pointer.

+ *

+ *******************************************************************************/

+static int FlashDownload_Internal(

+    GPS_DA* GPS_da,

+    GPS_Image_List* GPS_image_list,

+    FLASHTOOL_ARG  *p_arg,

+    GPS_Download_Arg arg)

+{

+    int ret;

+    //int *p_stopflag = arg.m_p_bootstop;

+    s_BOOT_FLASHTOOL_ARG boot_flashtool_arg;

+    ROM_HANDLE_T dl_handle,*p_dl_handle;

+    s_DA_REPORT_T      da_report;

+    s_DA_REPORT_T      *pDA_Report;

+    s_FlashDeviceKey   flash_id;

+    p_dl_handle = &dl_handle;

+

+

+    p_dl_handle->m_buf = GPS_image_list->m_image_list[0].m_image;

+    p_dl_handle->m_len = GPS_image_list->m_image_list[0].m_size;

+    p_dl_handle->m_begin_addr = 0x00000000;

+    p_dl_handle->m_end_addr = p_dl_handle->m_begin_addr + p_dl_handle->m_len - 1;

+    p_dl_handle->m_packet_length = 1024; 

+

+

+    // check arguments

+    if( NULL==GPS_image_list || NULL==p_arg || NULL==GPS_da) 

+    {

+        LOGE("[FUNET]Input parameters error");

+       return FT_INVALID_ARGUMENTS;

+    }

+

+    // fill boot flashtool arg 

+    boot_flashtool_arg.m_da_start_addr           = 0x00000C00;

+    boot_flashtool_arg.m_da_buf                  = GPS_da->m_image;

+    boot_flashtool_arg.m_da_len                  = GPS_da->m_size;

+

+     LOGI("[FUNET]Enter Boot_FlashTool");

+

+     // boot target to flashtool mode 

+     ret = Boot_FlashTool(&boot_flashtool_arg, arg);

+

+

+     // check return value 

+     if( BROM_OK != ret )

+     {

+        // boot up failed!

+        LOGE( "[FUNET]FlashDownload_Internal(): BRom_AutoBoot::Boot_FlashTool() fail! , Err(%x).", ret);

+        return (FT_BROM_ERROR|ret);

+     }

+

+    LOGE( "[FUNET]Sync With DA");

+

+    // sync with DA 

+    pDA_Report=&da_report;

+    if( FT_OK != (ret=SyncWithDA(arg, pDA_Report, &flash_id)) )

+    {

+      return ret;

+    }

+

+    // Doesn't format 

+    pDA_Report->fat_begin_addr = 0;

+    pDA_Report->fat_length = 0;

+    // change UART speed for high speed(921600bps)

+    LOGE( "Change to high speed baudrate(921600) ");

+

+    int status = CMD_ChangeUartSpeed(arg, 1);

+    if(status) 

+    {

+      LOGE( "CMD_ChangeUartSpeed fail status %d", status);

+      return FT_DA_CHANGE_BAUDRATE_FAIL;

+    }

+    else

+    {

+      LOGE("CMD_ChangeUartSpeed OK");                 

+    }

+

+    LOGE("[FUNET]CMD_SetMemBlock.");

+    // set memory block

+    if(CMD_SetMemBlock(arg, p_dl_handle))

+    {

+      return FT_DA_SET_DOWNLOAD_BLOCK_FAIL;

+    }

+    LOGE("[FUNET]da_cmd.CMD_WriteData.");

+    // write to flash by memory block

+    if(CMD_WriteData(arg, p_dl_handle, p_arg->m_cb_download_conn_init, p_arg->m_cb_download_conn_init_arg, p_arg->m_cb_download_conn, p_arg->m_cb_download_conn_arg))

+    {

+      return FT_DA_DOWNLOAD_FAIL;

+    }

+

+    // set ret to FT_OK 

+    ret = FT_OK;

+

+    LOGE("[FUNET]FlashDownload_Internal(): Success!");

+

+    // Finish Cmd

+    CMD_Finish(arg);

+

+    return ret;

+}

+

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  FlashDownload

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to manage the download flow.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  GPS_da: import Download Agent(DA) buffer and size. 

+ *  GPS_image_list:  import firmware buffer and size.

+ *

+ *******************************************************************************/

+int  FlashDownload(

+    GPS_DA* GPS_da,

+    GPS_Image_List* GPS_image_list,

+    GPS_Download_Arg arg)

+{

+   FLASHTOOL_ARG  flashtool_arg,*p_arg;

+   p_arg = &flashtool_arg;

+

+   // check arguments

+   if( NULL == GPS_image_list || NULL == GPS_da) 

+   {

+      LOGE("[FUNET]Input parameters error"); //Show debug log, please use your own logger API to replace 'BL_PRINT' function.

+      return FT_INVALID_ARGUMENTS;

+   }

+

+   p_arg->m_cb_download_conn_init = arg.m_cb_download_conn_init;

+   p_arg->m_cb_download_conn_init_arg = arg.m_cb_download_conn_init_arg;

+   p_arg->m_cb_download_conn = arg.m_cb_download_conn;

+   p_arg->m_cb_download_conn_arg = arg.m_cb_download_conn_arg;

+   p_arg->m_cb_download_conn_da_init = arg.m_cb_download_conn_da_init;

+   p_arg->m_cb_download_conn_da_init_arg = arg.m_cb_download_conn_da_init_arg;

+   p_arg->m_cb_download_conn_da = arg.m_cb_download_conn_da;

+   p_arg->m_cb_download_conn_da_arg = arg.m_cb_download_conn_da_arg;

+   

+   LOGI("[FUNET]Enter FlashDownload_Internal");

+   return FlashDownload_Internal(GPS_da, GPS_image_list, p_arg, arg);

+}

+

+

+//Example code of callback function

+int gps_download_progress_callback(unsigned char finished_percentage,

+                                           unsigned int finished_bytes,

+                                           unsigned int total_bytes, void *usr_arg)

+{

+    int percentage[] = {5, 15, 100};

+    int stage = (int) usr_arg;

+    LOGE( "[FUNET]current update progress: %d, stage:%d ",finished_percentage, stage);

+    UNUSED(finished_bytes);

+    UNUSED(total_bytes);

+    if (stage >= sizeof(percentage)/sizeof(int) - 1)

+    {

+        LOGE( "[FUNET]display error, stage:%d ", stage);

+        return 1;

+    }

+    finished_percentage = (percentage[stage + 1] - percentage[stage]) * finished_percentage/100 + percentage[stage];

+    LOGE("[FUNET]real update progress: %d ",finished_percentage);

+    return 0;

+}

+

+#if defined(__ANDROID_OS_10__)

+#define DA_FILE_NADA MTK_GPS_FW_PATH"3333_da.bin"

+#define FW_FILE_NADA MTK_GPS_FW_PATH"3333_fw.bin"

+#define FW_FILE_NADA_OLD MTK_GPS_DATA_PATH"3333_fw_old.bin"

+#else

+#define DA_FILE_NADA MTK_GPS_DATA_PATH"3333_da.bin"

+#define FW_FILE_NADA MTK_GPS_DATA_PATH"3333_fw.bin"

+#define FW_FILE_NADA_OLD MTK_GPS_DATA_PATH"3333_fw_old.bin"

+#endif

+

+uint8 *fw_buf=NULL;

+int32 fw_size=0;

+uint8 *da_buf=NULL;

+int32 da_size=0;

+int fw_downloading=0;

+extern int g_fd_mt3333_data;

+extern MNL_CONFIG_T mnld_cfg;

+

+int flashtool_file_isvalid(void){

+    int result_da=0;

+    int result_fw=0;

+#if defined(__ANDROID_OS_10__)

+    int result_fw_old=0;

+    result_fw_old=access(FW_FILE_NADA_OLD, F_OK);

+    result_da=access(DA_FILE_NADA, F_OK);

+    result_fw=access(FW_FILE_NADA, F_OK);

+

+    if(result_da>=0 && result_fw>=0 && result_fw_old<0){

+        //LOGE("result=ok");

+        return 1;

+    }

+#else

+    result_da=access(DA_FILE_NADA, F_OK);

+    result_fw=access(FW_FILE_NADA, F_OK);

+

+    if(result_da>=0 && result_fw>=0){

+        //LOGE("result=ok");

+        return 1;

+    }

+#endif

+    LOGE("da=%d, fw=%d, result=wrong", result_da,result_fw);

+    return 0;

+}

+

+int flashtool_read_da_file(void){

+    int result=0;

+    int fd=0;

+    int file_size=0;

+    int ret=0;

+

+    fd = open(DA_FILE_NADA, O_RDONLY);

+    if(fd < 0){

+        LOGE("open %s fail",DA_FILE_NADA);

+        ret=-1;

+        goto DEINIT;

+    }

+    

+    file_size=lseek(fd, 0, SEEK_END);

+    if(file_size < 0){

+        LOGE("point file tail error-1");

+        ret=-2;

+        goto DEINIT;

+    }

+    da_size=(int32)file_size;

+    LOGI("file size=%ld",da_size);

+    da_buf=malloc(da_size);

+    if(NULL == da_buf){

+        LOGE("malloc error");

+        ret=-3;

+        goto DEINIT;

+    }

+    

+

+    result=lseek(fd, 0, SEEK_SET);

+    if(result < 0){

+        LOGE("point file tail error-2");

+        ret=-4;

+        goto DEINIT;

+    }

+

+    if(da_size != (result=read(fd, da_buf, da_size))){

+        LOGE("read file error,len=%d,orilen=%ld",result,da_size);

+        ret=-5;

+        goto DEINIT;

+    }

+

+    close(fd);

+    return 0;

+

+DEINIT:

+    if(fd>=0){

+        close(fd);

+    }

+    

+    if(NULL != da_buf){

+        free(da_buf);

+        da_buf=NULL;

+    }

+    return ret;

+}

+

+int flashtool_read_fw_file(void){

+    int result=0;

+    int fd=0;

+    int file_size=0;

+    int ret=0;

+

+    fd = open(FW_FILE_NADA, O_RDONLY);

+    if(fd < 0){

+        LOGE("open %s fail",FW_FILE_NADA);

+        ret=-1;

+        goto DEINIT;

+    }

+    

+    file_size=lseek(fd, 0, SEEK_END);

+    if(file_size < 0){

+        LOGE("point file tail error-1");

+        ret=-2;

+        goto DEINIT;

+        

+    }

+    fw_size=file_size;

+    LOGI("file size=%ld",fw_size);

+    fw_buf=malloc(fw_size);

+    if(NULL == fw_buf){

+        LOGE("malloc error");

+        ret=-3;

+        goto DEINIT;

+    }

+    

+

+    result=lseek(fd, 0, SEEK_SET);

+    if(result < 0){

+        LOGE("point file tail error-2");

+        ret=-4;

+        goto DEINIT;

+    }

+

+    if(fw_size != (result=read(fd, fw_buf, fw_size))){

+        LOGE("read file error,len=%d,orilen=%ld",result,fw_size);

+        ret=-5;

+        goto DEINIT;

+    }

+

+    close(fd);

+    return 0;

+

+DEINIT:

+    if(fd>=0){

+        close(fd);

+    }

+    

+    if(NULL != fw_buf){

+        free(fw_buf);

+        fw_buf=NULL;

+    }

+    return ret;

+    return 0;

+}

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  main

+ *

+ * Description:

+ * ------------

+ *  Main funciton. 

+ *  Please invoke this funciton to start download process.

+ *  User must load DA and firmware file at MCU side and provide buffer pointer to the parameters in the sample

+ *  code below.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ *******************************************************************************/

+void* flashtool_download_thread(void *arg1)

+{

+    int ret;

+    GPS_DA gps_da;

+    GPS_Image_List gps_image;

+    GPS_Download_Arg arg;

+    pthread_t pthread_mt3333_controller;

+    pthread_t pthread_mt3333_data;

+    pthread_t pthread_mt3333_data_debug;

+    unsigned int retry_max=3;

+#if defined(__ANDROID_OS_10__)

+    FILE *fw_data_old = NULL;

+    char str[] = "FW download pass";

+#endif

+

+    UNUSED(arg1);

+    //mnl_set_pwrctl(1);

+    LOGI("everything is begin");

+    

+    for(int i=0;i<1; i++){

+        usleep(1000 * 1000);

+    }

+    

+

+    //User must provide the pointer of download agent file(DA) buffer and image size to the below parameters.

+    //gps_da.m_image = ......;

+    //gps_da.m_size = ......;

+    

+    //MT3333/3339 only has one image file, so set image number as 1.

+    gps_image.m_num = 1;

+    //User must provide the pointer of firmware buffer and image size to the below parameters.

+    //gps_image.m_image_list[0].m_image = ......;

+    //gps_image.m_image_list[0].m_size = ......;

+    if(flashtool_file_isvalid()){

+        if(0 == flashtool_read_da_file()){

+            if(0 == flashtool_read_fw_file()){

+                gps_image.m_image_list[0].m_image = fw_buf;

+                gps_image.m_image_list[0].m_size = fw_size;

+                gps_da.m_image = da_buf;

+                gps_da.m_size = da_size;

+            }else{

+                goto DEINIT;

+            }

+        }else{

+            goto DEINIT;

+        }

+        

+    }else{

+        goto DEINIT;

+    }

+

+    LOGI("file is ready");

+    fw_downloading=1;

+    

+    memset(&arg, 0, sizeof(arg));

+    //Callback functions which are invoked while downloading image to GPS chip help to show the rate of progress. 

+    //Callback functions are implemented by user.

+    //If do not want to use callback function, set them as 'NULL'.

+    //If callback functions do not need input parameter, set argument as 'NULL'. 

+    arg.m_cb_download_conn = gps_download_progress_callback;

+    arg.m_cb_download_conn_arg = (void*) 1;

+    arg.m_cb_download_conn_da = gps_download_progress_callback;

+    arg.m_cb_download_conn_da_arg = (void*) 0;

+

+    //Note: before downloading, user must confirm:

+    //1. MCU UART which connects to GPS chip UART has been initialized.

+    //2. UART baud rate has been set correctly.

+    //3. GPS has been power on correctly.

+    //4. GPS 32KHz clock has been input correctly.

+    

+    do{

+        ret = FlashDownload(&gps_da, &gps_image, arg);

+        retry_max--;

+        mnl_set_pwrctl(0);

+        usleep(100 * 1000);

+        LOGE("ret=0x%x, retry=%d", ret,retry_max);

+        if(ret == FT_OK ){

+            break;

+        }

+    }while(retry_max != 0);

+    

+    fw_downloading=0;

+    if(ret == FT_OK){

+#if defined(__ANDROID_OS_10__)

+        fw_data_old = fopen(FW_FILE_NADA_OLD, "w+");

+        if (fw_data_old != NULL) {

+            fwrite(str, sizeof(str), 1, fw_data_old);

+            fclose(fw_data_old);

+            LOGE("result pass");

+        } else {

+            LOGE("result fail=%s\n", strerror(errno));

+        }

+#else

+        LOGE("rename result=%d",rename(FW_FILE_NADA, FW_FILE_NADA_OLD));

+#endif

+    }

+

+DEINIT:

+    if(fw_buf){

+        free(fw_buf);

+        fw_buf = NULL;

+    }    

+    if(da_buf){

+        free(da_buf);

+        da_buf = NULL;

+    }

+#if 0    

+    if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,mnld_cfg.link_speed, 8, 'N', 1)){

+        LOGE("configure uart baudrate failed");

+        return;

+    }

+#endif

+

+    gps_driver_state_init();

+

+#if 1

+        //LOGE("uart baudrate:%d", mnld_cfg.init_speed);

+        if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,mnld_cfg.init_speed, 8, 'N', 1)){

+            LOGE("configure uart baudrate failed");

+            return NULL;

+        }

+        if(1 != mt3333_controller_check_if_gpsfunctionok()){

+        #if 0    

+            if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(

+                g_fd_mt3333_data ,

+                mnld_cfg.init_speed == 115200?921600:115200, 

+                8, 'N', 1)){

+                LOGE("configure uart baudrate failed");

+                return -1;

+            }

+        #endif    

+        }

+#endif    

+

+    

+    pthread_create(&pthread_mt3333_controller, NULL, mt3333_thread_control, NULL);

+    pthread_create(&pthread_mt3333_data, NULL, mt3333_thread_data, NULL);

+    pthread_create(&pthread_mt3333_data_debug, NULL, mt3333_thread_data_debug, NULL);

+

+    pthread_exit(NULL);

+    return NULL;

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.h
new file mode 100644
index 0000000..97b798a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/flashtool.h
@@ -0,0 +1,140 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ ******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *  flashtool.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *  APIs for FlashTool Library.

+ *

+ *******************************************************************************/

+#ifndef _FLASHTOOL_H_

+#define _FLASHTOOL_H_

+

+#include "brom.h"

+#include "DOWNLOAD.H"

+#include "GPS_DL_api.h"

+#include <stdio.h>

+

+#ifdef   __cplusplus

+extern "C" {

+#endif

+

+//------------------------------------------------------------------------------

+// return code                                                                  

+//------------------------------------------------------------------------------

+

+#define FT_RET(ret)  (ret&0x000000FF)

+

+#define FT_OK                          0x000000

+#define FT_ERROR                       0x000001

+#define FT_INVALID_ARGUMENTS           0x000002

+#define FT_COM_PORT_OPEN_ERR           0x000003

+#define FT_DA_HANDLE_ERROR             0x000004

+#define FT_DL_HANDLE_ERROR             0x000005

+#define FT_BROM_ERROR                  0x000007

+#define FT_COM_PORT_SET_TIMEOUT_ERR    0x000008

+#define FT_DA_NO_RESPONSE              0x000009

+#define FT_DA_SYNC_INCORRECT           0x00000A

+#define FT_DA_VERSION_INCORRECT        0x00000B

+#define FT_DA_UNKNOWN_FLASH_DEVICE     0x00000C

+#define FT_DA_SET_EXT_CLOCK_FAIL       0x00000D

+#define FT_DA_SET_BBCHIP_TYPE_FAIL     0x00000E

+#define FT_DA_CHANGE_BAUDRATE_FAIL     0x00000F

+#define FT_DA_SET_DOWNLOAD_BLOCK_FAIL  0x000010

+#define FT_DA_DOWNLOAD_FAIL            0x000011

+#define FT_DA_FORMAT_FAIL              0x000013

+#define FT_DA_FINISH_CMD_FAIL          0x000014

+#define FT_DA_SOC_CHECK_FAIL           0x000015

+#define FT_DA_BBCHIP_DSP_VER_INCORRECT 0x000016

+#define FT_SKIP_AUTO_FORMAT_FAT        0x000017

+#define FT_DA_HW_ERROR                 0x000018

+#define FT_DA_ENABLE_WATCHDOG_FAIL     0x000019

+#define FT_CALLBACK_ERROR              0x000020

+             

+

+//------------------------------------------------------------------------------

+// DA report structure                                                          

+//------------------------------------------------------------------------------

+typedef  struct DA_REPORT_T{

+   unsigned char  expected_da_major_ver;

+   unsigned char  expected_da_minor_ver;

+   unsigned char  da_major_ver;

+   unsigned char  da_minor_ver;

+   DEVICE_INFO    flash_device_id;

+   unsigned int   flash_size;

+   unsigned int   fat_begin_addr;

+   unsigned int   fat_length;

+   unsigned int   ext_sram_size;

+}s_DA_REPORT_T;

+

+

+//------------------------------------------------------------------------------

+// FLASHTOOL_ARG structure                                                      

+//------------------------------------------------------------------------------

+

+typedef  struct {

+   CALLBACK_DOWNLOAD_PROGRESS_INIT m_cb_download_conn_init; //callback function which is invoked at the beginning of firmware transimitting.

+   void  *m_cb_download_conn_init_arg; // parameter of the callback function upper

+

+   CALLBACK_CONN_BROM_WRITE_BUF_INIT m_cb_download_conn_da_init;//callback function which is invoked at the beginning of DA transimitting.

+   void *m_cb_download_conn_da_init_arg; // parameter of the callback function upper

+

+   CALLBACK_DOWNLOAD_PROGRESS  m_cb_download_conn; //callback function which is invoked during the firmware transimitting.

+   void  *m_cb_download_conn_arg; // parameter of the callback function upper

+

+   CALLBACK_CONN_BROM_WRITE_BUF  m_cb_download_conn_da; //callback function which is invoked during the DA transimitting.

+   void *m_cb_download_conn_da_arg; // parameter of the callback function upper

+   

+}FLASHTOOL_ARG;

+

+

+/*******************************************************************************

+ * Function name:

+ * ---------

+ *  FlashDownload

+ *

+ * Description:

+ * ------------

+ *  This funciton is used to manage the download flow.

+ *  The communication flow please refer to the BromDLL document.

+ *  'BL_PRINT' is a sample to output debug log.

+ *

+ * Input:

+ * --------

+ *  arg: download arguments structure includes callback function and parameter. 

+ *  GPS_da: import Download Agent(DA) buffer and size. 

+ *  GPS_image_list:  import firmware buffer and size.

+ *

+ *******************************************************************************/

+extern int  FlashDownload(

+   GPS_DA* GPS_da,

+   GPS_Image_List* GPS_image_list,

+   GPS_Download_Arg arg);

+

+void* flashtool_download_thread(void *arg);

+int flashtool_file_isvalid(void);

+

+

+#ifdef   __cplusplus

+}

+#endif

+

+#endif

+

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.c
new file mode 100644
index 0000000..c1deed2
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.c
@@ -0,0 +1,226 @@
+#ifdef CONFIG_GPS_MT3303

+

+/*******************************************************************************

+*  Copyright Statement:

+*  --------------------

+*  This software is protected by Copyright and the information contained

+*  herein is confidential. The software may not be copied and the information

+*  contained herein may not be used or disclosed except with the written

+*  permission of MediaTek Inc. (C) 2016

+*

+*******************************************************************************/

+

+/*******************************************************************************

+ *

+ * Filename:

+ * ---------

+ *       gps_uart.c

+ *

+ * Description:

+ * ------------

+ *    This file defines the sample code of uart driver.

+ *    User must implement all the functions in this file based on your MCU.

+ *

+ *******************************************************************************/

+#include "gps_uart.h"

+#include "sw_types.h"

+#include <stdio.h>

+#include <stdarg.h>

+#include <sys/time.h>

+#include <string.h>

+#include <sys/epoll.h>

+#include <errno.h>

+#include <pthread.h>

+#include <termios.h>

+#include <time.h>

+#include <unistd.h>

+

+#include "mtk_auto_log.h"

+

+#ifdef LOG_TAG

+#undef LOG_TAG

+#define LOG_TAG "flashtool"

+#endif

+

+extern int g_fd_mt3333_data;

+static uint32 err_threshold = 0xFFFFF; //Timeout flag, can be changed.

+

+void GPS_UART_IgnoreData(void)

+{

+    uint8 buf[1024];

+    int count=0;

+    while(1)

+    {

+        count = read(g_fd_mt3333_data, &buf, 1024);

+        if(count>=0){

+            LOGE("count=%d",count);

+             continue;

+        }

+        break;

+    }

+

+    //usleep(500 * 1000);

+

+    while(1)

+    {

+        count = read(g_fd_mt3333_data, &buf, 1024);

+        if(count>=0){

+            LOGE("count1=%d",count);

+             continue;

+        }

+        break;

+    }

+}

+

+void GPS_UART_Init(void)    

+{

+

+    /* uart pinmux configure */

+

+    /* enable uart clock */

+    

+    //Set Baudrate

+

+}

+

+//Get one byte data from UART and return this byte.

+//This function should wait in a while loop until received a data.

+uint8 GPS_UART_GetByte(void)

+{

+    uint8    g_uart_last_rx_data = 0;

+

+    while(1)

+    {

+        if(1 == read(g_fd_mt3333_data, &g_uart_last_rx_data, 1)){

+            return g_uart_last_rx_data;

+        }

+    }

+}

+

+//Get one byte data from UART and output this byte by formal parameter.

+//This function will return finally if received a data or timeout.

+BOOL GPS_UART_GetByteStatus(uint8 *data)

+{

+    //uint8    g_uart_last_rx_data = 0;

+    uint32  err_count=0;

+

+    while((err_count++)<err_threshold)

+    {

+        if(1 == read(g_fd_mt3333_data, data, 1)){

+            return TRUE;

+        }

+    }

+    return FALSE;

+}

+

+//Get one byte data from UART and output this byte by formal parameter.

+//This function will return immediatelly after trying reading data from UART no matter any data is read.

+BOOL GPS_UART_GetByte_NO_TIMEOUT(uint8 *data)

+{    

+    if(1 == read(g_fd_mt3333_data, data, 1)){

+        return TRUE;

+    }

+    return FALSE;

+}

+

+//Read data from UART, read length is defined by input parameter, and output the string by formal parameter.

+BOOL GPS_UART_GetByte_Buffer(uint32* buf, uint32 length)

+{

+    bool ret;

+    uint32 i;

+    uint8 * buf8 = (uint8*)buf;

+

+    for(i=0; i<length; i++)

+    {

+        ret = GPS_UART_GetByteStatus(buf8+i);

+        if(!ret){ return FALSE;}

+    }

+

+    return TRUE;

+}

+void GPS_UART_Flush(void)

+{

+    LOGE("result:%d",fsync(g_fd_mt3333_data));

+}

+

+//Put one byte data to UART.

+void GPS_UART_PutByte(uint8 data)

+{

+    while(1)

+    {

+        if(1 == write(g_fd_mt3333_data, &data, 1)){

+            return;

+        }

+    }

+}

+

+//Put data to UART, write buffer and length are defined by input parameter.

+void GPS_UART_PutByte_Buffer(uint32* buf, uint32 length)

+{

+    uint32 i;

+    uint8* tmp_buf = (uint8*)buf;

+

+    for(i=0; i < length; i++)

+    {

+        GPS_UART_PutByte(*(tmp_buf+i));

+    }

+}

+

+//Get 16 bits data from UART.

+uint16 GPS_UART_GetData16(void)            //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint16     tmp16;

+    uint16  result =0;

+    for (index =0;index < 2;index++)

+    {

+        tmp = GPS_UART_GetByte();

+        tmp16 = (uint16)tmp;

+        result |= (tmp16 << (8-8*index));

+    }

+    return result;

+}

+

+//Put 16 bits data from UART.

+void GPS_UART_PutData16(uint16 data)        //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint16     tmp16;

+

+    for (index =0;index < 2;index++)

+    {

+        tmp16 = (data >> (8-8*index));

+        tmp = (uint8)tmp16;

+        GPS_UART_PutByte(tmp);

+    }

+}

+

+//Get 32 bits data from UART.

+uint32 GPS_UART_GetData32(void)            //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint32     tmp32;

+    uint32  result =0;

+    for (index =0;index < 4;index++)

+    {

+        tmp = GPS_UART_GetByte();

+        tmp32 = (uint32)tmp;

+        result |= (tmp32 << (24-8*index));

+    }

+    return result;

+}

+

+//Put 32 bits data from UART.

+void GPS_UART_PutData32(uint32 data)        //ok, high byte is first

+{

+    uint8    tmp,index;

+    uint32     tmp32;

+

+    for (index =0;index < 4;index++)

+    {

+        tmp32 = (data >> (24-8*index));

+        tmp = (uint8)tmp32;

+        GPS_UART_PutByte(tmp);

+    }

+}

+#endif

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.h
new file mode 100644
index 0000000..3b98daa
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/gps_uart.h
@@ -0,0 +1,49 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ *******************************************************************************/

+//Sample code of gps_uart.h

+//User must implement this file based on your MCU.

+

+#include "sw_types.h"

+

+

+#define UART2_base       (0x00000000)

+

+//UART2 MMP address

+#define   UART2_RBR		(UART2_base+0x0000)		/* Read only */

+#define   UART2_THR		(UART2_base+0x0000)		/* Write only */

+#define   UART2_LSR		(UART2_base+0x0014)

+

+//LSR

+#define   UART_LSR_DR         	0x0001

+#define   UART_LSR_OE         	0x0002

+#define   UART_LSR_PE         	0x0004

+#define   UART_LSR_THRE     	  0x0020

+#define   UART_LSR_FIFOERR    	0x0080

+

+#define UART_ReadReg(_addr)   		(uint16)(*(volatile uint8 *)_addr)

+#define UART_WriteReg(_addr,_data)  *(volatile uint8 *)_addr = (uint8)_data

+

+

+void GPS_UART_IgnoreData(void);

+

+void GPS_UART_Init(void);

+uint8 GPS_UART_GetByte(void);

+BOOL GPS_UART_GetByteStatus(uint8 *data);

+BOOL GPS_UART_GetByte_NO_TIMEOUT(uint8 *data);

+BOOL GPS_UART_GetByte_Buffer(uint32* buf, uint32 length);

+void GPS_UART_PutByte(uint8 data);

+void GPS_UART_PutByte_Buffer(uint32* buf, uint32 length);

+uint16 GPS_UART_GetData16(void);

+void GPS_UART_PutData16(uint16 data);

+uint32 GPS_UART_GetData32(void);

+void GPS_UART_PutData32(uint32 data);

+void GPS_UART_Flush(void);

+

+

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/sw_types.h b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/sw_types.h
new file mode 100644
index 0000000..697670f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/flashdownload/sw_types.h
@@ -0,0 +1,102 @@
+/*******************************************************************************

+ *  Copyright Statement:

+ *  --------------------

+ *  This software is protected by Copyright and the information contained

+ *  herein is confidential. The software may not be copied and the information

+ *  contained herein may not be used or disclosed except with the written

+ *  permission of MediaTek Inc. (C) 2016

+ *

+ *******************************************************************************/

+

+/*******************************************************************************

+ * Filename:

+ * ---------

+ *   sw_types.h

+ *

+ * Project:

+ * --------

+ *  Flash Download Library.

+ *

+ * Description:

+ * ------------

+ *   Common type and structure definition

+ *

+ *******************************************************************************/

+

+#ifndef SW_TYPES_H

+#define SW_TYPES_H

+

+#define COMPILE_ASSERT(condition) ((void)sizeof(char[1 - 2*!!!(condition)]))

+

+/*

+ * general definitions

+ */

+

+typedef signed char    int8;

+typedef signed short   int16;

+typedef signed long    int32;

+typedef signed int     intx;

+typedef unsigned char  uint8;

+typedef unsigned short uint16;

+typedef unsigned long  uint32;

+#ifdef WIN32

+	typedef unsigned long uint64;

+#else

+	typedef unsigned long long uint64;

+#endif

+typedef unsigned int   uintx;

+typedef unsigned char  U8;

+typedef unsigned short U16;

+typedef unsigned long  U32;

+typedef int32          S32;

+typedef unsigned int   Ux;

+typedef unsigned char*  P_U8;

+typedef unsigned short* P_U16;

+typedef unsigned long*  P_U32;

+typedef unsigned int*   P_Ux;

+

+typedef int8    int8_t;

+typedef int16   int16_t;

+//typedef int32   int32_t;

+typedef uint8   uint8_t;

+typedef uint16  uint16_t;

+//typedef uint32  uint32_t;

+

+#ifndef __cplusplus

+typedef unsigned char  bool;

+#endif

+

+/*

+ * Definitions for BOOLEAN

+ */

+/*

+#define FALSE          0

+#define TRUE           1

+*/

+/*

+ * Definitions for BOOLEAN

+ */

+typedef enum BOOL

+{

+    FALSE = 0,

+    TRUE = 1

+} BOOL;

+

+

+/*

+ * Definitions for NULL

+ */

+#ifndef NULL

+#define NULL           0

+#endif

+

+/*

+ * For GFH library

+ */

+#if defined(WIN32)

+#define __WIN32_STDCALL   __stdcall

+#else

+#define __WIN32_STDCALL

+#endif

+

+#endif  /* SW_TYPES_H */

diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_controller.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_controller.c
new file mode 100644
index 0000000..6976fc6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_controller.c
@@ -0,0 +1,3373 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#include <stdio.h>   /* Standard input/output definitions */
+#include <string.h>  /* String function definitions */
+#include <unistd.h>  /* UNIX standard function definitions */
+#include <fcntl.h>   /* File control definitions */
+#include <errno.h>   /* Error number definitions */
+#include <termios.h>  /* POSIX terminal control definitions */
+#include <stdbool.h>
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <sys/un.h>
+//#include <linux/fm.h>
+#include <signal.h>
+#include <inttypes.h>
+
+#include "mtk_gps.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "mnld.h"
+#include "mnld_utile.h"
+#include "mnl2agps_interface.h"
+#include "mnl2hal_interface.h"
+#include "mtk_flp_main.h"
+#include "mtk_geofence_main.h"
+#include "gps_dbg_log.h"
+#include "mpe.h"
+#include "mtk_gps_agps.h"
+#include "mtk_gps_type.h"
+#include "mnl_common.h"
+#include "agps_agent.h"
+#include "mtk_gps_sys_fp.h"
+#include "SUPL_encryption.h"
+#include "epo.h"
+#include "qepo.h"
+#include "mtknav.h"
+#include "mtk_auto_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+
+int network_count = 0;
+int g_agc_level = 0;
+
+#if MTK_GPS_NVRAM
+//#include "CFG_GPS_File.h"
+#endif
+
+typedef enum {
+    MAIN2GPS_EVENT_START            = 0,
+    MAIN2GPS_EVENT_STOP             = 1,
+    MAIN2GPS_DELETE_AIDING_DATA     = 2,
+    GPS2GPS_NMEA_DATA_TIMEOUT       = 3,
+} main2gps_event;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gps_controlller"
+#endif
+
+/*#define QEPO_BD 1
+#define QEPO_GA 1*/
+
+#ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+#define GPS_CALI_DATA_PATH "/data/nvram/md/NVRAM/CALIBRAT/ML4A_000"
+#define GPS_CALI_DATA_DENALI_PATH "/data/nvram/md/NVRAM/CALIBRAT/EL6N_000"
+#endif
+
+#ifdef CONFIG_GPS_MT3303
+#define MNL_ATTR_PWRCTL  "/sys/class/gpsdrv/gps/pwrctl"
+#define MNL_ATTR_SUSPEND "/sys/class/gpsdrv/gps/suspend"
+#define MNL_ATTR_STATE   "/sys/class/gpsdrv/gps/state"
+#define MNL_ATTR_PWRSAVE "/sys/class/gpsdrv/gps/pwrsave"
+#define MNL_ATTR_STATUS  "/sys/class/gpsdrv/gps/status"
+#define MNL_ATTR_RDELAY  "/sys/class/gpsdrv/gps/rdelay"
+
+enum {
+    GPS_PWRCTL_UNSUPPORTED  = 0xFF,
+    GPS_PWRCTL_OFF          = 0x00,
+    GPS_PWRCTL_ON           = 0x01,
+    GPS_PWRCTL_RST          = 0x02,
+    GPS_PWRCTL_OFF_FORCE    = 0x03,
+    GPS_PWRCTL_RST_FORCE    = 0x04,
+    GPS_PWRCTL_MAX          = 0x05,
+};
+
+enum {
+    MNL_GPS_STATE_UNSUPPORTED   = 0xFF,
+    MNL_GPS_STATE_PWROFF        = 0x00, /*cleanup/power off, default state*/
+    MNL_GPS_STATE_INIT          = 0x01, /*init*/
+    MNL_GPS_STATE_START         = 0x02, /*start navigating*/
+    MNL_GPS_STATE_STOP          = 0x03, /*stop navigating*/
+    MNL_GPS_STATE_DEC_FREQ      = 0x04,
+    MNL_GPS_STATE_SLEEP         = 0x05,
+    MNL_GPS_STATE_MAX           = 0x06,
+};
+
+extern MNL_CONFIG_T mnl_config;
+extern int is_ygps_delete_data;
+
+#if 0
+/*****************************************************************************/
+static int mnl_read_attr(const char *name, unsigned char *attr) {
+    int fd = open(name, O_RDWR);
+    unsigned char buf;
+    int err = 0;
+
+    if (fd == -1) {
+        LOGE("open %s err = %s\n", name, strerror(errno));
+        return err;
+    }
+    do {
+        err = read(fd, &buf, sizeof(buf));
+    } while (err < 0 && errno == EINTR);
+    if (err != sizeof(buf)) {
+        LOGE("read fails = %s\n", strerror(errno));
+        err = -1;
+    } else {
+        err = 0;    /*no error*/
+    }
+    if (close(fd) == -1) {
+        LOGE("close fails = %s\n", strerror(errno));
+        err = (err) ? (err) : (-1);
+    }
+    if (!err)
+        *attr = buf - '0';
+    else
+        *attr = 0xFF;
+    return err;
+}
+#endif
+
+static int mnl_write_attr(const char *name, unsigned char attr) {
+    int err, fd = open(name, O_RDWR);
+    char buf[] = {attr + '0'};
+
+    if (fd == -1) {
+        LOGE("open %s err = %s\n", name, strerror(errno));
+        return -errno;
+    }
+    do { err = write(fd, buf, sizeof(buf));
+    } while (err < 0 && errno == EINTR);
+
+    if (err != sizeof(buf)) {
+        LOGE("write fails = %s\n", strerror(errno));
+        err = -errno;
+    } else {
+        err = 0;    // no error
+    }
+    if (close(fd) == -1) {
+        LOGE("close fails = %s\n", strerror(errno));
+        err = (err) ? (err) : (-errno);
+    }
+    LOGD("write '%d' to %s okay\n", attr, name);
+    return err;
+}
+
+#ifdef CONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL
+extern int g_fd_mt3333_data;
+extern unsigned char gps_nmea_cal_checksum(unsigned char *ptr, unsigned char len);
+
+int mnl_hot_start(void)
+{ 
+    int err=0;
+    int count=0;
+    const char hot_cmd[]="$PMTK101";
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",hot_cmd);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s\n" ,err, nmea_cmd);
+    
+    return 0;
+}
+#endif
+
+int mnl_set_pwrctl(unsigned char pwrctl) {
+    if (pwrctl < GPS_PWRCTL_MAX) {
+        #ifdef CONFIG_GPS_MT3303_WITHOUT_POWER_CONTROL
+        if(pwrctl == GPS_PWRCTL_ON) {
+            mnl_hot_start();
+            LOGD("$PMTK101 pwrctl = %d\n", pwrctl);
+        }
+        #endif
+        return mnl_write_attr(MNL_ATTR_PWRCTL, pwrctl);
+    } else {
+        LOGE("invalid pwrctl = %d\n", pwrctl);
+        errno = -EINVAL;
+        return -1;
+    }
+}
+
+#endif
+
+enum {
+    GPS_MEASUREMENT_UNKNOWN     = 0xFF,
+    GPS_MEASUREMENT_INIT        = 0x00,
+    GPS_MEASUREMENT_CLOSE       = 0x01,
+};
+enum {
+    GPS_NAVIGATION_UNKNOWN     = 0xFF,
+    GPS_NAVIGATION_INIT        = 0x00,
+    GPS_NAVIGATION_CLOSE       = 0x01,
+};
+
+#define DSP_DEV                     "/dev/stpgps" /* stp-gps char dev */
+#define DBG_DEV                     "/dev/ttygserial"
+#define BEE_PATH                    MTK_GPS_DATA_PATH
+#define DSP_BIN_LOG_FILE            MTK_GPS_DATA_PATH"DSPdebug.log"
+#define PARM_FILE                   MTK_GPS_DATA_PATH"gpsparm.dat"
+#define NV_FILE                     MTK_GPS_DATA_PATH"mtkgps.dat"
+#define OFL_NV_FILE                 MTK_GPS_DATA_PATH"mtkgps_ofl.dat"
+
+#define PATH_INTERNAL       "internal_sd"
+#define PATH_EXTERNAL       "external_sd"
+#define PATH_DEFAULT        "/mnt/sdcard/"
+#define PATH_EX             "/mnt/sdcard2/"
+#define SDCARD_SWITCH_PROP  "persist.mtklog.log2sd.path"
+/*---------------------------------------------------------------------------*/
+
+#define GET_VER
+#ifdef TCXO
+#undef TCXO
+#endif
+#define TCXO 0
+#ifdef CO_CLOCK
+#undef CO_CLOCK
+#endif
+#define CO_CLOCK 1
+#ifdef CO_DCXO
+#undef CO_DCXO
+#endif
+#define CO_DCXO 2
+
+#if defined(__ANDROID_OS_P__)
+#define GPS_CLOCK_TYPE_P    "vendor.gps.clock.type"
+#define GPS_GPS_VERSION     "vendor.gps.gps.version"
+#elif defined(__ANDROID_OS_O__)
+#define GPS_CLOCK_TYPE_P    "gps.clock.type"
+#define GPS_GPS_VERSION     "gps.gps.version"
+#endif
+
+#define COMBO_IOC_GPS_IC_HW_VERSION   7
+#define COMBO_IOC_GPS_IC_FW_VERSION   8
+
+#define COMBO_IOC_TRIGGER_WMT_ASSERT        12
+#define COMBO_IOC_TRIGGER_WMT_SUBSYS_RESET  13
+#define COMBO_IOC_TAKE_GPS_WAKELOCK         14
+#define COMBO_IOC_GIVE_GPS_WAKELOCK         15
+/*#define COMBO_IOC_GET_GPS_LNA_PIN           16*/
+
+static int g_fd_gps;
+/////////////// temporary defineded for Android ////////////
+//////////////////////////////////////////
+
+// for one binary
+#define RAW_DATA_SUPPORT 1
+#if RAW_DATA_SUPPORT
+#define GPS_CONF_FILE_SIZE 100
+#define RAW_DATA_CONTROL_FILE_PATH MTK_GPS_DATA_PATH"gps.conf"
+static int gps_raw_debug_mode = 0;
+static int mtk_msg_raw_meas_flag = 0;
+#define IS_SPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+#endif
+
+// static unsigned char gps_measurement_state = GPS_MEASUREMENT_UNKNOWN;
+// static unsigned char gps_navigation_state = GPS_NAVIGATION_UNKNOWN;
+extern unsigned char gps_debuglog_state;
+extern char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern char storagePath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+extern bool g_gpsdbglogThreadExit;
+extern MTK_GPS_MNL_INFO mtk_gps_mnl_info;
+extern UINT32 g_dbglog_file_size_in_config;    //Max dbg log file size read from config file
+extern UINT32 g_dbglog_folder_size_in_config;  //Max dbg log folder size read from config file
+
+
+UINT32 assist_data_bit_map = FLAG_HOT_START;
+#ifndef CONFIG_GPS_MT3303
+static UINT32 delete_aiding_data;
+#endif
+#if MTK_GPS_NVRAM
+int gps_nvram_valid = 0;
+ap_nvram_gps_config_struct stGPSReadback;
+#endif
+int g_is_1Hz = 1;
+int dsp_fd = -1;
+#if ANDROID_MNLD_PROP_SUPPORT
+char chip_id[PROPERTY_VALUE_MAX]={0};
+#else
+char chip_id[100]={0};
+#endif
+int epo_setconfig = 0;
+extern int gps_epo_type;
+int start_time_out = MNLD_GPS_START_TIMEOUT;
+int nmea_data_time_out = MNLD_GPS_NMEA_DATA_TIMEOUT;
+static int exit_meta_factory = 0;
+static int PDN_test_enable = 0;
+static int in_meta_factory = 0;
+
+static int gps_restart = 0;
+#define M_RESTART 0
+static SYNC_LOCK_T lock_for_sync[] = {{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0}};
+static int mtk_gps_log_hide = 0;
+
+#define HIDE_LOG_PROP "ro.mtk_log_hide_gps"
+
+#define fieldp_copy(dst, src, f)  (dst)->f  = (src)->f
+#define field_copy(dst, src, f)  (dst).f   = (src).f
+
+extern UINT8 sv_type_agps_set;
+extern UINT8 sib8_16_enable;
+extern UINT8 lppe_enable;
+extern UINT8 enable_debug2app;
+
+extern int mtk_gps_sys_init();
+extern int mtk_gps_sys_uninit();
+static int mnld_gps_start_impl(void);
+static int mnld_gps_stop_impl(void);
+static int linux_gps_init(void);
+
+#if ANDROID_MNLD_PROP_SUPPORT
+static int get_prop(int index);
+#endif
+static int gps_raw_data_enable(void);
+#if 0
+static void get_gps_measurement_clock_data();
+#endif
+static void get_gnss_measurement_clock_data();
+#if 0
+static void get_gps_navigation_event();
+#endif
+static void get_gnss_navigation_event();
+
+/////////////////////////////////////////////////////////////////////////////
+// MAIN -> GPS Control (handlers)
+static int mnld_gps_start(int delete_aiding_data_flags) {
+    LOGD("mnld_gps_start flag=0x%x", delete_aiding_data_flags);
+
+    int ret = 0;
+    assist_data_bit_map = delete_aiding_data_flags;
+
+#ifdef CONFIG_GPS_MT3303
+    ret = mnl_set_pwrctl(GPS_PWRCTL_ON);  /*if current state is power off*/
+#endif
+    if ((ret = mnld_gps_start_impl())) {
+        LOGE("mnld_gps_start() fail, ret=%d", ret);
+        return ret;
+    } else {
+        LOGD("mnld_gps_start() success");
+    }
+
+    return ret;
+}
+
+
+static int mnld_gps_stop() {
+    LOGD("mnld_gps_stop begin");
+    int err = 0;
+
+    mnld_gps_stop_nmea_monitor();
+    if ((err = mnld_gps_stop_impl())) {
+        LOGD("mnld_gps_stop_impl: err = %d", err);
+        return err;
+    } else {
+        mnld_gps_stop_done();
+        LOGD("mnld_gps_stop_impl success");
+    }
+#ifdef CONFIG_GPS_MT3303
+    mnl_set_pwrctl(GPS_PWRCTL_OFF);
+#endif
+
+    return 0;
+}
+
+static int mnld_gps_delete_aiding_data(int delete_aiding_data_flags) {
+    LOGD("mnld_gps_delete_aiding_data flag=0x%x", delete_aiding_data_flags);
+    MTK_GPS_PARAM_RESTART restart = {MTK_GPS_START_HOT};
+#ifndef CONFIG_GPS_MT3303
+    int ret = 0;
+#endif
+    if (delete_aiding_data_flags == FLAG_HOT_START) {
+        restart.restart_type = MTK_GPS_START_HOT;
+    } else if (delete_aiding_data_flags == FLAG_WARM_START) {
+        restart.restart_type = MTK_GPS_START_WARM;
+    } else if (delete_aiding_data_flags == FLAG_COLD_START) {
+        restart.restart_type = MTK_GPS_START_COLD;
+    } else if (delete_aiding_data_flags == FLAG_FULL_START) {
+        restart.restart_type = MTK_GPS_START_FULL;
+    } else if (delete_aiding_data_flags == FLAG_AGPS_START) {
+        restart.restart_type = MTK_GPS_START_AGPS;
+    } else if (delete_aiding_data_flags == FLAG_DELETE_EPH_ALM_START) {
+        restart.restart_type = MTK_GPS_START_D_EPH_ALM;
+    } else if (delete_aiding_data_flags == FLAG_DELETE_TIME_START) {
+        restart.restart_type = MTK_GPS_START_D_TIME;
+    } else if (delete_aiding_data_flags == FLAG_AGPS_HOT_START) {
+        restart.restart_type = MTK_GPS_START_HOT;
+    } else if (delete_aiding_data_flags == FLAG_AGPS_WARM_START) {
+        restart.restart_type = MTK_GPS_START_WARM;
+    } else if (delete_aiding_data_flags == FLAG_AGPS_COLD_START) {
+        restart.restart_type = MTK_GPS_START_COLD;
+    } else if (delete_aiding_data_flags == FLAG_AGPS_FULL_START) {
+        restart.restart_type = MTK_GPS_START_FULL;
+    } else if (delete_aiding_data_flags == FLAG_AGPS_AGPS_START) {
+        restart.restart_type = MTK_GPS_START_AGPS;
+    } else {
+#ifndef CONFIG_GPS_MT3303
+        assist_data_bit_map = delete_aiding_data_flags;
+        mtk_gps_delete_nv_data(assist_data_bit_map);
+#endif
+    }
+#ifndef CONFIG_GPS_MT3303
+    if ((ret = mtk_gps_set_param(MTK_PARAM_CMD_RESTART, &restart))) {
+        LOGE("GPS restart fail %d", ret);
+    }
+#else
+    is_ygps_delete_data=10;
+    mt3333_controller_delete_aiding_data(delete_aiding_data_flags);
+#endif
+    gps_restart = 1;
+    get_condition(&lock_for_sync[M_RESTART]);
+    gps_restart = 0;
+    mnld_gps_reset_done();
+    return 0;
+}
+/////////////////////////////////////////////////////////////////////////////
+
+/*****************************************************************************/
+#ifndef CONFIG_GPS_MT3303
+static MNL_CONFIG_T mnld_cfg = {
+#else
+MNL_CONFIG_T mnld_cfg = {
+    .init_speed = 921600,
+    .link_speed = 921600,
+#endif 
+    .timeout_init  = MNLD_GPS_START_TIMEOUT,
+    .timeout_monitor = MNLD_GPS_NMEA_DATA_TIMEOUT,
+    .OFFLOAD_enabled = 0,
+    .OFFLOAD_switchMode = 0,    //0: always offload mode  1: Offload/Host-base auto switch mode
+};
+
+#ifndef CONFIG_GPS_MT3303
+static MNL_CONFIG_T mnl_config = {
+#else
+MNL_CONFIG_T mnl_config = {
+#endif
+    .init_speed = 38400,
+    .link_speed = 921600,
+    .debug_nmea = 1,
+    .debug_mnl  = MNL_NEMA_DEBUG_SENTENCE,  /*MNL_NMEA_DEBUG_NORMAL,*/
+    .pmtk_conn  = PMTK_CONNECTION_SOCKET,
+    .socket_port = 7000,
+    .dev_dbg = DBG_DEV,
+    .dev_dsp = DSP_DEV,
+    .dev_gps = "UseCallback",
+    .bee_path = BEE_PATH,
+    .epo_file = EPO_FILE,
+    .epo_update_file = EPO_UPDATE_HAL,
+    .qepo_file = QEPO_FILE,
+    .qepo_update_file = QEPO_UPDATE_HAL,
+    .delay_reset_dsp = 500,
+    .nmea2file = 0,
+    .dbg2file = 0,
+    .nmea2socket = 1,
+    .dbg2socket = 0,
+    .timeout_init = 0,
+    .timeout_monitor = 0,
+    .timeout_wakeup = 0,
+    .timeout_sleep = 0,
+    .timeout_pwroff = 0,
+    .timeout_ttff = 0,
+    .EPO_enabled = 0,
+    .BEE_enabled = 0,
+    .SUPL_enabled = 1,
+    .SUPLSI_enabled = 1,
+    .EPO_priority = 64,
+    .BEE_priority = 32,
+    .SUPL_priority = 96,
+    .fgGpsAosp_Ver = 1,
+    .AVAILIABLE_AGE = 2,
+    .RTC_DRIFT = 30,
+    .TIME_INTERVAL = 10,
+    .u1AgpsMachine = 0,  // default use spirent "0"
+    .ACCURACY_SNR = 1,
+#ifndef CONFIG_GPS_MT3303
+    .GNSSOPMode = MTK_CONFIG_GPS_GLONASS_BEIDOU,     // 0: G+G; 1: G+B
+#else
+    .GNSSOPMode = MTK_CONFIG_GPS_BEIDOU,
+#endif
+    .dbglog_file_max_size = 25*1024*1024,
+    .dbglog_folder_max_size = 300*1024*1024,
+    .debug_file_name = LOG_FILE,
+    .fix_interval = 1000,
+    .pps_mode = MTK_PPS_3D_FIX,
+    .pps_delay = 0,
+    .pps_polarity = 0,
+    .pps_duty = 100,
+    .elev_mask = 5
+};
+void mtk_null(UINT16 a) {
+    LOGD("mtk_null a=%d\n", a);
+    return;
+}
+int SUPL_encrypt_wrapper(unsigned char *plain,
+                         unsigned char *cipher, unsigned int length) {
+    return SUPL_encrypt(plain, cipher, length);
+}
+
+int SUPL_decrypt_wrapper(unsigned char *plain,
+                         unsigned char *cipher, unsigned int length) {
+    return SUPL_decrypt(plain, cipher, length);
+}
+
+MTK_GPS_SYS_FUNCTION_PTR_T porting_layer_callback = {
+    .sys_gps_mnl_callback = mtk_gps_sys_gps_mnl_callback,
+    .sys_nmea_output_to_app = mtk_gps_sys_nmea_output_to_app,
+    .sys_nmea_output_to_mnld = mtk_gps_sys_nmea_output_to_mnld,
+    .sys_frame_sync_enable_sleep_mode = mtk_gps_sys_frame_sync_enable_sleep_mode,
+    .sys_frame_sync_meas_req_by_network = mtk_gps_sys_frame_sync_meas_req_by_network,
+    .sys_frame_sync_meas_req = mtk_gps_sys_frame_sync_meas_req,
+    .sys_agps_disaptcher_callback = mtk_gps_sys_agps_disaptcher_callback,
+    .sys_pmtk_cmd_cb = mtk_null,
+    .encrypt = SUPL_encrypt_wrapper,
+    .decrypt = SUPL_decrypt_wrapper,
+    .ofl_sys_rst_stpgps_req = mtk_gps_ofl_sys_rst_stpgps_req,
+    .ofl_sys_submit_flp_data = mtk_gps_ofl_sys_submit_flp_data,
+    .sys_alps_gps_dbg2file_mnld = mnl_sys_alps_gps_dbg2file_mnld,
+    .ofl_sys_mnl_offload_callback = mtk_gps_ofl_sys_mnl_offload_callback,
+    .sys_gps_mnl_data2mnld_callback = sys_gps_mnl_data2mnld_callback,
+};
+
+/*****************************************************************************/
+int mtk_gps_log_is_hide(void){
+    return !!(mtk_gps_log_hide );
+}
+
+bool mnl_offload_is_enabled() {
+    return !!(mnld_cfg.OFFLOAD_enabled);
+}
+
+void mnl_offload_set_enabled(void) {
+    mnld_cfg.OFFLOAD_enabled = 1;
+}
+
+void mnl_offload_clear_enabled(void) {
+    mnld_cfg.OFFLOAD_enabled = 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnld_timeout_ne_enabled
+ * DESCRIPTION
+ *  To get the property and check need to trigger MNLD ne or not
+ *  If timeout NE trigger enabled, will trigger NE
+ *  If timeout NE trigger disabled, will use "dump + exit" to instead NE(default)
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  None
+ *****************************************************************************/
+bool mnld_timeout_ne_enabled(void) {
+#if ANDROID_MNLD_PROP_SUPPORT
+    char result[PROPERTY_VALUE_MAX] = {0};
+
+    if((in_meta_factory == 1)
+      ||((property_get("debug.gps.mnld.ne", result, NULL) != 0) && (result[0] == '1'))) {
+        LOGD("mnld NE enabled!!!");
+        return true;
+    } else {
+        LOGD("mnld NE disabled!!!");
+        return false;
+    }
+#else
+    if(in_meta_factory == 1)  {
+        LOGD("mnld NE enabled!!!");
+        return true;
+    } else {
+        LOGD("mnld NE disabled!!!");
+        return false;
+    }
+#endif
+}
+bool mnld_support_auto_switch_mode() {
+    bool ret = false;
+    if (mnld_cfg.OFFLOAD_enabled && (mnld_cfg.OFFLOAD_switchMode == 1)) {
+        ret = true;
+    }
+    return ret;
+}
+
+bool mnld_offload_is_auto_mode() {
+    bool ret = false;
+    if (mnld_cfg.OFFLOAD_enabled && (mnld_cfg.OFFLOAD_switchMode == 1) &&
+        ((mnld_flp_session.type == MNLD_FLP_CAPABILITY_OFL_MODE) ||
+        (mnld_gfc_session.type == MNLD_GFC_CAPABILITY_OFL_MODE))) {
+        ret = true;
+    }
+    return ret;
+}
+
+bool mnld_offload_is_always_on_mode() {
+    bool ret = false;
+    if (mnld_cfg.OFFLOAD_enabled && (mnld_cfg.OFFLOAD_switchMode == 0)) {
+        ret = true;
+    }
+    return ret;
+}
+
+void mnld_offload_check_capability() {
+    if (chip_id[0] == 0) {
+        chip_detector();
+    }
+    if (strcmp(chip_id, "0x6758") == 0 || strcmp(chip_id, "0x6771") == 0
+        || strcmp(chip_id, "0x6775") == 0) {
+        mnld_cfg.OFFLOAD_enabled = 1;
+        mnld_cfg.OFFLOAD_switchMode = 1;
+        mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+        mnld_flp_session.pre_type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+        mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+        mnld_gfc_session.pre_type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+    }
+}
+
+#ifdef CONFIG_GPS_MT3303
+/*****************************************************************************/
+static int mnl_set_state(unsigned char state) {
+
+    int err;
+    if (state < MNL_GPS_STATE_MAX) {
+        if ((err = mnl_write_attr(MNL_ATTR_STATE, state)))
+            return err;
+        return 0;
+    } else {
+        LOGE("invalid state = %d\n", state);
+        errno = -EINVAL;
+        return -1;
+    }
+}
+
+#if 0
+/*****************************************************************************/
+static int mnl_get_state(unsigned char *state) {
+    return mnl_read_attr(MNL_ATTR_STATE, state);
+}
+#endif
+
+void gps_control_mnl_set_pwrctl(void) {
+    mnl_set_pwrctl(GPS_PWRCTL_RST_FORCE);
+}
+
+/*****************************************************************************/
+static int mnl_set_status(char *buf, int len) {
+    const char *name = MNL_ATTR_STATUS;
+    int err, fd = open(name, O_RDWR);
+
+    if (fd == -1) {
+        LOGE("open %s err = %s\n", name, strerror(errno));
+        return -errno;
+    }
+    do {
+        err = write(fd, buf, len);
+    } while (err < 0 && errno == EINTR);
+
+    if (err != len) {
+        LOGE("write fails = %s\n", strerror(errno));
+        err = -errno;
+    } else {
+        err = 0;    /*no error*/
+    }
+    if (close(fd) == -1) {
+        LOGE("close fails = %s\n", strerror(errno));
+        err = (err) ? (err) : (-errno);
+    }
+    return err;
+}
+
+void gps_control_mnl_set_status(void) {
+    static int restart_count = 0;
+    time_t tm;
+    struct tm *p;
+
+    time(&tm);
+    p = localtime(&tm);
+
+    restart_count++;
+    LOGD("restart_count=%d\n", restart_count);
+    if (p != NULL) {
+        char buf_restart[48];
+        snprintf(buf_restart, sizeof(buf_restart), "(%d/%d/%d %d:%d:%d) - %d/%d",
+            p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec,
+            restart_count, 0x02);  // MNL_RESTART_TIMEOUT_NMEA_MONITOR
+        mnl_set_status(buf_restart, strlen(buf_restart));
+    }
+}
+
+extern int fw_downloading; //wangguojun modify
+int gps_driver_state_init() {
+    int ret = 0;
+    if(fw_downloading==1)//wangguojun modify
+        return 0;
+    if ((ret = mnl_set_pwrctl(GPS_PWRCTL_OFF)))  /*default power off*/
+        return ret;
+    ret = mnl_set_state(MNL_GPS_STATE_INIT);
+    return ret;
+}
+
+#endif
+
+int mnl_init() {
+    if(mtk_gps_get_mnl_info(&mtk_gps_mnl_info)) {
+        LOGE("get mnl ver infor fail\n");
+    }
+    lppe_enable=mtk_gps_mnl_info.support_lppe;
+    /*setup property*/
+    if (!mnl_utl_load_property(&mnld_cfg)) {
+        start_time_out = mnld_cfg.timeout_init;
+        nmea_data_time_out = mnld_cfg.timeout_monitor;
+    }
+
+    gps_dbg_log_property_load();
+
+#ifndef CONFIG_GPS_MT3303
+    MTK_GPS_SYS_FUNCTION_PTR_T*  mBEE_SYS_FP = &porting_layer_callback;
+    if (mtk_gps_sys_function_register(mBEE_SYS_FP) != MTK_GPS_SUCCESS) {
+        LOGE("register callback for mnl fail\n");
+    }
+    else {
+        LOGD("register callback for mnl okey, mtk_gps_sys_function_register=%p\n", mtk_gps_sys_function_register);
+    }
+#endif
+    LOGD("MNLD can support offload/non-offload, ver = %s.\n", OFL_VER);
+    return 0;
+}
+void get_gps_version() {
+#if ANDROID_MNLD_PROP_SUPPORT
+    if (strcmp(chip_id, "0x0321") == 0 || strcmp(chip_id, "0x0335") == 0 ||
+        strcmp(chip_id, "0x0337") == 0 ||strcmp(chip_id, "0x6735") == 0) {
+        property_set(GPS_GPS_VERSION, "0x6735");  // Denali1/2/3
+    } else {
+        property_set(GPS_GPS_VERSION, chip_id);
+    }
+    return;
+#endif
+}
+void get_chip_sv_support_capability(unsigned char* sv_type) {
+    if (strcmp(chip_id, "0x6620") == 0 || strcmp(chip_id, "0x6628") == 0 ||
+        strcmp(chip_id, "0x3336") == 0 || strcmp(chip_id, "0x6572") == 0 ||
+        strcmp(chip_id, "0x6582") == 0 || strcmp(chip_id, "0x6592") == 0 ||
+        strcmp(chip_id, "0x6571") == 0 || strcmp(chip_id, "0x6580") == 0 ||
+        strcmp(chip_id, "0x0335") == 0 || strcmp(chip_id, "0x6570") == 0) {
+        *sv_type = 1;  // GPS only
+    } else if (strcmp(chip_id, "0x3332") == 0 || strcmp(chip_id, "0x6752") == 0 ||
+        strcmp(chip_id, "0x0321") == 0 || strcmp(chip_id, "0x0337") == 0 ||
+        strcmp(chip_id, "0x6755") == 0 || strcmp(chip_id, "0x6757") == 0 ||
+        strcmp(chip_id, "0x6763") == 0 || strcmp(chip_id, "0x6739") == 0) {
+        *sv_type = 3;  // GPS+Glonass
+    } else if (strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6630") == 0 ||
+        strcmp(chip_id, "0x6759") == 0 || strcmp(chip_id, "0x6758") == 0 ||
+        strcmp(chip_id, "0x6771") == 0 || strcmp(chip_id, "0x6775") == 0) {
+        *sv_type = 7;  // GPS+Glonass+Beidou
+    } else if (strcmp(chip_id, "0x6632") == 0) {
+        *sv_type = 15;  // GPS+Glonass+Beidou+Galileo
+    }
+}
+
+int hasAlmanac() {
+    char ch;
+    char* ptr;
+    int i = -1;
+    int size = -1;
+    FILE *fp;
+    char fileName[] = "/nvcfg/almanac.dat";
+    char str[32] = {0};
+    char strTime[32] = {0};
+    char strSatNum[32] = {0};
+    int almanac_sat_num = 0;
+
+    if ((fp = fopen(fileName, "r")) == NULL) {
+        LOGE("open file(%s) fail", fileName);
+        return 0;
+    }
+
+    fseek(fp, 0L, SEEK_END);
+    size = ftell(fp);
+    if (size == 0) {
+        LOGD("file(%s) is empty", fileName);
+        fclose(fp);
+        return 0;
+    }
+    if (fseek(fp, i, SEEK_END) == -1){
+        LOGE("fseek fail,offset:%d", i);
+        fclose(fp);
+        return 0;
+    }
+
+    ch = fgetc(fp);
+    while ((ch != '\n') && (size != 0)) {
+        i--;
+        if (fseek(fp, i, SEEK_END) == -1){
+            LOGE("fseek fail,offset:%d", i);
+            fclose(fp);
+            return 0;
+        }
+        size = ftell(fp);
+        ch = fgetc(fp);
+    }
+
+    i = 0;
+    ch = fgetc(fp);
+
+    while (!feof(fp)) {
+        if ((ch >= '0' && ch <= '9') || (ch == ',')) {
+            str[i] = ch;
+            i++;
+        }
+        ch = fgetc(fp);
+    }
+    fclose(fp);
+    LOGD("almanac.dat last line, str=%s\n", str);
+
+    ptr = strchr(str, ',');
+    if (ptr) {
+        MNLD_STRNCPY(strTime, ptr + 1, sizeof(strTime));
+        *ptr = '\0';
+        MNLD_STRNCPY(strSatNum, str, sizeof(strSatNum));
+        LOGD("strSatNum=%s, strTime=%s\n", strSatNum, strTime);
+    } else {
+        LOGD("don't find dot in almanac.dat last line, return\n");
+        return 0;
+    }
+
+    if (strlen(strSatNum) > 0) {
+        almanac_sat_num = atoi(strSatNum);
+    }
+#if ANDROID_MNLD_PROP_SUPPORT
+    if (almanac_sat_num >= 25) {
+        property_set("gps.almanac", strTime);
+        return 1;
+    } else {
+        property_set("gps.almanac", "0");
+    }
+#endif
+    return 0;
+}
+
+static int mnld_gps_start_impl(void) {
+    int ret = 0;
+    int gps_user = GPS_USER_UNKNOWN;
+
+#ifdef CONFIG_GPS_MT3303
+    char name[128] = "Version: MTK_MNLD_5_6_0_18041201, GNSS chip is 3303, there is no MNL";
+#else
+    char name[128] = "Version: MTK_MNLD_5_6_0_18041201, MNL_5_0_W1824_MP";
+#endif
+    gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+    //LOGD("mnld_gps_start_impl");
+    mnl_utl_load_property(&mnl_config);
+
+    g_dbglog_file_size_in_config = mnl_config.dbglog_file_max_size;
+    g_dbglog_folder_size_in_config = mnl_config.dbglog_folder_max_size;
+
+    gps_user = mtk_gps_get_gps_user();
+    LOGD("gps_user=0x%x\n", gps_user);
+#ifndef CONFIG_GPS_MT3303
+        mtk_gps_ofl_set_user(gps_user);
+#endif
+
+    // GNSS HIDL v1.1 update driver/mnl version
+        mnl2hal_update_gnss_name(name, strlen(name));
+
+    /*initialize system resource (message queue, mutex) used by library*/
+    if ((ret = mtk_gps_sys_init())) {
+        LOGD("mtk_gps_sys_init err = %d\n", errno);
+    } else {
+        LOGD("mtk_gps_sys_init() success\n");
+    }
+    // mnld_gps_start_nmea_monitor();
+    // start library gps run
+    if ((ret = linux_gps_init())) {
+        LOGE("linux_gps_init err = %d\n", errno);
+        mnld_gps_stop_impl();
+        return ret;
+    } else {
+        LOGD("linux_gps_init() success\n");
+    }
+
+    if ((ret = linux_setup_signal_handler())) {
+        LOGE("linux_setup_signal_handler err = %d\n", errno);
+        mnld_gps_stop_impl();
+        return ret;
+    } else {
+        LOGD("linux_setup_signal_handler() success\n");
+    }
+
+    get_gps_version();
+    return ret;
+}
+
+/*****************************************************************************/
+#ifndef CONFIG_GPS_MT3303
+static int linux_gps_init(void) {
+    int clock_type;
+    int gnss_mode_flag = 0;
+    INT32 status = MTK_GPS_SUCCESS;
+    static MTK_GPS_INIT_CFG init_cfg;
+    static MTK_GPS_DRIVER_CFG driver_cfg;
+    MTK_GPS_BOOT_STATUS mnl_status = 0;
+    double latitude, longitude;
+    int accuracy  = 100;
+    int ret_val = 0;
+    int dsp_open_retry;
+
+    memset(&init_cfg, 0, sizeof(MTK_GPS_INIT_CFG));
+    memset(&driver_cfg, 0, sizeof(MTK_GPS_DRIVER_CFG));
+    MTK_AGPS_USER_PROFILE userprofile;
+    memset(&userprofile, 0, sizeof(MTK_AGPS_USER_PROFILE));
+    //  ====== default config ======
+    init_cfg.if_type = MTK_IF_UART_NO_HW_FLOW_CTRL;
+    init_cfg.if_link_spd = 115200;              //  115200bps
+
+    init_cfg.pps_mode = mnl_config.pps_mode;
+    init_cfg.pps_delay= mnl_config.pps_delay;
+    init_cfg.pps_polarity= mnl_config.pps_polarity;
+    init_cfg.pps_duty = mnl_config.pps_duty;
+    init_cfg.elev_mask = mnl_config.elev_mask;
+
+    UINT32 hw_ver = 0;
+    UINT32 fw_ver = 0;
+    UINT32 lna_pin = 0;
+
+#ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+    typedef struct gps_nvram_t {
+        unsigned int C0;
+        unsigned int C1;
+        unsigned int initU;
+        unsigned int lastU;
+    }GPS_NVRAM_COCLOCK_T;
+    GPS_NVRAM_COCLOCK_T gps_clock_calidata;
+    int fd = -1;
+    int read_size;
+    if ((strcmp(chip_id, "0x6735") == 0) || (strcmp(chip_id, "0x0321") == 0)
+        || (strcmp(chip_id, "0x0335") == 0) || (strcmp(chip_id, "0x0337") == 0)) {
+        LOGD("Denali calibration,chip_id:%s",chip_id);
+        //fd = open(GPS_CALI_DATA_DENALI_PATH, O_RDONLY, 660);
+        fd = open(GPS_CALI_DATA_DENALI_PATH, O_RDONLY);
+    } else {
+        LOGD("Other calibration,chip_id:%s",chip_id);
+        //fd = open(GPS_CALI_DATA_PATH, O_RDONLY, 660);
+        fd = open(GPS_CALI_DATA_DENALI_PATH, O_RDONLY);
+    }
+
+    if (fd == -1) {
+        LOGD("open error is %s\n", strerror(errno));
+        gps_clock_calidata.C0 = 0x0;
+        gps_clock_calidata.C1 = 0x0;
+        gps_clock_calidata.initU = 0x0;
+        gps_clock_calidata.lastU = 0x0;
+    } else {
+        if ((strcmp(chip_id, "0x6763") == 0) || (strcmp(chip_id, "0x6739") == 0)
+            || (strcmp(chip_id, "0x6771") == 0)) {
+            LOGD("lseek calibration file for 93MD");
+            if (lseek(fd, 0x40, SEEK_SET) < 0) {
+                LOGW("MD NVRam file lseek failed!!\n");
+            }
+        }
+        read_size = read(fd, &gps_clock_calidata, sizeof(GPS_NVRAM_COCLOCK_T));
+        if (read_size != sizeof(GPS_NVRAM_COCLOCK_T)) {
+            LOGD("read size is %d, structure size is %d\n", read_size, sizeof(GPS_NVRAM_COCLOCK_T));
+        }
+        close(fd);
+        fd = -1;
+    }
+    init_cfg.C0 = gps_clock_calidata.C0;
+    init_cfg.C1 = gps_clock_calidata.C1;
+    init_cfg.initU = gps_clock_calidata.initU;
+    init_cfg.lastU = gps_clock_calidata.lastU;
+#endif
+#if MTK_GPS_NVRAM
+    if (gps_nvram_valid == 1) {
+        init_cfg.hw_Clock_Freq = stGPSReadback.gps_tcxo_hz;            //  26MHz TCXO,
+        init_cfg.hw_Clock_Drift = stGPSReadback.gps_tcxo_ppb;                 //  0.5ppm TCXO
+        init_cfg.Int_LNA_Config = stGPSReadback.gps_lna_mode;                   //  0 -> Mixer in , 1 -> Internal LNA
+        init_cfg.u1ClockType = stGPSReadback.gps_tcxo_type;  // clk_type;
+  #ifdef MTK_GPS_CO_CLOCK_DATA_IN_MD
+        if (strcmp(chip_id, "0x6580") == 0 || strcmp(chip_id, "0x6570") == 0) {
+          LOGD("calibration read from AP NVRAM\n");
+          init_cfg.C0 = stGPSReadback.C0;
+          init_cfg.C1 = stGPSReadback.C1;
+          init_cfg.initU = stGPSReadback.initU;
+          init_cfg.lastU = stGPSReadback.lastU;
+        }
+  #else
+        init_cfg.C0 = stGPSReadback.C0;
+        init_cfg.C1 = stGPSReadback.C1;
+        init_cfg.initU = stGPSReadback.initU;
+        init_cfg.lastU = stGPSReadback.lastU;
+  #endif
+    } else {
+#endif
+        init_cfg.hw_Clock_Freq = 26000000;             //  26MHz TCXO
+        init_cfg.hw_Clock_Drift = 2000;                 //  0.5ppm TCXO
+        init_cfg.Int_LNA_Config = 0;                    //  0 -> Mixer in , 1 -> Internal LNA
+        init_cfg.u1ClockType = 0xFF;  // clk_type;
+#if MTK_GPS_NVRAM
+    }
+#endif
+    if (init_cfg.hw_Clock_Drift == 0) {
+        LOGD("customer didn't set clock drift value, use default value\n");
+        init_cfg.hw_Clock_Drift = 2000;
+    }
+
+    /*setting 1Hz/5Hz */
+#if 0
+    if (g_is_1Hz) {
+        init_cfg.fix_interval = 1000;               //  1Hz update rate
+    } else {
+        init_cfg.fix_interval = 200;               //  5Hz update rate
+    }
+#endif
+
+#ifdef MTK_ADR_SUPPORT
+    init_cfg.fix_interval = 1000;                //  1Hz update rate
+#else
+    if(mnl_config.fix_interval == 200 || mnl_config.fix_interval == 500 ||
+        mnl_config.fix_interval == 1000 || (mnl_config.fix_interval >= 100 &&
+        mnl_config.GNSSOPMode == MTK_CONFIG_GPS_ONLY)) {
+        init_cfg.fix_interval = mnl_config.fix_interval;
+    }else{
+        init_cfg.fix_interval = 1000;
+    }
+    LOGD("init_cfg.fix_interval = %d \n", init_cfg.fix_interval);
+#endif
+
+    init_cfg.datum = MTK_DATUM_WGS84;           //  datum
+    init_cfg.dgps_mode = MTK_DGPS_MODE_SBAS;    //  enable SBAS
+
+    dsp_open_retry = 0;
+    while (1) {
+        dsp_fd = open(mnl_config.dev_dsp, O_RDWR);
+        if (dsp_fd == -1) {
+            LOGD("open_port: Unable to open - %s \n", mnl_config.dev_dsp);
+            if (dsp_open_retry <= 20) {
+                usleep(1000*1000);
+                dsp_open_retry++;
+                LOGD("open_port: sleep and contine to do %d retry", dsp_open_retry);
+                continue;
+            } else {
+                LOGE("open_port: %d retry still fail, return err", dsp_open_retry);
+            }
+            return MTK_GPS_ERROR;
+        } else {
+            LOGD("open dsp successfully\n");
+        }
+        break;
+    }
+#if ANDROID_MNLD_PROP_SUPPORT
+{
+    char result[PROPERTY_VALUE_MAX] = {0};
+    property_get(HIDE_LOG_PROP, result, NULL);
+    if (result[0] == '1') {
+        mtk_gps_log_hide = 1;
+    }else{
+        mtk_gps_log_hide = 0;
+    }
+}
+#endif
+
+    if (chip_id[0] == 0) {
+        chip_detector();
+    }
+
+#if ANDROID_MNLD_PROP_SUPPORT
+    // strcpy(driver_cfg.mnl_chip_id, chip_id);
+    if (strcmp(chip_id, "0x6592") == 0 || strcmp(chip_id, "0x6571") == 0
+        || strcmp(chip_id, "0x6580") == 0 || strcmp(chip_id, "0x0321") == 0
+        || strcmp(chip_id, "0x0335") == 0 || strcmp(chip_id, "0x0337") == 0
+        || strcmp(chip_id, "0x6735") == 0 || strcmp(chip_id, "0x8163") == 0
+        || strcmp(chip_id, "0x8127") == 0 || strcmp(chip_id, "0x6755") == 0
+        || strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6757") == 0
+        || strcmp(chip_id, "0x6759") == 0 || strcmp(chip_id, "0x6763") == 0
+        || strcmp(chip_id, "0x6758") == 0 || strcmp(chip_id, "0x6570") == 0
+        || strcmp(chip_id, "0x6739") == 0 || strcmp(chip_id, "0x6771") == 0
+        || strcmp(chip_id, "0x6775") == 0) {
+        clock_type = ioctl(dsp_fd, 11, NULL);
+        clock_type = clock_type & 0x00ff;
+        switch (clock_type) {
+        case 0x00:
+            LOGD("TCXO, buffer 2\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x10:
+            LOGD("TCXO, buffer 1\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "10") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x20:
+            LOGD("TCXO, buffer 2\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x30:
+            LOGD("TCXO, buffer 3\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "30") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x40:
+            LOGD("TCXO, buffer 4\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "40") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x01:
+            LOGD("GPS coclock, buffer 2, coTMS\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x02:
+        case 0x03:
+            LOGD("TCXO, buffer 2, coVCTCXO\n");
+            init_cfg.u1ClockType = 0xFF;
+            if (property_set(GPS_CLOCK_TYPE_P, "20") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x11:
+            LOGD("GPS coclock, buffer 1\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "11") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x21:
+            LOGD("GPS coclock, buffer 2\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "21") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x31:
+            LOGD("GPS coclock, buffer 3\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "31") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        case 0x41:
+            LOGD("GPS coclock, buffer 4\n");
+            init_cfg.u1ClockType = 0xFE;
+            if (property_set(GPS_CLOCK_TYPE_P, "41") != 0)
+                LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+            break;
+        default:
+            LOGE("unknown clock type, clocktype = %x\n", clock_type);
+        }
+    } else {
+        if (strcmp(chip_id, "0x6572") == 0 || strcmp(chip_id, "0x6582") == 0
+            || strcmp(chip_id, "0x6630") == 0 || strcmp(chip_id, "0x6752") == 0
+            || strcmp(chip_id, "0x6632") == 0) {
+            if (0xFF == init_cfg.u1ClockType) {
+                LOGD("TCXO\n");
+                if (property_set(GPS_CLOCK_TYPE_P, "90") != 0) {
+                    LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+                }
+            } else if (0xFE == init_cfg.u1ClockType) {
+                LOGD("GPS coclock\n");
+                if (property_set(GPS_CLOCK_TYPE_P, "91") != 0) {
+                    LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+                }
+            } else {
+                LOGD("GPS unknown clock\n");
+            }
+        }
+        /*Add clock type to display on YGPS by mtk06325 2013-12-09 end */
+    }
+#endif
+    if (ioctl(dsp_fd, 10, NULL) == 1) {
+        LOGD("clear RTC\n");
+        delete_aiding_data = GPS_DELETE_TIME;
+    }
+
+    if (strcmp(chip_id, "0x6628") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6628;
+        init_cfg.reservedx = MT6628_E1;
+    } else if (strcmp(chip_id, "0x6630") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6630;
+        if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_HW_VERSION, &hw_ver) < 0) {
+            LOGD("get COMBO_IOC_GPS_IC_HW_VERSION failed\n");
+            return MTK_GPS_ERROR;
+        }
+
+        if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_FW_VERSION, &fw_ver) < 0) {
+            LOGD("get COMBO_IOC_GPS_IC_FW_VERSION failed\n");
+            return MTK_GPS_ERROR;
+        }
+
+        if ((hw_ver == 0x8A00) && (fw_ver == 0x8A00)) {
+            LOGD("MT6630_E1\n");
+            init_cfg.reservedx = MT6630_E1;
+        } else if ((hw_ver == 0x8A10) && (fw_ver == 0x8A10)) {
+            LOGD("MT6630_E2\n");
+            init_cfg.reservedx = MT6630_E2;
+        } else if ((hw_ver >= 0x8A11) && (fw_ver >= 0x8A11)) {
+            LOGD("MT6630 chip dection done,hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+            init_cfg.reservedx = MT6630_E2;  /*mnl match E1 or not E1,so we send MT6630_E2 to mnl */
+        } else {
+            LOGD("hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+            init_cfg.reservedx = MT6630_E2; /*default value*/
+        }
+    } else if (strcmp(chip_id, "0x6572") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6572;
+        init_cfg.reservedx = MT6572_E1;
+    } else if (strcmp(chip_id, "0x6570") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6570;
+        init_cfg.reservedx = MT6570_E1;
+    } else if (strcmp(chip_id, "0x6571") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6571;
+        init_cfg.reservedx = MT6571_E1;
+    } else if (strcmp(chip_id, "0x8127") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6571;
+        init_cfg.reservedx = MT6571_E1;
+    } else if (strcmp(chip_id, "0x6582") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6582;
+        init_cfg.reservedx = MT6582_E1;
+    } else if (strcmp(chip_id, "0x6592") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6592;
+        init_cfg.reservedx = MT6592_E1;
+    } else if (strcmp(chip_id, "0x3332") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT3332;
+        init_cfg.reservedx = MT3332_E2;
+    } else if (strcmp(chip_id, "0x6752") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6752;
+        init_cfg.reservedx = MT6752_E1;
+    } else if (strcmp(chip_id, "0x8163") == 0) {
+        mnl_config.GNSSOPMode = 3;  // gps only
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6735M;
+        init_cfg.reservedx = MT6735M_E1;
+    } else if (strcmp(chip_id, "0x6580") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6580;
+        init_cfg.reservedx = MT6580_E1;
+    } else if (strcmp(chip_id, "0x0321") == 0) {  // Denali1
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6735;
+        init_cfg.reservedx = MT6735_E1;
+
+        gnss_mode_flag = ioctl(dsp_fd, 9, NULL);  //  32'h10206198 value is 01
+        LOGD("gnss_mode_flag=%d \n", gnss_mode_flag);
+
+        if (((gnss_mode_flag & 0x01000000) != 0) && ((gnss_mode_flag & 0x02000000) == 0)) {
+            mnl_config.GNSSOPMode = 3;  //  gps only
+        }
+    } else if (strcmp(chip_id, "0x0335") == 0) {   // Denali2
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6735M;
+        init_cfg.reservedx = MT6735M_E1;
+    } else if (strcmp(chip_id, "0x0337") == 0) {    // Denali3
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6753;
+        init_cfg.reservedx = MT6753_E1;
+    } else if (strcmp(chip_id, "0x6739") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6739;
+        init_cfg.reservedx = MT6739_E1;
+    } else if (strcmp(chip_id, "0x6755") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6755;
+        init_cfg.reservedx = MT6755_E1;
+
+        gnss_mode_flag = ioctl(dsp_fd, 9, NULL);  // 32'h10206048 value is 01
+        LOGD("gnss_mode_flag=%d \n", gnss_mode_flag);
+
+        if (((gnss_mode_flag & 0x01000000) != 0) && ((gnss_mode_flag & 0x02000000) == 0)) {
+            mnl_config.GNSSOPMode = 3;  // gps only
+        }
+    } else if (strcmp(chip_id, "0x6763") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6763;
+        init_cfg.reservedx = MT6763_E1;
+    } else if (strcmp(chip_id, "0x6797") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6797;
+        init_cfg.reservedx = MT6797_E1;
+    } else if (strcmp(chip_id, "0x6757") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6757;
+        init_cfg.reservedx = MT6757_E1;
+
+        gnss_mode_flag = ioctl(dsp_fd, 9, NULL);  // 32'h10206048 value is 01
+        LOGD("gnss_mode_flag=%d \n", gnss_mode_flag);
+
+        if (((gnss_mode_flag & 0x01000000) != 0) && ((gnss_mode_flag & 0x02000000) == 0)) {
+            mnl_config.GNSSOPMode = 3;  // gps only
+        }
+    } else if (strcmp(chip_id, "0x6758") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6758;
+        init_cfg.reservedx = MT6758_E1;
+    } else if (strcmp(chip_id, "0x6759") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6759;
+        init_cfg.reservedx = MT6759_E1;
+    } else if (strcmp(chip_id, "0x6771") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6771;
+        init_cfg.reservedx = MT6771_E1;
+    } else if (strcmp(chip_id, "0x6775") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6775;
+        init_cfg.reservedx = MT6775_E1;
+    } else if (strcmp(chip_id, "0x6632") == 0) {
+        init_cfg.reservedy = (void *)MTK_GPS_CHIP_KEY_MT6632;
+        if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_HW_VERSION, &hw_ver) < 0) {
+            LOGD("get COMBO_IOC_GPS_IC_HW_VERSION failed\n");
+            return MTK_GPS_ERROR;
+        }
+        if (ioctl(dsp_fd, COMBO_IOC_GPS_IC_FW_VERSION, &fw_ver) < 0) {
+            LOGD("get COMBO_IOC_GPS_IC_FW_VERSION failed\n");
+            return MTK_GPS_ERROR;
+        }
+
+        if ((hw_ver == 0x8A00) && (fw_ver == 0x8A00)) {
+            LOGD("MT6632_E1\n");
+            init_cfg.reservedx = MT6632_E1;
+        } else if ((hw_ver >= 0x8A10) && (fw_ver >= 0x8A10)) {
+            LOGD("MT6632 chip dection done, hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+            init_cfg.reservedx = MT6632_E3;
+        } else {
+            LOGD("hw_ver = %d and fw_ver = %d\n", hw_ver, fw_ver);
+            init_cfg.reservedx = MT6632_E3; /*default value*/
+            mnl_config.GNSSOPMode = 6;
+        }
+    } else {
+        LOGE("chip is unknown, chip id is %s\n", chip_id);
+    }
+
+    LOGD("Get chip version type (%p) \n", init_cfg.reservedy);
+    LOGD("Get chip version value (%d) \n", init_cfg.reservedx);
+
+    /*if (ioctl(dsp_fd, COMBO_IOC_GET_GPS_LNA_PIN, &lna_pin) < 0) {
+        LOGE("get COMBO_IOC_GET_GPS_LNA_PIN failed\n");
+    }*/
+    init_cfg.eLNA_pin_num = lna_pin;
+
+    if (gps_epo_type == 0) {
+        if (((mnl_config.GNSSOPMode & 0x000f) != 0) && ((mnl_config.GNSSOPMode & 0x000f) != 2)) {
+            //gps_epo_type = 1;
+        }
+    }
+
+    if (mnl_config.ACCURACY_SNR == 1) {
+        init_cfg.reservedx |=(UINT32)0x80000000;
+    } else if (mnl_config.ACCURACY_SNR == 2) {
+        init_cfg.reservedx |=(UINT32)0x40000000;
+    } else if (mnl_config.ACCURACY_SNR == 3) {
+        init_cfg.reservedx |=(UINT32)0xC0000000;
+    }
+    init_cfg.mtk_gps_version_mode = MTK_GPS_AOSP_MODE;
+    //LOGD("mtk_gps_version_mode = %d\n", init_cfg.mtk_gps_version_mode);
+
+    /*mnl_config.GNSSOPMode |= 0x0300;  // default AGps On, AGlonass On, ABeidou Off
+    if ((sv_type_agps_set | 0xef) == 0xef) {  // locationEM2 AGlonass button off
+        mnl_config.GNSSOPMode &= ~(0x0200);
+    }
+    if ((sv_type_agps_set & 0x40) == 0x40) {   // locationEM2 ABeidou button on
+        mnl_config.GNSSOPMode |= 0x0400;
+    } else {
+        mnl_config.GNSSOPMode &= ~(0x0400);
+    }*/
+    init_cfg.GNSSOPMode = mnl_config.GNSSOPMode;
+    LOGI("GNSSOPMode: 0x%x\n", init_cfg.GNSSOPMode);
+
+    MNLD_STRNCPY(driver_cfg.nv_file_name, NV_FILE,sizeof(driver_cfg.nv_file_name));
+    MNLD_STRNCPY(driver_cfg.ofl_nv_file_name, OFL_NV_FILE ,sizeof(driver_cfg.ofl_nv_file_name));
+    // strcpy(driver_cfg.dbg_file_name, LOG_FILE);
+    MNLD_STRNCPY(driver_cfg.nmeain_port_name, mnl_config.dev_dbg ,sizeof(driver_cfg.nmeain_port_name));
+    MNLD_STRNCPY(driver_cfg.nmea_port_name, mnl_config.dev_gps ,sizeof(driver_cfg.nmea_port_name));
+    MNLD_STRNCPY(driver_cfg.dsp_port_name, mnl_config.dev_dsp ,sizeof(driver_cfg.dsp_port_name));
+    MNLD_STRNCPY((char *)driver_cfg.bee_path_name, mnl_config.bee_path ,sizeof(driver_cfg.bee_path_name));
+    driver_cfg.reserved   =   mnl_config.BEE_enabled;
+
+    init_cfg.sv_type_agps_set = sv_type_agps_set;
+
+    extern MTK_GPS_BOOL enable_dbg_log;
+    enable_dbg_log = mnl_config.debug_nmea;
+
+    gps_debuglog_state = gps_debuglog_state | mnl_config.dbg2file;
+     // driver_cfg.DebugType: 0x01-> libmnl write file;0x11 -> libmnl write file.
+    driver_cfg.DebugType    =   gps_debuglog_state;
+    if(mnl_debug_file_check(mnl_config.debug_file_name) == MTK_GPS_SUCCESS)
+    {
+        strncpy(gps_debuglog_file_name,mnl_config.debug_file_name,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    } else {
+        LOGW("debug file(%s) invalide, use the default(%s)\r\n", mnl_config.debug_file_name, LOG_FILE);
+        strncpy(storagePath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        strncpy(gps_debuglog_file_name,LOG_FILE,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    }
+    MNLD_STRNCPY(driver_cfg.dbg_file_name, gps_debuglog_file_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+
+    driver_cfg.u1AgpsMachine = mnl_config.u1AgpsMachine;
+    MNLD_STRNCPY((char *)driver_cfg.epo_file_name, mnl_config.epo_file ,sizeof(driver_cfg.epo_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.epo_update_file_name, mnl_config.epo_update_file ,sizeof(driver_cfg.epo_update_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.qepo_file_name, mnl_config.qepo_file ,sizeof(driver_cfg.qepo_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.qepo_update_file_name, mnl_config.qepo_update_file ,sizeof(driver_cfg.qepo_update_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.qepo_bd_file_name, QEPO_BD_FILE,sizeof(driver_cfg.qepo_bd_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.qepo_bd_update_file_name, QEPO_BD_UPDATE_FILE ,sizeof(driver_cfg.qepo_bd_update_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.mtknav_file_name, MTKNAV_DAT_FILE ,sizeof(driver_cfg.mtknav_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.mtknav_update_file_name, MTKNAV_DAT_FILE_HAL ,sizeof(driver_cfg.mtknav_update_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.qepo_ga_file_name, QEPO_GA_FILE ,sizeof(driver_cfg.qepo_ga_file_name));
+    MNLD_STRNCPY((char *)driver_cfg.qepo_ga_update_file_name, QEPO_GA_UPDATE_FILE ,sizeof(driver_cfg.qepo_ga_update_file_name));
+
+    driver_cfg.log_file_max_size = MAX_DBG_LOG_FILE_SIZE;
+    driver_cfg.log_folder_max_size = MAX_DBG_LOG_DIR_SIZE;
+
+    driver_cfg.u1AgpsMachine = mnl_config.u1AgpsMachine;
+    if (driver_cfg.u1AgpsMachine == 1) {
+        LOGD("use CRTU to test\n");
+    } else {
+        LOGD("use Spirent to test\n");
+    }
+
+    if (network_count > 0) {
+        //driver_cfg.network_connect = 1; //network is connect
+    } else {
+        //driver_cfg.network_connect = 0; //network is disconnect
+    }
+    //LOGD("start gps network_count:%d", driver_cfg.network_connect);
+
+    if(mnld_is_gps_meas_enabled() && assist_data_bit_map != FLAG_HOT_START) {
+        driver_cfg.raw_meas_enable = 1;
+    } else {
+        driver_cfg.raw_meas_enable = 0;
+    }
+    LOGD("start gps raw meas enable:%d", driver_cfg.raw_meas_enable);
+
+    status = mtk_gps_delete_nv_data(assist_data_bit_map);
+
+    LOGD("u4Bitmap= %d, init_cfg.C0 = %d,init_cfg.C1 = %d,init_cfg.initU = %d,init_cfg.lastU = %d,GNSSOPMode: 0x%x,eLNA_pin:%d\n",
+        status, init_cfg.C0, init_cfg.C1, init_cfg.initU, init_cfg.lastU, init_cfg.GNSSOPMode, init_cfg.eLNA_pin_num);
+    driver_cfg.dsp_fd = dsp_fd;
+    if (strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6632") == 0 ||
+        strcmp(chip_id, "0x6759") == 0 || strcmp(chip_id, "0x6758") == 0 ||
+        strcmp(chip_id, "0x6771") == 0 || strcmp(chip_id, "0x6775") == 0) {
+        LOGD("OFFLOAD_STATUS:OFFLOAD_enabled:%d,OFFLOAD_switchMode:%d,type=%d",
+            mnld_cfg.OFFLOAD_enabled,mnld_cfg.OFFLOAD_switchMode,mnld_flp_session.type);
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            gps_control_kernel_wakelock_init();
+            mtk_gps_ofl_set_option(MNL_OFL_OPTION_ENALBE_OFFLOAD);
+            LOGD("MNL_OFL_OPTION_ENALBE_OFFLOAD = 1");
+        } else {
+            mtk_gps_ofl_set_option(0);
+            LOGD("MNL_OFL_OPTION_ENALBE_OFFLOAD = 0");
+        }
+    } else {
+        mtk_gps_ofl_set_option(0);
+        LOGD("MNL_OFL_OPTION_ENALBE_OFFLOAD = 0");
+    }
+    gps_dbg_log_thread_init();
+
+    if (PDN_test_enable == 1 || PDN_test_enable == 0) {
+        init_cfg.Int_IMAX_Config = PDN_test_enable;
+        LOGD("init_cfg.Int_IMAX_Config = %d\n", init_cfg.Int_IMAX_Config);
+    } else {
+        LOGD("PDN_test_enable has wrong number\n");
+        init_cfg.Int_IMAX_Config = 0;
+    }
+
+    LOGD("pps_config mode = %d, delay = %d, polarity = %d, duty = %d elev_mask = %d\n",
+        init_cfg.pps_mode, init_cfg.pps_delay, init_cfg.pps_polarity, init_cfg.pps_duty, init_cfg.elev_mask);
+    mnl_status = mtk_gps_mnl_run((const MTK_GPS_INIT_CFG*)&init_cfg , (const MTK_GPS_DRIVER_CFG*)&driver_cfg);
+    LOGD("Status (%d) \n", mnl_status);
+    if (mnl_status != MNL_INIT_SUCCESS) {
+        status = MTK_GPS_ERROR;
+        return status;
+    }
+    mnl_mpe_thread_init();
+
+    if (access(EPO_UPDATE_HAL, F_OK) == -1) {
+        LOGD("EPOHAL file does not exist, no EPO yet\n");
+    } else if (mnld_is_epo_download_finished() == false) {
+        LOGD("EPO is still downloading");
+    } else {
+        //LOGD("there is a EPOHAL file, please mnl update EPO.DAT from EPOHAL.DAT\n");
+        if (mtk_agps_agent_epo_file_update() == MTK_GPS_ERROR) {
+            LOGE("EPO file updates fail\n");
+        } else {
+            unlink(EPO_UPDATE_HAL);
+        }
+    }
+    if (access(QEPO_UPDATE_HAL, F_OK) == -1) {
+        LOGD("QEPOHAL file does not exist, no EPO yet\n");
+    } else {
+        //LOGD("there is a QEPOHAL file, please mnl update QEPO.DAT from QEPOHAL.DAT\n");
+        if (mtk_agps_agent_qepo_file_update() == MTK_GPS_ERROR) {
+            LOGE("QEPO file updates fail\n");
+        }
+    }
+    if (access(MTKNAV_DAT_FILE_HAL, F_OK) == -1) {
+        LOGD("MTKNAVHAL file does not exist, no MTKNAV yet\n");
+    } else {
+        //LOGD("there is a MTKNAVHAL file, please mnl update MTKNAV.DAT from MTKNAVHAL.DAT\n");
+        if (mtk_agps_agent_mtknav_file_update() == MTK_GPS_ERROR) {
+            LOGE("MTKNAV file updates fail\n");
+        } else {
+            unlink(MTKNAV_DAT_FILE_HAL);
+        }
+    }
+    LOGD("dsp port (%s),nmea port (%s),nmea dbg port (%s),dbg_file_name (%s),DebugType (%d),nv_file_name (%s), mtk_gps_log_hide:%d\n",
+        driver_cfg.dsp_port_name, driver_cfg.nmea_port_name, driver_cfg.nmeain_port_name,
+        driver_cfg.dbg_file_name, driver_cfg.DebugType, driver_cfg.nv_file_name, mtk_gps_log_hide);
+    if (epo_setconfig == 1) {
+        userprofile.EPO_enabled = mnl_config.EPO_enabled;
+    } else {
+#if ANDROID_MNLD_PROP_SUPPORT
+        userprofile.EPO_enabled = get_prop(7);
+#else
+    LOGD("Prop is not support,EPO_enabled (%d) \n", userprofile.EPO_enabled);
+#endif
+    }
+    // userprofile.EPO_enabled = mnl_config.EPO_enabled;
+    userprofile.BEE_enabled = mnl_config.BEE_enabled;
+    userprofile.SUPL_enabled = mnl_config.SUPL_enabled;
+    userprofile.EPO_priority = mnl_config.EPO_priority;
+    userprofile.BEE_priority = mnl_config.BEE_priority;
+    userprofile.SUPL_priority = mnl_config.SUPL_priority;
+    userprofile.fgGpsAosp_Ver = mnl_config.fgGpsAosp_Ver;
+    userprofile.LPPE_enabled = lppe_enable;
+    // mtk_agps_set_param(MTK_MSG_AGPS_MSG_PROFILE, &userprofile, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+#if RAW_DATA_SUPPORT
+    gps_raw_data_enable();
+#endif
+
+    unsigned int i = 0;
+    INT32 ret = MTK_GPS_ERROR;
+    bool alt_valid = false;
+    float altitude = 0.0f;
+    bool source_valid = true;
+    bool source_gnss = true;
+    bool source_nlp = false;
+    bool source_sensor = false;
+    //  if sending profile msg fail, re-try 2-times, each time sleep 10ms
+    for (i = 0; i < 3; i++) {
+        ret = mtk_agps_set_param(MTK_MSG_AGPS_MSG_PROFILE, &userprofile, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+        if (ret != MTK_GPS_SUCCESS) {
+            LOGD("%d st send profile to agent fail. try again \n", i);
+            usleep(10000);  //  sleep 10ms for init agent message queue
+        } else {
+            LOGD("%d st send profile to agent OK \n", i);
+            break;
+        }
+    }
+
+    if (mtk_gps_get_position_accuracy(&latitude, &longitude, &accuracy) == MTK_GPS_SUCCESS) {
+        if (mtk_gps_log_is_hide() == 0) {
+            LOGD("mnl init, mtk_gps_get_position_accuracy success, %lf, %lf, %d", latitude, longitude, accuracy);
+        }
+        if (accuracy < 100) {
+            ret_val = mnl2agps_location_sync(latitude, longitude, accuracy, alt_valid, altitude, source_valid, source_gnss, source_nlp, source_sensor);
+            if (0 == ret_val) {
+                LOGD("mnl2agps_location_sync success");
+            }
+        }
+    }
+    hasAlmanac();
+
+    ret = mtk_gps_set_param(MTK_PARAM_CMD_SIB8_16_ENABLE, &sib8_16_enable);
+    LOGD("sent CMD_SIB8_16_ENABLE to mnl, sib8_16_enable = %d ,ret = %d", sib8_16_enable, ret);
+    ret = mtk_gps_set_param(MTK_PARAM_CMD_DEBUG2APP_CONFIG, &enable_debug2app);
+    LOGD("sent enable_debug2app to mnl, enable_debug2app = %d ,ret = %d", enable_debug2app, ret);
+    if(mtk_gps_mnl_info.support_lppe){
+        ret = mtk_gps_set_param(MTK_PARAM_CMD_LPPE_ENABLE, &lppe_enable);
+        LOGD("sent MTK_PARAM_CMD_LPPE_ENABLE to mnl, lppe_enable = %d ,ret = %d", lppe_enable, ret);
+    }
+    return  status;
+}
+#else
+static int linux_gps_init(void) {
+ // power on gps on another place.
+#if ANDROID_MNLD_PROP_SUPPORT
+    // strcpy(driver_cfg.mnl_chip_id, chip_id);
+    if (strcmp(chip_id, "0x3303") == 0 ) {
+        LOGD("TCXO\n");
+        if (property_set(GPS_CLOCK_TYPE_P, "90") != 0) {
+            LOGE("set GPS_CLOCK_TYPE_P %s\n", strerror(errno));
+        }
+    }
+#endif
+
+#ifdef MTK_ADR_SUPPORT
+    mnl_config.fix_interval = 1000;  //1Hz update rate
+    LOGD("mnl_config.fix_interval = %d \n", mnl_config.fix_interval);
+#endif
+
+    gps_debuglog_state = gps_debuglog_state | mnl_config.dbg2file;
+    if(mnl_debug_file_check(mnl_config.debug_file_name) == MTK_GPS_SUCCESS)
+    {
+        strncpy(gps_debuglog_file_name, mnl_config.debug_file_name,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    } else {
+        LOGW("debug file(%s) invalide, use the default(%s)\r\n", mnl_config.debug_file_name, LOG_FILE);
+        strncpy(storagePath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        strncpy(gps_debuglog_file_name,LOG_FILE,GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    }
+
+    extern MTK_GPS_BOOL enable_dbg_log;
+    enable_dbg_log = mnl_config.debug_nmea;
+
+    gps_dbg_log_thread_init();
+#if RAW_DATA_SUPPORT
+    gps_raw_data_enable();
+#endif
+
+    hasAlmanac();
+
+    return  0;
+}
+
+#endif
+
+/*****************************************************************************/
+static int mnld_gps_stop_impl(void) {
+    int ret = 0;
+    LOGD("MNL exiting \n");
+#ifndef CONFIG_GPS_MT3303	
+    mtk_gps_mnl_stop();
+    LOGD("mtk_gps_mnl_stop()\n");
+#endif
+
+    if (g_gpsdbglogThreadExit == false) {
+        gps_dbg_log_exit_flush(1);
+    }
+    if ((ret = mtk_gps_sys_uninit())) {
+        LOGE("mtk_gps_sys_uninit err = %d=\n", errno);
+    }
+#ifndef CONFIG_GPS_MT3303    
+    if (dsp_fd > 0) {
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            gps_control_kernel_wakelock_uninit();
+        }
+        close(dsp_fd);
+        dsp_fd = -1;
+    }
+    mnld_gps_stop_nmea_monitor();  //Stop monitor timer again for GPS stop and nmea report timing issue
+    // cancel alarm
+    LOGD("Cancel alarm");
+    alarm(0);
+#endif
+    return ret;
+}
+
+/*****************************************************************************/
+//static time_t last_send_time = 0;
+//static time_t current_time = 0;
+
+int send_active_notify() {
+    int gps_user = mtk_gps_get_gps_user();
+    // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+    if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled()
+        && (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+        LOGE("gps_user: %d,offload: %d\n", gps_user, mnld_cfg.OFFLOAD_enabled);
+        return -1;
+    }
+    if (!(mnl_config.debug_mnl & MNL_NMEA_DISABLE_NOTIFY)) {
+        char buff[1024] = {0};
+        int offset = 0;
+        LOGD("send clean nmea timer cmd!\n");
+        put_int(buff, &offset, GPS2GPS_NMEA_DATA_TIMEOUT);
+        return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+    }
+    return -1;
+}
+
+INT32 mtk_gps_sys_gps_mnl_callback(MTK_GPS_NOTIFICATION_TYPE msg) {
+    LOGD("msg:%d\n", msg);
+    switch (msg) {
+    case MTK_GPS_MSG_FIX_READY:
+        {
+            send_active_notify();
+#if 0
+            // For NI open GPS
+            double dfRtcD = 0.0, dfAge = 0.0;
+            send_active_notify();
+            if (mtk_gps_get_rtc_info(&dfRtcD, &dfAge) == MTK_GPS_SUCCESS) {
+                LOGD("MTK_GPS_MSG_FIX_READY, GET_RTC_OK, %.3lf, %.3lf\n", dfRtcD, dfAge);
+                LOGD("Age = %d, RTCDiff = %d, Time_interval = %d\n", mnl_config.AVAILIABLE_AGE,
+                    mnl_config.RTC_DRIFT, mnl_config.TIME_INTERVAL);
+                if ((dfAge <= mnl_config.AVAILIABLE_AGE) && (dfRtcD >= mnl_config.RTC_DRIFT ||
+                    dfRtcD <= -mnl_config.RTC_DRIFT) && dfRtcD < 5000) {
+                    int fd_fmsta = -1;
+                    unsigned char buf[2]= {0};
+                    int status = -1;
+                    fd_fmsta = open("/proc/fm", O_RDWR);
+                    if (fd_fmsta < 0) {
+                        LOGD("open /proc/fm error");
+                    } else {
+                        LOGD("open /proc/fm success!");
+                        status = read(fd_fmsta, &buf, sizeof(buf));
+                        if (status < 0)
+                            LOGD("read fm status fails = %s", strerror(errno));
+                        if (close(fd_fmsta) == -1)
+                            LOGD("close fails = %s", strerror(errno));
+                    }
+
+                    if (buf[0] == '2') {
+                        INT32 time_diff;
+                        time(&current_time);
+                        time_diff = current_time - last_send_time;
+                        if ((0 == last_send_time) || (time_diff > mnl_config.TIME_INTERVAL)) {
+                            int fd_fmdev = -1;
+                            int ret = 0;
+                            struct fm_gps_rtc_info rtcInfo;
+                            fd_fmdev = open("dev/fm", O_RDWR);
+                            if (fd_fmdev < 0) {
+                                LOGD("open fm dev error\n");
+                            }
+                            else {
+                                rtcInfo.retryCnt = 2;
+                                rtcInfo.ageThd = mnl_config.AVAILIABLE_AGE;
+                                rtcInfo.driftThd = mnl_config.RTC_DRIFT;
+                                rtcInfo.tvThd.tv_sec = mnl_config.TIME_INTERVAL;
+                                rtcInfo.age = dfAge;
+                                rtcInfo.drift = dfRtcD;
+                                rtcInfo.tv.tv_sec = current_time;
+                                ret = ioctl(fd_fmdev, FM_IOCTL_GPS_RTC_DRIFT, &rtcInfo);
+                                if (ret) {
+                                    LOGD("send rtc info failed, [ret=%d]\n", ret);
+                                }
+                                ret = close(fd_fmdev);
+                                if (ret) {
+                                    LOGD("close fm dev error\n");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            else {
+                LOGD("MTK_GPS_MSG_FIX_READY,GET_RTC_FAIL\n");
+            }
+#endif
+     #if RAW_DATA_SUPPORT
+            if (gps_raw_debug_mode && !mtk_msg_raw_meas_flag) {
+                LOGD("raw_debug_mode is open, send MTK_MSG_RAW_MEAS to libmnl\n");
+
+                INT32 ret = MTK_GPS_ERROR;
+                ret = mtk_gps_set_param(MTK_MSG_RAW_MEAS, NULL);
+                LOGD("mtk_gps_set_param,ret = %d\n", ret);
+                if (ret != MTK_GPS_SUCCESS) {
+                    LOGE("send MTK_MSG_RAW_MEASto mnl fail,please reopen gps\n");
+                } else {
+                    LOGD("send MTK_MSG_RAW_MEAS to mnl OK \n");
+                    mtk_msg_raw_meas_flag = 1;  // Don't send MTK_MSG_RAW_MEAS when it was sent to mnl successfully
+                }
+            }
+
+            /*get gps measurement and clock data*/
+            if (mnld_is_gps_meas_enabled() && mnld_is_gps_started_done()) {
+                #if 0 //gnss navigation API include gps info
+                get_gps_measurement_clock_data();
+                #endif
+                get_gnss_measurement_clock_data();
+                LOGD("gps_meas_enable");
+            }
+
+            /*get gps navigation event */
+            if (mnld_is_gps_navi_enabled() && mnld_is_gps_started_done()) {
+                LOGD("gps_navi_enable");
+                #if 0 //gnss navigation API include gps info
+                get_gps_navigation_event();
+                #endif
+                get_gnss_navigation_event();
+            }
+    #endif
+            if (is_flp_user_exist() && !(mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                UINT8 buff[1024] = {0};
+                UINT8 playload[OFFLOAD_PAYLOAD_LEN] = {0};
+                UINT32 p_get_len = 0;
+                //MTK_FLP_OFFLOAD_MSG_T *prMsg = (MTK_FLP_OFFLOAD_MSG_T *)&buff[0];
+                MTK_FLP_MNL_MSG_T *prMsg = (MTK_FLP_MNL_MSG_T *)&buff[0];
+                mtk_gps_flp_get_location(playload, OFFLOAD_PAYLOAD_LEN, &p_get_len);
+                //prMsg->type = FLPMNL_GPS_REPORT_LOC;
+                prMsg->type = MNLD_FLP_TYPE_HBD_GPS_LOCATION;
+                prMsg->length = p_get_len;
+                prMsg->session = mnld_flp_session.id;
+                memcpy(&prMsg->data[0], playload, p_get_len);
+                if (-1 == mnl2flp_data_send(buff, sizeof(buff))) {
+                    LOGE("[FLP2MNLD]Send to FLP failed, %s\n", strerror(errno));
+                } else {
+                    //LOGD("[FLP2MNLD]Send to FLP successfully\n");
+                }
+            }
+            if (is_geofence_user_exist() && !(mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                UINT8 buff[1024] = {0};
+                UINT8 playload[OFFLOAD_PAYLOAD_LEN] = {0};
+                UINT32 p_get_len = 0;
+                //MTK_FLP_OFFLOAD_MSG_T *prMsg = (MTK_FLP_OFFLOAD_MSG_T *)&buff[0];
+                MTK_GFC_MNL_MSG_T *prMsg = (MTK_GFC_MNL_MSG_T *)&buff[0];
+                mtk_gps_flp_get_location(playload, OFFLOAD_PAYLOAD_LEN, &p_get_len);
+                //prMsg->type = FLPMNL_GPS_REPORT_LOC;
+                prMsg->type = MNLD_FLP_TYPE_HBD_GPS_LOCATION;
+                prMsg->length = p_get_len;
+                prMsg->session = mnld_gfc_session.id;
+                memcpy(&prMsg->data[0], playload, p_get_len);
+                if (-1 == mnl2gfc_data_send(buff, sizeof(buff))) {
+                    LOGE("[GFC2MNLD]Send to GFC failed, %s\n", strerror(errno));
+                } else {
+                    //LOGD("[GFC2MNLD]Send to GFC successfully\n");
+                }
+            }
+
+        }
+        break;
+    case MTK_GPS_MSG_FIX_PROHIBITED:
+        {
+            send_active_notify();
+            LOGD("MTK_GPS_MSG_FIX_PROHIBITED\n");
+        }
+        break;
+    default:
+        break;
+    }
+    return  MTK_GPS_SUCCESS;
+}
+
+/*****************************************************************************/
+/*Agps dispatcher state mode*/
+typedef enum {
+    ST_SI,
+    ST_NI,
+    ST_IDLE,
+    ST_UNKNOWN,
+}MTK_AGPS_DISPATCH_STATE;
+
+MTK_AGPS_DISPATCH_STATE state_mode = ST_IDLE;
+MTK_AGPS_DISPATCH_STATE last_state_mode = ST_UNKNOWN;
+int AGENT_SET_ALARM = 0;
+static void alarm_handler() {
+    if (AGENT_SET_ALARM == 1) {
+        if ((mtk_gps_get_gps_user()& GPS_USER_AGPS) != 0) {
+            // SI alarm handler: ignore, as current user is AGPS, it may in NI session
+            // NI alarm handler: ignore, as AGPSD send close_gps_req(timer be canceled)
+            return;
+        }
+        if (mnld_is_gps_and_ofl_stopped()) {
+            LOGD("GPS driver is stopped");
+            AGENT_SET_ALARM = 0;
+            last_state_mode = state_mode;
+            state_mode = ST_IDLE;
+            return;
+        }
+        // SI only session and GPS driver is running
+        LOGD("Send MTK_AGPS_SUPL_END to MNL");
+        mtk_agps_set_param(MTK_MSG_AGPS_MSG_SUPL_TERMINATE, NULL, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+        last_state_mode = state_mode;
+        state_mode = ST_IDLE;
+        LOGD("Receive MTK_AGPS_SUPL_END , last_state_mode = %d, state_mode = %d", last_state_mode, state_mode);
+    }
+    AGENT_SET_ALARM = 0;
+}
+
+void gps_controller_agps_session_done() {
+    LOGD("agps_session_done");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("GPS driver is stopped");
+        AGENT_SET_ALARM = 0;
+        last_state_mode = state_mode;
+        state_mode = ST_IDLE;
+        return;
+    }
+    if (0 == AGENT_SET_ALARM) {
+        LOGD("Set up signal & alarm!");
+        signal(SIGALRM, alarm_handler);
+        alarm(30);
+        AGENT_SET_ALARM = 1;
+    } else {
+        LOGD("AGENT_SET_ALARM == 1");
+    }
+}
+
+void gps_controller_rcv_pmtk(const char* pmtk) {
+    // LOGD("rcv_pmtk: %s", pmtk);
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_pmtk: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param(MTK_MSG_AGPS_MSG_SUPL_PMTK, pmtk, MTK_MOD_DISPATCHER, MTK_MOD_AGENT);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_PMTK\n");
+    }
+}
+
+INT32 mtk_gps_sys_agps_disaptcher_callback(UINT16 type, UINT16 length, char *data) {
+    INT32 ret = MTK_GPS_SUCCESS;
+
+    if (type == MTK_AGPS_CB_SUPL_PMTK || type == MTK_AGPS_CB_ASSIST_REQ || \
+        type == MTK_AGPS_CB_START_REQ || type == MTK_AGPS_CB_LPPE_ASSIST_REQ) {
+        if (mnl_config.SUPL_enabled) {
+            if (type == MTK_AGPS_CB_SUPL_PMTK) {
+                if (length != 0)
+                  mnl2agps_pmtk(data);
+                return 0;
+            } else if (type == MTK_AGPS_CB_ASSIST_REQ) {
+                if (state_mode == ST_IDLE || state_mode == ST_SI) {
+                    LOGD("GPS re-aiding\n");
+                    mnl2agps_reaiding_req();
+                    return 0;
+                } else {
+                    LOGE("Dispatcher in %d mode, ignore current request\n", state_mode);
+                    return MTK_GPS_ERROR;
+                }
+            }else if (type == MTK_AGPS_CB_LPPE_ASSIST_REQ) {
+                if (length != 0) {
+                    mnl2agps_lppe_assist_data_req(data,length);
+                    LOGD("request lppe data\n");
+                }
+                return 0;
+            } else if ((type == MTK_AGPS_CB_START_REQ) && (data != NULL)) {
+                LOGD("MNL ready and assist req:%d", *data);
+                int assist_req;
+                if (*data == 1) {
+                    //LOGD("Agent assist request");
+                    assist_req = 1;
+                } else if (*data == 0) {
+                    //LOGD("Agent no assist request");
+                    assist_req = 0;
+                } else {
+                    LOGD("unknown data");
+                    assist_req = 0;
+                }
+                // mnl2agps_gps_open(assist_req);
+                if (gps_restart == 1) {
+                    release_condition(&lock_for_sync[M_RESTART]);
+                    LOGD("release condition for restart");
+                }
+                mnld_gps_start_done(assist_req);
+                return ret;
+            }
+
+        } else {
+            LOGD("mtk_sys_agps_disaptcher_callback: SUPL disable");
+            ret = MTK_GPS_ERROR;
+        }
+    }  else if ((type == MTK_AGPS_CB_BITMAP_UPDATE) && (data != NULL)) {
+        LOGD("MNL NTP/NLP request:%d", *data);
+        if ((*data & 0x01) == 0x01) {
+            LOGD("Call request utc time request");
+            mnl2hal_request_utc_time();
+        }
+        if ((*data & 0x02) == 0x02) {
+            LOGD("Call nlp_server request");
+            mnld_gps_request_nlp(NLP_REQUEST_SRC_MNL);
+        }
+    } else if (type == MTK_AGPS_CB_QEPO_DOWNLOAD_REQ) {
+        UINT16 wn;
+        UINT32 tow;
+        UINT32 sys_time;
+        //char dl_bitmap = 0;
+
+    #if defined(QEPO_BD) || defined(QEPO_GA)
+        if(data != NULL)
+        {
+            dl_bitmap = *data;
+            ret = mtk_agps_agent_qepo_get_rqst_time(&wn, &tow, &sys_time);
+            LOGD("wn, tow, sys_time = %d, %d, %d,bitmap:0x%x\n", wn, tow, sys_time, *data);
+            gps_mnl_set_gps_time(wn, tow, sys_time);
+            if (( dl_bitmap & (AGT_QEPO_GP_BIT|AGT_QEPO_GL_BIT)) != 0) {
+                qepo_downloader_start();
+            }
+
+            if ((dl_bitmap & AGT_QEPO_BD_BIT) == AGT_QEPO_BD_BIT) {
+                qepo_bd_downloader_start();
+            }
+
+            if ((dl_bitmap & AGT_QEPO_GA_BIT) == AGT_QEPO_GA_BIT) {
+                qepo_ga_downloader_start();
+            }
+
+        }else{
+            LOGE("QEPO dl request , pointer of data is null!!!\n");
+        }
+    #else
+        ret = mtk_agps_agent_qepo_get_rqst_time(&wn, &tow, &sys_time);
+        LOGD("wn, tow, sys_time = %d, %d, %d\n", wn, tow, sys_time);
+        gps_mnl_set_gps_time(wn, tow, sys_time);
+        qepo_downloader_start();
+    #endif
+    }else if (type == MTK_AGPS_CB_MTKNAV_DOWNLOAD_REQ) {
+        if(mtknav_downloader_start() == -1){
+            LOGW("mtknav downloader start fail");
+        }
+    }
+    return ret;
+}
+
+#if RAW_DATA_SUPPORT
+int get_val(char *pStr, char** ppKey, char** ppVal) {
+    int len = (int)strlen(pStr);
+    char *end = pStr + len;
+    char *key = NULL, *val = NULL;
+
+    LOGD("pStr = %s,len=%d!!\n", pStr, len);
+
+    if (!len) {
+        return -1;    // no data
+    } else if (pStr[0] == '#') {   /*ignore comment*/
+        *ppKey = *ppVal = NULL;
+        return 0;
+    } else if (pStr[len-1] != '\n') {
+        if (len >= GPS_CONF_FILE_SIZE-1) {
+            LOGD("buffer is not enough!!\n");
+            return -1;
+        } else {
+            pStr[len] = '\n';
+        }
+    }
+    key = pStr;
+
+    LOGD("key = %s!!\n", key);
+    while ((*pStr != '=') && (pStr < end)) pStr++;
+    if (pStr >= end) {
+        LOGD("'=' is not found!!\n");
+        return -1;    // format error
+    }
+
+    *pStr++ = '\0';
+    while (IS_SPACE(*pStr) && (pStr < end)) pStr++;    // skip space chars
+    val = pStr;
+    while (!IS_SPACE(*pStr) && (pStr < end)) pStr++;
+    *pStr = '\0';
+    *ppKey = key;
+    *ppVal = val;
+
+    LOGD("val = %s!!\n", val);
+    return 0;
+}
+
+static int gps_raw_data_enable(void) {
+    char result[GPS_CONF_FILE_SIZE] = {0};
+
+    FILE *fp = fopen(RAW_DATA_CONTROL_FILE_PATH, "r");
+    char *key, *val;
+    if (!fp) {
+        LOGD("open %s fail!\n", RAW_DATA_CONTROL_FILE_PATH);
+        return 1;
+    }
+
+    while (fgets(result, sizeof(result), fp)) {
+        if (get_val(result, &key, &val)) {
+            LOGD("Get data fails!!\n");
+            fclose(fp);
+            return 1;
+        }
+        if (!key || !val) {
+            continue;
+        }
+        if (!strcmp(key, "RAW_DEBUG_MODE")) {
+            int len = strlen(val);
+            gps_raw_debug_mode = str2int(val, val+len);  // *val-'0';
+            if ((gps_raw_debug_mode != 1) && (gps_raw_debug_mode != 0)) {
+                gps_raw_debug_mode = 0;
+            }
+            LOGD("gps_raw_debug_mode = %d\n", gps_raw_debug_mode);
+        }
+    }
+    fclose(fp);
+    return gps_raw_debug_mode;
+}
+
+void print_gps_measurement(gps_measurement in) {
+    LOGD("===== print_gps_measurement ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("prn=%d", in.prn);
+    LOGD("time_offset_ns=%f", in.time_offset_ns);
+    LOGD("state=0x%x", in.state);
+    LOGD("received_gps_tow_ns=%"PRId64, in.received_gps_tow_ns);
+    LOGD("received_gps_tow_uncertainty_ns=%"PRId64, in.received_gps_tow_uncertainty_ns);
+    LOGD("c_n0_dbhz=%f", in.c_n0_dbhz);
+    LOGD("pseudorange_rate_mps=%f", in.pseudorange_rate_mps);
+    LOGD("pseudorange_rate_uncertainty_mps=%f", in.pseudorange_rate_uncertainty_mps);
+    LOGD("accumulated_delta_range_state=0x%x", in.accumulated_delta_range_state);
+    LOGD("accumulated_delta_range_m=%f", in.accumulated_delta_range_m);
+    LOGD("accumulated_delta_range_uncertainty_m=%f", in.accumulated_delta_range_uncertainty_m);
+    LOGD("pseudorange_m=%f", in.pseudorange_m);
+    LOGD("pseudorange_uncertainty_m=%f", in.pseudorange_uncertainty_m);
+    LOGD("code_phase_chips=%f", in.code_phase_chips);
+    LOGD("code_phase_uncertainty_chips=%f", in.code_phase_uncertainty_chips);
+    LOGD("carrier_frequency_hz=%f", in.carrier_frequency_hz);
+    LOGD("carrier_cycles=%"PRId64, in.carrier_cycles);
+    LOGD("carrier_phase=%f", in.carrier_phase);
+    LOGD("carrier_phase_uncertainty=%f", in.carrier_phase_uncertainty);
+    LOGD("loss_of_lock=%d", in.loss_of_lock);
+    LOGD("bit_number=%d", in.bit_number);
+    LOGD("time_from_last_bit_ms=%d", in.time_from_last_bit_ms);
+    LOGD("doppler_shift_hz=%f", in.doppler_shift_hz);
+    LOGD("doppler_shift_uncertainty_hz=%f", in.doppler_shift_uncertainty_hz);
+    LOGD("multipath_indicator=%d", in.multipath_indicator);
+    LOGD("snr_db=%f", in.snr_db);
+    LOGD("elevation_deg=%f", in.elevation_deg);
+    LOGD("elevation_uncertainty_deg=%f", in.elevation_uncertainty_deg);
+    LOGD("azimuth_deg=%f", in.azimuth_deg);
+    LOGD("azimuth_uncertainty_deg=%f", in.azimuth_uncertainty_deg);
+    LOGD("used_in_fix=%d", in.used_in_fix);
+}
+
+void print_gps_clock(gps_clock in) {
+    LOGD("===== print_gps_clock ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("leap_second=%d", in.leap_second);
+    LOGD("type=%d", in.type);
+    LOGD("time_ns=%"PRId64, in.time_ns);
+    LOGD("time_uncertainty_ns=%f", in.time_uncertainty_ns);
+    LOGD("full_bias_ns=%"PRId64, in.full_bias_ns);
+    LOGD("bias_ns=%f", in.bias_ns);
+    LOGD("bias_uncertainty_ns=%f", in.bias_uncertainty_ns);
+    LOGD("drift_nsps=%f", in.drift_nsps);
+    LOGD("drift_uncertainty_nsps=%f", in.drift_uncertainty_nsps);
+}
+
+void print_gps_nav_msg(gps_nav_msg in) {
+    LOGD("===== print_gps_nav_msg ====");
+    LOGD("prn=%d", in.prn);
+    LOGD("type=%d", in.type);
+    LOGD("status=0x%x", in.status);
+    LOGD("message_id=%d", in.message_id);
+    LOGD("submessage_id=%d", in.submessage_id);
+    LOGD("data_length=%zu", in.data_length);
+}
+
+void print_gnss_measurement(gnss_measurement in) {
+    LOGD("===== print_gnss_measurement ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("svid=%d", in.svid);
+    LOGD("constellation=0x%x", in.constellation);
+    LOGD("time_offset_ns=%f", in.time_offset_ns);
+    LOGD("state=0x%x", in.state);
+    LOGD("received_gps_tow_ns=%"PRId64, in.received_sv_time_in_ns);
+    LOGD("received_gps_tow_uncertainty_ns=%"PRId64, in.received_sv_time_uncertainty_in_ns);
+    LOGD("c_n0_dbhz=%f", in.c_n0_dbhz);
+    LOGD("pseudorange_rate_mps=%f", in.pseudorange_rate_mps);
+    LOGD("pseudorange_rate_uncertainty_mps=%f", in.pseudorange_rate_uncertainty_mps);
+    LOGD("accumulated_delta_range_state=0x%x", in.accumulated_delta_range_state);
+    LOGD("accumulated_delta_range_m=%f", in.accumulated_delta_range_m);
+    LOGD("accumulated_delta_range_uncertainty_m=%f", in.accumulated_delta_range_uncertainty_m);;
+    LOGD("carrier_frequency_hz=%f", in.carrier_frequency_hz);
+    LOGD("carrier_cycles=%"PRId64, in.carrier_cycles);
+    LOGD("carrier_phase=%f", in.carrier_phase);
+    LOGD("carrier_phase_uncertainty=%f", in.carrier_phase_uncertainty);
+    LOGD("multipath_indicator=%d", in.multipath_indicator);
+    LOGD("snr_db=%f", in.snr_db);
+    LOGD("agc_level_db=%f", in.agc_level_db);
+}
+
+void print_gnss_clock(gnss_clock in) {
+    LOGD("===== print_gnss_clock ====");
+    LOGD("flags=0x%x", in.flags);
+    LOGD("leap_second=%d", in.leap_second);
+    LOGD("time_ns=%"PRId64, in.time_ns);
+    LOGD("time_uncertainty_ns=%f", in.time_uncertainty_ns);
+    LOGD("full_bias_ns=%"PRId64, in.full_bias_ns);
+    LOGD("bias_ns=%f", in.bias_ns);
+    LOGD("bias_uncertainty_ns=%f", in.bias_uncertainty_ns);
+    LOGD("drift_nsps=%f", in.drift_nsps);
+    LOGD("drift_uncertainty_nsps=%f", in.drift_uncertainty_nsps);
+    LOGD("hw_clock_discontinuity_count=%d", in.hw_clock_discontinuity_count);
+}
+
+void print_gnss_nav_msg(gnss_nav_msg in) {
+    LOGD("===== print_gnss_nav_msg ====");
+    LOGD("svid=%d", in.svid);
+    LOGD("type=%d", in.type);
+    LOGD("status=0x%x", in.status);
+    LOGD("message_id=%d", in.message_id);
+    LOGD("submessage_id=%d", in.submessage_id);
+    LOGD("data_length=%d", in.data_length);
+}
+
+#if 0
+static void get_gps_measurement_clock_data() {
+    LOGD("get_gps_measurement_clock_data begin");
+
+    int i;
+    int num = 0;
+    int ret;
+    gps_data gpsdata;
+    MTK_GPS_MEASUREMENT mtk_gps_measurement[GPS_MAX_MEASUREMENT];
+    INT8 ch_proc_ord_prn[GPS_MAX_MEASUREMENT]={0};
+    mtk_gps_get_measurement(mtk_gps_measurement, ch_proc_ord_prn);
+    LOGD("sizeof(mtk_gps_get_measurement) = %d,sizeof(mtk_gps_get_measurement[0]) = %d\n",
+        sizeof(mtk_gps_measurement), sizeof(mtk_gps_measurement[0]));
+
+    MTK_GPS_CLOCK mtk_gps_clock;
+    ret = mtk_gps_get_clock(&mtk_gps_clock);
+    if (ret == 0) {
+        LOGD("mtk_gps_get_clock fail,[ret=%d]\n", ret);
+    }
+
+    gps_clock gpsclock;
+    memset(&gpsclock, 0, sizeof(gps_clock));
+    // gpsclock.size = sizeof(gps_clock);
+    gpsclock.bias_ns = mtk_gps_clock.BiasInNs;
+    gpsclock.bias_uncertainty_ns = mtk_gps_clock.BiasUncertaintyInNs;
+    gpsclock.drift_nsps = mtk_gps_clock.DriftInNsPerSec;
+    gpsclock.flags = mtk_gps_clock.flag;
+    gpsclock.leap_second = mtk_gps_clock.leapsecond;
+    gpsclock.time_ns = mtk_gps_clock.TimeInNs;
+    gpsclock.time_uncertainty_ns = mtk_gps_clock.TimeUncertaintyInNs;
+    gpsclock.type = mtk_gps_clock.type;
+    gpsclock.full_bias_ns = mtk_gps_clock.FullBiasInNs;
+    gpsclock.drift_uncertainty_nsps = mtk_gps_clock.DriftUncertaintyInNsPerSec;
+    if (gps_raw_debug_mode) {
+        print_gps_clock(gpsclock);
+    }
+
+    memset(&gpsdata, 0, sizeof(gps_data));
+    // gpsdata.size = sizeof(gps_data);
+    for (i = 0; i < GPS_MAX_MEASUREMENT; i++) {
+        if (mtk_gps_measurement[i].PRN != 0) {
+            num = gpsdata.measurement_count;
+
+            // gpsdata.measurements[num].size = sizeof(gps_measurement);
+            gpsdata.measurements[num].accumulated_delta_range_m = mtk_gps_measurement[i].AcDRInMeters;
+            gpsdata.measurements[num].accumulated_delta_range_state = mtk_gps_measurement[i].AcDRState10;
+            gpsdata.measurements[num].accumulated_delta_range_uncertainty_m = \
+            mtk_gps_measurement[i].AcDRUnInMeters;
+            gpsdata.measurements[num].azimuth_deg = mtk_gps_measurement[i].AzInDeg;
+            gpsdata.measurements[num].azimuth_uncertainty_deg = mtk_gps_measurement[i].AzUnInDeg;
+            gpsdata.measurements[num].bit_number = mtk_gps_measurement[i].BitNumber;
+            gpsdata.measurements[num].carrier_cycles = mtk_gps_measurement[i].CarrierCycle;
+            gpsdata.measurements[num].carrier_phase = mtk_gps_measurement[i].CarrierPhase;
+            gpsdata.measurements[num].carrier_phase_uncertainty = mtk_gps_measurement[i].CarrierPhaseUn;
+            gpsdata.measurements[num].carrier_frequency_hz = mtk_gps_measurement[i].CFInhZ;
+            gpsdata.measurements[num].c_n0_dbhz = mtk_gps_measurement[i].Cn0InDbHz;
+            gpsdata.measurements[num].code_phase_chips = mtk_gps_measurement[i].CPInChips;
+            gpsdata.measurements[num].code_phase_uncertainty_chips = mtk_gps_measurement[i].CPUnInChips;
+            gpsdata.measurements[num].doppler_shift_hz = mtk_gps_measurement[i].DopperShiftInHz;
+            gpsdata.measurements[num].doppler_shift_uncertainty_hz = mtk_gps_measurement[i].DopperShiftUnInHz;
+            gpsdata.measurements[num].elevation_deg = mtk_gps_measurement[i].ElInDeg;
+            gpsdata.measurements[num].elevation_uncertainty_deg = mtk_gps_measurement[i].ElUnInDeg;
+            gpsdata.measurements[num].flags = mtk_gps_measurement[i].flag;
+            gpsdata.measurements[num].loss_of_lock = mtk_gps_measurement[i].LossOfLock;
+            gpsdata.measurements[num].multipath_indicator = mtk_gps_measurement[i].MultipathIndicater;
+            gpsdata.measurements[num].pseudorange_m = mtk_gps_measurement[i].PRInMeters;
+            gpsdata.measurements[num].prn = mtk_gps_measurement[i].PRN;
+            gpsdata.measurements[num].pseudorange_rate_mps = mtk_gps_measurement[i].PRRateInMeterPreSec;
+            gpsdata.measurements[num].pseudorange_rate_uncertainty_mps = \
+            mtk_gps_measurement[i].PRRateUnInMeterPreSec;
+            gpsdata.measurements[num].pseudorange_uncertainty_m = mtk_gps_measurement[i].PRUnInMeters;
+            gpsdata.measurements[num].received_gps_tow_ns = mtk_gps_measurement[i].ReGpsTowInNs;
+            gpsdata.measurements[num].received_gps_tow_uncertainty_ns = mtk_gps_measurement[i].ReGpsTowUnInNs;
+            gpsdata.measurements[num].snr_db = mtk_gps_measurement[i].SnrInDb;
+            gpsdata.measurements[num].state = mtk_gps_measurement[i].state;
+            gpsdata.measurements[num].time_from_last_bit_ms = mtk_gps_measurement[i].TimeFromLastBitInMs;
+            gpsdata.measurements[num].time_offset_ns = mtk_gps_measurement[i].TimeOffsetInNs;
+            gpsdata.measurements[num].used_in_fix = mtk_gps_measurement[i].UsedInFix;
+            if (gpsdata.measurements[num].state == 0) {
+                gpsdata.measurements[num].received_gps_tow_ns = 0;
+                gpsdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            LOGD("gpsdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gpsdata.measurements[num].prn);
+            if (gps_raw_debug_mode) {
+                print_gps_measurement(gpsdata.measurements[num]);
+            }
+            gpsdata.measurement_count++;
+        }
+    }
+    memcpy(&gpsdata.clock , &gpsclock, sizeof(gpsclock));
+    if (gpsdata.measurement_count > 0) {
+        ret = mnl2hal_gps_measurements(gpsdata);
+        LOGD("mnl2hal_gps_measurements done ,ret = %d", ret);
+    }
+}
+static void get_gps_navigation_event() {
+    LOGD("get_gps_navigation_event begin");
+
+    int svid;
+    int i;
+    int ret;
+    MTK_GPS_NAVIGATION_EVENT gps_navigation_event;
+    gps_nav_msg gpsnavigation;
+
+    for (svid = 0; svid < GPS_MAX_MEASUREMENT; svid++) {
+        ret = mtk_gps_get_navigation_event(&gps_navigation_event, svid);
+        if (ret == 0) {
+            LOGD("mtk_gps_get_navigation_event fail,SVID = %d,[ret=%d]\n", svid, ret);
+            memset(&gps_navigation_event, 0, sizeof(MTK_GPS_NAVIGATION_EVENT));
+        }
+
+        memset(&gpsnavigation, 0, sizeof(gps_nav_msg));
+        // gpsnavigation.size = sizeof(gps_nav_msg);
+        gpsnavigation.prn = gps_navigation_event.prn;
+        gpsnavigation.type = gps_navigation_event.type;
+        gpsnavigation.message_id = gps_navigation_event.messageID;
+        gpsnavigation.submessage_id = gps_navigation_event.submessageID;
+        gpsnavigation.data_length = sizeof(gps_navigation_event.data);
+        memcpy(gpsnavigation.data, gps_navigation_event.data, sizeof(gps_navigation_event.data));
+
+        if (gps_raw_debug_mode) {
+            print_gps_nav_msg(gpsnavigation);
+            for (i = 0; i < 40; i++) {
+                LOGD("gpsnavigation.data[%d] = %x, %p",
+                    i, gpsnavigation.data[i], &gpsnavigation.data[i]);
+            }
+        }
+        ret = mnl2hal_gps_navigation(gpsnavigation);
+        LOGD("mnl2hal_gps_navigation done ,ret = %d", ret);
+    }
+}
+#endif
+
+static void update_gnss_measurement(gnss_measurement* dst, Gnssmeasurement* src) {
+    LOGD("update_gnss_measurement begin");
+
+    fieldp_copy(dst, src, flags);
+    fieldp_copy(dst, src, svid);
+    fieldp_copy(dst, src, constellation);
+    fieldp_copy(dst, src, time_offset_ns);
+    fieldp_copy(dst, src, state);
+    fieldp_copy(dst, src, received_sv_time_in_ns);
+    fieldp_copy(dst, src, received_sv_time_uncertainty_in_ns);
+    fieldp_copy(dst, src, c_n0_dbhz);
+    fieldp_copy(dst, src, pseudorange_rate_mps);
+    fieldp_copy(dst, src, pseudorange_rate_uncertainty_mps);
+    fieldp_copy(dst, src, accumulated_delta_range_state);
+    fieldp_copy(dst, src, accumulated_delta_range_m);
+    fieldp_copy(dst, src, accumulated_delta_range_uncertainty_m);
+    fieldp_copy(dst, src, carrier_frequency_hz);
+    fieldp_copy(dst, src, carrier_cycles);
+    fieldp_copy(dst, src, carrier_phase);
+    fieldp_copy(dst, src, carrier_phase_uncertainty);
+    fieldp_copy(dst, src, multipath_indicator);
+    fieldp_copy(dst, src, snr_db);
+
+    ///TODO FIX IT
+    //    fieldp_copy(dst, src, agc_level_db);
+    dst->agc_level_db = g_agc_level;
+//    private static final int HAS_SNR = (1<<0);
+//    private static final int HAS_CARRIER_FREQUENCY = (1<<9);
+///    private static final int HAS_AUTOMATIC_GAIN_CONTROL = (1<<13);
+    dst->flags = (dst->flags | (1<<0)| (1<<9) |(1<<13));
+
+    //if (gps_raw_debug_mode) {
+        print_gnss_measurement((*dst));
+    //}
+}
+
+static void update_gnss_clock(gnss_clock* dst, Gnssclock* src) {
+    LOGD("update_gnss_clock begin");
+
+    fieldp_copy(dst, src, flags);
+    fieldp_copy(dst, src, leap_second);
+    fieldp_copy(dst, src, time_ns);
+    fieldp_copy(dst, src, time_uncertainty_ns);
+    fieldp_copy(dst, src, full_bias_ns);
+    fieldp_copy(dst, src, bias_ns);
+    fieldp_copy(dst, src, bias_uncertainty_ns);
+    fieldp_copy(dst, src, drift_nsps);
+    fieldp_copy(dst, src, drift_uncertainty_nsps);
+    fieldp_copy(dst, src, hw_clock_discontinuity_count);
+
+    if (gps_raw_debug_mode) {
+        print_gnss_clock((*dst));
+    }
+}
+
+static void update_gnss_navigation(gnss_nav_msg* dst, GnssNavigationmessage* src) {
+    LOGD("update_gnss_navigation begin");
+
+    fieldp_copy(dst, src, svid);
+    fieldp_copy(dst, src, type);
+    fieldp_copy(dst, src, status);
+    fieldp_copy(dst, src, message_id);
+    fieldp_copy(dst, src, submessage_id);
+    fieldp_copy(dst, src, data_length);
+
+    if (gps_raw_debug_mode) {
+        print_gnss_nav_msg((*dst));
+    }
+}
+#ifndef CONFIG_GPS_MT3303
+static void get_gnss_measurement_clock_data() {
+    LOGD("get_gnss_measurement_clock_data begin");
+
+    int i;
+    int num = 0;
+    int ret;
+    gnss_data gnssdata;
+    Gnssmeasurement gpqzmeasurement[40];
+    Gnssmeasurement glomeasurement[24];
+    Gnssmeasurement bdmeasurement[37];
+    Gnssmeasurement galmeasurement[36];
+    Gnssmeasurement sbasmeasurement[42];
+
+    INT8 GpQz_Ch_Proc_Ord_PRN[40] = {0};
+    INT8 Glo_Ch_Proc_Ord_PRN[24] = {0};
+    INT8 BD_Ch_Proc_Ord_PRN[37] = {0};
+    INT8 Gal_Ch_Proc_Ord_PRN[36] = {0};
+    INT8 SBAS_Ch_Proc_Ord_PRN[42] = {0};
+
+    mtk_gnss_get_measurement(gpqzmeasurement, glomeasurement, bdmeasurement, galmeasurement, sbasmeasurement,
+        GpQz_Ch_Proc_Ord_PRN, Glo_Ch_Proc_Ord_PRN, BD_Ch_Proc_Ord_PRN, Gal_Ch_Proc_Ord_PRN, SBAS_Ch_Proc_Ord_PRN);
+
+    Gnssclock gnssclock;
+    if (mtk_gnss_get_clock(&gnssclock) == 0) {
+        LOGD("mtk_gnss_get_clock fail\n");
+        memset(&gnssclock, 0, sizeof(Gnssclock));
+    }
+    gnss_clock gnss_clock;
+    memset(&gnss_clock, 0, sizeof(gnss_clock));
+    update_gnss_clock(&gnss_clock, &gnssclock);
+
+
+    memset(&gnssdata, 0, sizeof(gnssdata));
+    // For GPS & QZSS
+    for (i = 0; i < 40; i++) {
+        if (gpqzmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &gpqzmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("GP gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Glonass
+    for (i = 0; i < 24; i++) {
+        if (glomeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &glomeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("GL gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Beidou
+    for (i = 0; i < 37; i++) {
+        if (bdmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &bdmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("BD gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Galileo
+    for (i = 0; i < 36; i++) {
+        if (galmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &galmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("GA gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For SBAS
+    for (i = 0; i < 42; i++) {
+        if (sbasmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= MTK_MNLD_GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &sbasmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("SBAS gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    memcpy(&gnssdata.clock , &gnss_clock, sizeof(gnss_clock));
+    LOGD("gnssdata.measurement_count = %d, sizeof(gnssdata) = %d", gnssdata.measurement_count, sizeof(gnssdata));
+    if (gnssdata.measurement_count > 0) {
+        ret = mnl2hal_gnss_measurements(gnssdata);
+        LOGD("mnl2hal_gnss_measurements done ,ret = %d", ret);
+    }
+}
+
+static void get_gnss_navigation_event() {
+    LOGD("get_gnss_navigation_event begin");
+
+    int svid;
+    int i;
+    int ret;
+    GnssNavigationmessage gnss_navigation_msg;
+    gnss_nav_msg gnssnavigation;
+
+    // GPS
+    for (svid = 1; svid <= GPS_MAX_MEASUREMENT; svid++) {
+        ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 1);
+        if (ret == 0) {
+            LOGD("mtk_gnss_get_navigation_event GPS sv fail, svid = %d,[ret=%d]\n", svid, ret);
+            memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+        }
+
+        memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+        update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GP_data, gnssnavigation.data_length);
+        if (gps_raw_debug_mode) {
+            for (i = 0; i < 40; i++) {
+                LOGD("GPS sv gnssnavigation.data[%d] = %x, %p",
+                i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+            }
+        }
+        ret = mnl2hal_gnss_navigation(gnssnavigation);
+        LOGD("GPS sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+    }
+
+    // glonass
+    for (svid = 1; svid <= 24; svid++) {
+        ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 16);
+        if (ret == 0) {
+            LOGD("mtk_gnss_get_navigation_event Glonass sv fail, svid = %d,[ret=%d]\n", svid, ret);
+            memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+        }
+
+        memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+        update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GL_data, gnssnavigation.data_length);
+        if (gps_raw_debug_mode) {
+            for (i = 0; i < 12; i++) {
+                LOGD("Glonass sv gnssnavigation.data[%d] = %x, %p",
+                i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+            }
+        }
+        ret = mnl2hal_gnss_navigation(gnssnavigation);
+        LOGD("Glonass sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+    }
+
+    // beidou
+    for (svid = 1; svid <= 37; svid++) {
+        ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 32);
+        if (ret == 0) {
+            LOGD("mtk_gnss_get_navigation_event BD sv fail, svid = %d,[ret=%d]\n", svid, ret);
+            memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+        }
+
+        memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+        update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.BD_data, gnssnavigation.data_length);
+        if (gps_raw_debug_mode) {
+            for (i = 0; i < 40; i++) {
+                LOGD("BD sv gnssnavigation.data[%d] = %x, %p",
+                i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+            }
+        }
+        ret = mnl2hal_gnss_navigation(gnssnavigation);
+        LOGD("BD sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+    }
+
+    // galileo
+    for (svid = 1; svid <= 36; svid++) {
+        ret = mtk_gnss_get_navigation_event(&gnss_navigation_msg, svid, 4);
+        if (ret == 0) {
+            LOGD("mtk_gnss_get_navigation_event Galileo sv fail, svid = %d,[ret=%d]\n", svid, ret);
+            memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+        }
+
+        memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+        update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+        memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GA_data, gnssnavigation.data_length);
+        if (gps_raw_debug_mode) {
+            for (i = 0; i < 40; i++) {
+                LOGD("Galileo sv gnssnavigation.data[%d] = %x, %p",
+                i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+            }
+        }
+        ret = mnl2hal_gnss_navigation(gnssnavigation);
+        LOGD("Galileo sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+    }
+}
+#else
+gnss_sv_info cts_sv_data;
+
+ void get_gnss_measurement_clock_data() {
+    LOGD("get_gnss_measurement_clock_data begin");
+
+    int i;
+    int num = 0;
+    int ret;
+    gnss_data gnssdata;
+    Gnssmeasurement gpqzmeasurement[40];
+    Gnssmeasurement glomeasurement[24];
+    Gnssmeasurement bdmeasurement[37];
+    Gnssmeasurement galmeasurement[36];
+    Gnssmeasurement sbasmeasurement[42];
+
+#if 0
+    INT8 GpQz_Ch_Proc_Ord_PRN[40] = {0};
+    INT8 Glo_Ch_Proc_Ord_PRN[24] = {0};
+    INT8 BD_Ch_Proc_Ord_PRN[37] = {0};
+    INT8 Gal_Ch_Proc_Ord_PRN[36] = {0};
+    INT8 SBAS_Ch_Proc_Ord_PRN[42] = {0};
+#endif
+    
+    
+
+    for (i = 0; i < 40; i++) {
+        gpqzmeasurement[i].accumulated_delta_range_m=0;
+        gpqzmeasurement[i].accumulated_delta_range_state=0x0;
+        gpqzmeasurement[i].accumulated_delta_range_uncertainty_m=0;
+        gpqzmeasurement[i].carrier_cycles=0;
+        gpqzmeasurement[i].carrier_frequency_hz=1575420032.000000;
+        gpqzmeasurement[i].carrier_phase=0;
+        gpqzmeasurement[i].carrier_phase_uncertainty=0;
+
+        gpqzmeasurement[i].svid=0;
+        gpqzmeasurement[i].snr_db=0;
+        gpqzmeasurement[i].constellation=0;
+        gpqzmeasurement[i].c_n0_dbhz=0 ;
+        for(int cnt=cts_sv_data.num_svs; cnt>0; cnt--){
+            if(cts_sv_data.sv_list[cnt-1].svid == (i+1)){
+                if(cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17 < 0){
+                    gpqzmeasurement[i].snr_db=0;
+                }else{
+                    gpqzmeasurement[i].snr_db=cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17;
+                }
+                
+                gpqzmeasurement[i].constellation=cts_sv_data.sv_list[cnt-1].constellation;
+                gpqzmeasurement[i].c_n0_dbhz=cts_sv_data.sv_list[cnt-1].c_n0_dbhz ;
+                if(gpqzmeasurement[i].c_n0_dbhz <= 5.0){
+                    gpqzmeasurement[i].svid=0;
+                }else{
+                    gpqzmeasurement[i].svid=cts_sv_data.sv_list[cnt-1].svid;
+                }
+                break;
+            }
+            
+        }
+        
+        gpqzmeasurement[i].flags=0x40201;
+        gpqzmeasurement[i].multipath_indicator=0;
+        gpqzmeasurement[i].pseudorange_rate_mps=14522.145508;
+        gpqzmeasurement[i].pseudorange_rate_uncertainty_mps=0.150000;
+        gpqzmeasurement[i].received_sv_time_in_ns=20000;
+        gpqzmeasurement[i].received_sv_time_uncertainty_in_ns=33353074;
+        gpqzmeasurement[i].size=sizeof(gpqzmeasurement[i]);
+        gpqzmeasurement[i].state=0x02;
+        gpqzmeasurement[i].time_offset_ns=421235.186561;
+    }
+
+    for (i = 0; i < 24; i++) {
+        glomeasurement[i].accumulated_delta_range_m=0;
+        glomeasurement[i].accumulated_delta_range_state=0x0;
+        glomeasurement[i].accumulated_delta_range_uncertainty_m=0;
+        glomeasurement[i].carrier_cycles=0;
+        glomeasurement[i].carrier_frequency_hz=1575420032.000000;
+        glomeasurement[i].carrier_phase=0;
+        glomeasurement[i].carrier_phase_uncertainty=0;
+
+        glomeasurement[i].svid=0;
+        glomeasurement[i].snr_db=0;
+        glomeasurement[i].constellation=0;
+        glomeasurement[i].c_n0_dbhz=0 ;
+        for(int cnt=cts_sv_data.num_svs; cnt>0; cnt--){
+            if(cts_sv_data.sv_list[cnt-1].svid == (i+65)){
+                if(cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17 < 0){
+                    glomeasurement[i].snr_db=0;
+                }else{
+                    glomeasurement[i].snr_db=cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17;
+                }
+                
+                glomeasurement[i].constellation=cts_sv_data.sv_list[cnt-1].constellation;
+                glomeasurement[i].c_n0_dbhz=cts_sv_data.sv_list[cnt-1].c_n0_dbhz ;
+                if(glomeasurement[i].c_n0_dbhz <= 5.0){
+                    glomeasurement[i].svid=0;
+                }else{
+                    glomeasurement[i].svid=cts_sv_data.sv_list[cnt-1].svid - 65 + 1;
+                }
+                break;
+            }
+            
+        }
+        
+        glomeasurement[i].flags=0x40201;
+        glomeasurement[i].multipath_indicator=0;
+        glomeasurement[i].pseudorange_rate_mps=14522.145508;
+        glomeasurement[i].pseudorange_rate_uncertainty_mps=0.150000;
+        glomeasurement[i].received_sv_time_in_ns=20000;
+        glomeasurement[i].received_sv_time_uncertainty_in_ns=33353074;
+        glomeasurement[i].size=sizeof(glomeasurement[i]);
+        glomeasurement[i].state=0x02;
+        glomeasurement[i].time_offset_ns=421235.186561;
+    }
+    for (i = 0; i < 37; i++) {
+        bdmeasurement[i].accumulated_delta_range_m=0;
+        bdmeasurement[i].accumulated_delta_range_state=0x0;
+        bdmeasurement[i].accumulated_delta_range_uncertainty_m=0;
+        bdmeasurement[i].carrier_cycles=0;
+        bdmeasurement[i].carrier_frequency_hz=1575420032.000000;
+        bdmeasurement[i].carrier_phase=0;
+        bdmeasurement[i].carrier_phase_uncertainty=0;
+
+        bdmeasurement[i].svid=0;
+        bdmeasurement[i].snr_db=0;
+        bdmeasurement[i].constellation=0;
+        bdmeasurement[i].c_n0_dbhz=0 ;
+        for(int cnt=cts_sv_data.num_svs; cnt>0; cnt--){
+            if(cts_sv_data.sv_list[cnt-1].svid == (i+201)){
+                if(cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17 < 0){
+                    bdmeasurement[i].snr_db=0;
+                }else{
+                    bdmeasurement[i].snr_db=cts_sv_data.sv_list[cnt-1].c_n0_dbhz - 17;
+                }
+                
+                bdmeasurement[i].constellation=cts_sv_data.sv_list[cnt-1].constellation;
+                bdmeasurement[i].c_n0_dbhz=cts_sv_data.sv_list[cnt-1].c_n0_dbhz ;
+                if(bdmeasurement[i].c_n0_dbhz <= 5.0){
+                    bdmeasurement[i].svid=0;
+                }else{
+                    bdmeasurement[i].svid=cts_sv_data.sv_list[cnt-1].svid - 201 + 1;
+                }
+                break;
+            }
+            
+        }
+        
+        bdmeasurement[i].flags=0x40201;
+        bdmeasurement[i].multipath_indicator=0;
+        bdmeasurement[i].pseudorange_rate_mps=14522.145508;
+        bdmeasurement[i].pseudorange_rate_uncertainty_mps=0.150000;
+        bdmeasurement[i].received_sv_time_in_ns=20000;
+        bdmeasurement[i].received_sv_time_uncertainty_in_ns=33353074;
+        bdmeasurement[i].size=sizeof(bdmeasurement[i]);
+        bdmeasurement[i].state=0x02;
+        bdmeasurement[i].time_offset_ns=421235.186561;
+    }
+    for (i = 0; i < 36; i++) {
+        memset(galmeasurement,0,sizeof(galmeasurement));
+    }
+    for (i = 0; i < 42; i++) {
+        memset(sbasmeasurement,0,sizeof(sbasmeasurement));
+    }
+
+    Gnssclock gnssclock;
+    memset(&gnssclock,0,sizeof(gnssclock));
+    gnssclock.bias_ns=0.186561;
+    gnssclock.bias_uncertainty_ns=609.745098;
+    gnssclock.drift_nsps=7183.074831;
+    gnssclock.drift_uncertainty_nsps=16.441889;
+    gnssclock.flags=0x01;
+    gnssclock.full_bias_ns=421235;
+    gnssclock.hw_clock_discontinuity_count=0;
+    gnssclock.leap_second=18;
+    gnssclock.size=sizeof(gnssclock);
+    gnssclock.time_ns=1185356046700000000;
+    gnssclock.time_uncertainty_ns=33353073.878863;
+    
+    gnss_clock gnss_clock;
+    memset(&gnss_clock, 0, sizeof(gnss_clock));
+    update_gnss_clock(&gnss_clock, &gnssclock);
+
+
+    memset(&gnssdata, 0, sizeof(gnssdata));
+    // For GPS & QZSS
+    for (i = 0; i < 40; i++) {
+        if (gpqzmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &gpqzmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Glonass
+    for (i = 0; i < 24; i++) {
+        if (glomeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &glomeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Beidou
+    for (i = 0; i < 37; i++) {
+        if (bdmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &bdmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For Galileo
+    for (i = 0; i < 36; i++) {
+        if (galmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &galmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    // For SBAS
+    for (i = 0; i < 42; i++) {
+        if (sbasmeasurement[i].svid != 0) {
+            num = gnssdata.measurement_count;
+            if (num >= GNSS_MAX_MEASUREMENT) {
+                LOGD("measurement_count exceed the upper limit!");
+                break;
+            }
+
+            update_gnss_measurement(&gnssdata.measurements[num], &sbasmeasurement[i]);
+            if (gnssdata.measurements[num].state == 0) {
+                gnssdata.measurements[num].pseudorange_rate_mps = 1;
+            }
+            gnssdata.measurement_count++;
+            LOGD("gnssdata measurements[%d] memcpy completed, old _num = %d, prn = %d\n",
+                num, i, gnssdata.measurements[num].svid);
+        }
+    }
+
+    memcpy(&gnssdata.clock , &gnss_clock, sizeof(gnss_clock));
+    LOGD("gnssdata.measurement_count = %d, sizeof(gnssdata) = %d", gnssdata.measurement_count, sizeof(gnssdata));
+    if (gnssdata.measurement_count > 0) {
+        ret = mnl2hal_gnss_measurements(gnssdata);
+        LOGD("mnl2hal_gnss_measurements done ,ret = %d", ret);
+    }
+
+    memset(&cts_sv_data,0,sizeof(cts_sv_data));
+}
+
+#ifdef __ANDROID_OS_10__ 
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GNSS_L1CA GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA
+#endif
+  void get_gnss_navigation_event() {
+     LOGD("get_gnss_navigation_event begin");
+ 
+     int svid;
+     int i;
+     int ret;
+     GnssNavigationmessage gnss_navigation_msg;
+     gnss_nav_msg gnssnavigation;
+ 
+     // GPS
+     for (svid = 1; svid <= GPS_MAX_MEASUREMENT; svid++) {
+         ret = 0;
+         gnss_navigation_msg.data_length=40;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA;
+         if (ret == 0) {
+             LOGD("mtk_gnss_get_navigation_event GPS sv fail, svid = %d,[ret=%d]\n", svid, ret);
+             memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+         }
+ 
+         memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+         update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GP_data, gnssnavigation.data_length);
+         if (gps_raw_debug_mode) {
+             for (i = 0; i < 40; i++) {
+                 LOGD("GPS sv gnssnavigation.data[%d] = %x, %p",
+                 i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+             }
+         }
+         ret = mnl2hal_gnss_navigation(gnssnavigation);
+         LOGD("GPS sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+     }
+ 
+     // glonass
+     for (svid = 1; svid <= 24; svid++) {
+         ret = 0;
+         gnss_navigation_msg.data_length=12;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA;
+         if (ret == 0) {
+             LOGD("mtk_gnss_get_navigation_event Glonass sv fail, svid = %d,[ret=%d]\n", svid, ret);
+             memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+         }
+ 
+         memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+         update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GL_data, gnssnavigation.data_length);
+         if (gps_raw_debug_mode) {
+             for (i = 0; i < 12; i++) {
+                 LOGD("Glonass sv gnssnavigation.data[%d] = %x, %p",
+                 i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+             }
+         }
+         ret = mnl2hal_gnss_navigation(gnssnavigation);
+         LOGD("Glonass sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+     }
+ 
+     // beidou
+     for (svid = 1; svid <= 37; svid++) {
+         ret = 0;
+         gnss_navigation_msg.data_length=40;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1;
+         if (ret == 0) {
+             LOGD("mtk_gnss_get_navigation_event BD sv fail, svid = %d,[ret=%d]\n", svid, ret);
+             memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+         }
+ 
+         memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+         update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.BD_data, gnssnavigation.data_length);
+         if (gps_raw_debug_mode) {
+             for (i = 0; i < 40; i++) {
+                 LOGD("BD sv gnssnavigation.data[%d] = %x, %p",
+                 i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+             }
+         }
+         ret = mnl2hal_gnss_navigation(gnssnavigation);
+         LOGD("BD sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+     }
+ 
+     // galileo
+     for (svid = 1; svid <= 36; svid++) {
+         ret = 0;
+         gnss_navigation_msg.data_length=40;
+         gnss_navigation_msg.message_id=1;
+         gnss_navigation_msg.submessage_id=1;
+         gnss_navigation_msg.size=sizeof(gnss_navigation_msg);
+         gnss_navigation_msg.status=0x0;
+         gnss_navigation_msg.svid=svid;
+         gnss_navigation_msg.type=GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I;
+         if (ret == 0) {
+             LOGD("mtk_gnss_get_navigation_event Galileo sv fail, svid = %d,[ret=%d]\n", svid, ret);
+             memset(&gnss_navigation_msg, 0, sizeof(GnssNavigationmessage));
+         }
+ 
+         memset(&gnssnavigation, 0, sizeof(gnss_nav_msg));
+         update_gnss_navigation(&gnssnavigation, &gnss_navigation_msg);
+         memcpy(gnssnavigation.data, gnss_navigation_msg.uData.GA_data, gnssnavigation.data_length);
+         if (gps_raw_debug_mode) {
+             for (i = 0; i < 40; i++) {
+                 LOGD("Galileo sv gnssnavigation.data[%d] = %x, %p",
+                 i, gnssnavigation.data[i], &gnssnavigation.data[i]);
+             }
+         }
+         ret = mnl2hal_gnss_navigation(gnssnavigation);
+         LOGD("Galileo sv, mnl2hal_gnss_navigation done ,ret = %d", ret);
+     }
+ }
+
+#endif
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+/*---------------------------------------------------------------------------*/
+#define  MNL_CONFIG_STATUS      "persist.vendor.radio.mnl.prop"
+static int get_prop(int index) {
+    // Read property
+    char result[PROPERTY_VALUE_MAX] = {0};
+    int ret = 0;
+    if (property_get(MNL_CONFIG_STATUS, result, NULL)) {
+        ret = result[index] - '0';
+        LOGD("gps.log: %s, %d\n", &result[index], ret);
+    } else {
+        if (index == 7) {
+            ret = 1;
+        } else {
+            ret = 0;
+        }
+        LOGD("Config is not set yet, use default value");
+    }
+    return ret;
+}
+
+int get_gps_cmcc_log_enabled() {
+    int is_enabled = get_prop(6);
+    return is_enabled;
+}
+#endif
+static int gps_control_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main2gps_event cmd;
+    int read_len;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("gps_control_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    cmd = get_int(buff, &offset, sizeof(buff));
+    switch (cmd) {
+    case MAIN2GPS_EVENT_START: {
+        int delete_aiding_data_flags = get_int(buff, &offset, sizeof(buff));
+        LOGI("mnld version: %s", MNLD_VERSION);
+        // need to call mnld_gps_start_done() when GPS is started
+        mnld_gps_start(delete_aiding_data_flags);
+        break;
+    }
+    case MAIN2GPS_EVENT_STOP: {
+        // need to call mnld_gps_stop_done() when GPS is stopped
+        mnld_gps_stop();
+        break;
+    }
+    case MAIN2GPS_DELETE_AIDING_DATA: {
+        int delete_aiding_data_flags = get_int(buff, &offset, sizeof(buff));
+        LOGW("mnld_gps_delete_aiding_data() before delete_aiding_data_flags=0x%x",
+            delete_aiding_data_flags);
+        // need to call mnld_gps_reset_done() when GPS is reset
+        mnld_gps_delete_aiding_data(delete_aiding_data_flags);
+        LOGW("mnld_gps_delete_aiding_data() after");
+        break;
+    }
+    case GPS2GPS_NMEA_DATA_TIMEOUT: {
+        // not to start nmea timer if only LINK user
+        // although send_ative_noitfy already add the protection, it's also needed here
+        // to handle race condition:
+        //   1. send_ative_noitfy send a GPS2GPS_NMEA_DATA_TIMEOUT msg
+        //   2. MAIN thread change user to FLP only, and mnld_fsm stop nmea timer
+        //   3. GPS2GPS_NMEA_DATA_TIMEOUT reach here, and restart the timer
+        // then, GPS2MAIN_EVENT_NMEA_TIMEOUT may be caused
+        int gps_user = mtk_gps_get_gps_user();
+        if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) &&
+            mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            break;
+        }
+
+        mnld_gps_controller_mnl_nmea_timeout();
+        break;
+    }
+    default: {
+        LOGE("gps_control_event_hdlr() unknown cmd=%d", cmd);
+        return -1;
+    }
+    }
+    return 0;
+}
+
+static void gps_control_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("gps_control_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("gps_control_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void* gps_control_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    timer_t hdlr_timer = init_timer(gps_control_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("gps_control_thread() epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_gps) == -1) {
+        LOGE("gps_control_thread() epoll_add_fd() failed for g_fd_gps failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("gps_control_thread wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("gps_control_thread() epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        start_timer(hdlr_timer, MNLD_GPS_HANDLER_TIMEOUT);
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_gps) {
+                if (events[i].events & EPOLLIN) {
+                    gps_control_event_hdlr(g_fd_gps);
+                }
+            } else {
+                LOGE("gps_control_thread() unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        stop_timer(hdlr_timer);
+    }
+
+    LOGE("gps_control_thread() exit");
+    return 0;
+}
+
+int gps_control_gps_start(int delete_aiding_data_flags) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    #ifdef MTK_ADR_SUPPORT
+    mnl2adr_gps_open();
+    #endif
+    put_int(buff, &offset, MAIN2GPS_EVENT_START);
+    put_int(buff, &offset, delete_aiding_data_flags);
+    return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_stop() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    #ifdef MTK_ADR_SUPPORT
+    mnl2adr_gps_close();
+    #endif
+    put_int(buff, &offset, MAIN2GPS_EVENT_STOP);
+    return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_gps_reset(int delete_aiding_data_flags) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, MAIN2GPS_DELETE_AIDING_DATA);
+    put_int(buff, &offset, delete_aiding_data_flags);
+    return safe_sendto(MNLD_GPS_CONTROL_SOCKET, buff, offset);
+}
+
+int gps_control_init() {
+    pthread_t pthread_gps;
+
+    hasAlmanac();
+    g_fd_gps = socket_bind_udp(MNLD_GPS_CONTROL_SOCKET);
+    if (g_fd_gps < 0) {
+        LOGE("socket_bind_udp(MNLD_GPS_CONTROL_SOCKET) failed");
+        return -1;
+    }
+
+    pthread_create(&pthread_gps, NULL, gps_control_thread, NULL);
+
+    return 0;
+}
+
+// for kernel wakelock control when offload is enabled
+#if 1
+static int gps_kernel_wakelock_fd = C_INVALID_FD;
+static int gps_kernel_wakelock_to_take = 1;
+
+void gps_control_kernel_wakelock_init() {
+    if (gps_kernel_wakelock_fd != dsp_fd && dsp_fd >= 0) {
+        gps_kernel_wakelock_fd = dsp_fd;
+        LOGD("dsp_fd is opened, fellow wakelock to take = %d, dsp_fd = %d",
+            gps_kernel_wakelock_to_take, gps_kernel_wakelock_fd);
+        if (!gps_kernel_wakelock_to_take) {
+            gps_control_kernel_wakelock_give();
+        } else {
+            LOGD("dsp_fd is opened, wakelock is taken defaultly, no need to take again");
+        }
+    }
+}
+
+void gps_control_kernel_wakelock_uninit() {
+    gps_kernel_wakelock_fd = C_INVALID_FD;
+}
+
+void gps_control_kernel_wakelock_take() {
+    int ret, fd;
+    fd = gps_kernel_wakelock_fd;
+    gps_kernel_wakelock_to_take = 1;
+    if (fd >= 0) {
+        ret = ioctl(fd, COMBO_IOC_TAKE_GPS_WAKELOCK, NULL);
+        LOGD("take kernel wakelock, fd = %d, ret = %d", fd, ret);
+    } else {
+        LOGD("dsp_fd not opened, record wakelock to take = %d", gps_kernel_wakelock_to_take);
+    }
+}
+
+void gps_control_kernel_wakelock_give() {
+    int ret, fd;
+    fd = gps_kernel_wakelock_fd;
+    gps_kernel_wakelock_to_take = 0;
+    if (fd >= 0) {
+        ret = ioctl(fd, COMBO_IOC_GIVE_GPS_WAKELOCK, NULL);
+        LOGD("give kernel wakelock, fd = %d, ret = %d", fd, ret);
+    } else {
+        LOGD("dsp_fd not opened, record wakelock to take = %d", gps_kernel_wakelock_to_take);
+    }
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// META mode
+/*****************************************************************************/
+void linux_signal_handler(int signo) {
+    int ret = 0;
+    pthread_t self = pthread_self();
+    if (signo == SIGTERM) {
+        int gps_user = GPS_USER_UNKNOWN;
+        gps_user = mtk_gps_get_gps_user();
+        if ((gps_user & GPS_USER_APP) != 0) {
+            LOGD("Normal mode,sdcard storage send SIGTERM to mnld");
+            gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+            if (mnld_is_gps_started_done()) {
+                ret = mtk_gps_set_debug_type(gps_debuglog_state);
+                if (MTK_GPS_ERROR== ret) {
+                    LOGD("sdcard storage send SIGTERM to mnld, stop gpsdebuglog, mtk_gps_set_debug_type fail");
+                }
+            }
+        } else {
+            LOGD("Meta or factory or adb shell mode done");
+            if (gps_user & GPS_USER_META) {
+                mnld_gps_stop();
+            } else if (gps_user & GPS_USER_OFL_TEST) {
+                // flp_test2mnl_gps_start();
+                mnld_gps_start(FLAG_HOT_START);
+            }
+#ifdef CONFIG_GPS_MT3303
+            else{
+                mnld_gps_stop();
+            }
+#endif
+            exit_meta_factory = 1;
+        }
+    }
+    LOGD("Signal handler of %.8x -> %s\n", (unsigned int)self, sys_siglist[signo]);
+}
+
+int linux_setup_signal_handler(void) {
+    struct sigaction actions;
+    int err;
+    /*the signal handler is MUST, otherwise, the thread will not be killed*/
+    memset(&actions, 0, sizeof(actions));
+    sigemptyset(&actions.sa_mask);
+    actions.sa_flags = 0;
+    actions.sa_handler = linux_signal_handler;
+    if ((err = sigaction(SIGTERM, &actions, NULL))) {
+        LOGD("register signal hanlder for SIGTERM: %s\n", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+int mnld_factory_test_entry(int argc, char** argv) {
+    int res = 0;
+
+    LOGD("Meta or factory or adb shell mode");
+
+    in_meta_factory = 1;
+    res = unlink(NV_FILE);
+    LOGD("unlink NV_FILE, errno=%d, res=%d\n", errno, res);
+    MNLD_STRNCPY(gps_debuglog_file_name, LOG_FILE, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    if (argc >= 4) {
+        if (!strncmp(argv[3], "od", 2)) {
+            LOGD("MNL is non-offload");
+            mnld_cfg.OFFLOAD_enabled = 0;
+            // factory_mnld_gps_start();
+            mnld_gps_start(FLAG_HOT_START);
+        } else if (!strncmp(argv[3], "ot", 2)) {
+            LOGD("MNL is offload, run on test mode");
+            // flp_test2mnl_gps_start();
+            mnld_gps_start(FLAG_HOT_START);
+        } else if (!strncmp(argv[2], "PDNTest", 7)) {
+            PDN_test_enable = atoi(argv[3]);
+            LOGD("PDN test start, option is %d\n",PDN_test_enable);
+            mnld_gps_start(FLAG_HOT_START);
+        } else {
+            LOGD("MNL is offload, for meta/factory mode");
+            // factory_mnld_gps_start();
+#ifdef CONFIG_GPS_MT3303
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA);
+#endif
+            mnld_gps_start(FLAG_HOT_START);
+        }
+    } else {
+        LOGD("MNL is offload, for meta/factory mode");
+        // factory_mnld_gps_start();
+#ifdef CONFIG_GPS_MT3303
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA);
+#endif
+
+        mnld_gps_start(FLAG_HOT_START);
+    }
+    while (1) {
+        usleep(100000);
+        if (exit_meta_factory == 1) {
+            LOGD("Meta or factory mode exit");
+            exit_meta_factory = 0;
+            in_meta_factory = 0;
+            exit(1);
+        }
+        LOGD("Meta or factory mode testing...");
+    }
+    in_meta_factory = 0;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_dbg_log.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_dbg_log.c
new file mode 100644
index 0000000..d2a8dd5
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/gps_dbg_log.c
@@ -0,0 +1,1180 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/epoll.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "mnld_utile.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mnld.h"
+#include "mtk_gps.h"
+#include "mtk_gps_type.h"
+#include "gps_dbg_log.h"
+#include "mpe.h"
+#include "mtk_auto_log.h"
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "gps_dbg_log"
+#endif
+
+/*Close the GPS debug log file, and rename to ".nma".
+  *fd: file descriptor, should be a global variable for NULL check;
+  *fn: Current writing file name;
+  */
+#if defined(__ANDROID_OS__)
+#define GPSLOG_FCLOSE(fd,fn) do {\
+    if (NULL != fd) {\
+        fclose(fd);\
+        fd = NULL;\
+        gps_log_file_rename(fn);\
+        property_set(GPS_LOG_PERSIST_FLNM, GPS_LOG_PERSIST_VALUE_NONE);\
+    }\
+} while (0)
+#elif defined(__LINUX_OS__)
+#define FILE_FCLOSE(fd) do {\
+    if (NULL != fd) {\
+        fclose(fd);\
+        fd = NULL;}\
+    } while (0)
+
+#endif
+
+#define GPSLog_TIMESTRING_LEN 25
+#define C_INVALID_TID  (-1)   /*invalid thread id*/
+
+unsigned char gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+char gps_debuglog_file_name[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "/mnt/sdcard/mtklog/gpsdbglog/gpsdebug.log";
+char storagePath_mtklogger_set[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "/mnt/sdcard/mtklog/gpsdbglog/";
+char storagePath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "/mnt/sdcard/mtklog/gpsdbglog/";
+static char log_filename_suffix[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = "gpsdebug.log";
+static char gsGpsLogFileName[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static char gsGpsLogFileName_full[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+static int total_file_count = 0;
+static size_t Current_FileSize = 0;
+static int Filenum = 0;
+static size_t DirLogSize = 0;
+UINT32 g_dbglog_file_size_in_config = 0;   //Max dbg log file size read from config file
+UINT32 g_dbglog_folder_size_in_config = 0;   //Max dbg log folder size read from config file
+static int fg_create_dir_done = 0;
+pthread_mutex_t g_mnldMutex[MNLD_MUTEX_MAX];
+
+FILE* g_hLogFile = NULL;
+bool g_gpsdbglogThreadExit = true;
+bool g_pingpang_init = false;
+pthread_mutex_t FILE_WRITE_MUTEX;
+pthread_t pthread_dbg_log = C_INVALID_TID;
+
+#define PINGPANG_WRITE_LOCK 0
+#define PINGPANG_FLUSH_LOCK 1
+
+static SYNC_LOCK_T lock_for_sync[] = {{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0},
+                                      {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 1}};
+
+//  data
+#define PINGPANG_BUFFER_SIZE         (20*1024)
+#define GPSDBGLOG_EXIT_RETRY_SLEEP (20*1000) //20ms
+#define GPSDBGLOG_EXIT_RETRY_CNT (100) //Total retry time is 100*20ms
+#define GPSDBGLOG_EXIT_RETRY_SGL_INTERVAL (25)  //send signal every 500ms
+#define GPSDBGLOG_EXIT_SIG (SIGRTMIN+1)
+
+// describle one single buffer
+typedef enum {
+    NOTINIT = 0,
+    WRITABLE,  // the state which can swtich to writing state
+    WRITING,   // means the buffer is writing
+    READABLE,  // means mtklogger thread now can read this buffer and write data to flash
+    READING    // means mtklogger thread is writing data to flash
+} buffer_state;
+
+typedef struct {
+    char* volatile next_write;
+    char* start_address_buffer1;
+    char* start_address_buffer2;
+    char* end_address_buffer1;
+    char* end_address_buffer2;
+    // int* p_buffer1_lenth_to_write;
+    // int* p_buffer2_lenth_to_write;
+    // buffer_state* p_buffer1_state;
+    // buffer_state* p_buffer2_state;
+    int volatile buffer1_lenth_to_write;
+    int volatile buffer2_lenth_to_write;
+    buffer_state volatile buffer1_state;
+    buffer_state volatile buffer2_state;
+    int num_loose;
+} ping_pang_buffer;
+// static buffer_state buffer1_state = NOTINIT;
+// static buffer_state buffer2_state = NOTINIT;
+// static int lenth_to_write_buffer1 = 0;
+// static int lenth_to_write_buffer2 = 0;
+static ping_pang_buffer ping_pang_buffer_body;
+
+// function related
+// called when mtklogger thread init if debugtype set true
+static INT32 create_debug_log_file();
+static INT32 mtklog_gps_set_debug_file(char* file_name);
+static INT32 gps_dbg_log_pingpang_init();
+// called in function mnl_sys_alps_nmea_output
+static INT32 gps_dbg_log_pingpang_copy(ping_pang_buffer* pingpang, const char* buffer, INT32 len);
+// called in mtklogger thread when it is need to write
+static size_t gps_dbg_log_pingpang_write(ping_pang_buffer* pingpang, FILE* filp);
+// called when debugtype set 1 to 0 or  mtklogger thread exit
+static INT32 gps_dbg_log_pingpang_free();
+// called when debugtype set 1 to 0 or  mtklogger thread exit
+static INT32 gps_dbg_log_pingpang_flush(ping_pang_buffer* pingpang, FILE * filp);
+
+void gps_dbg_log_thread_exit(int sig_no);
+
+static void mnld_create_mutex( mnld_mutex_enum mutex_idx);
+
+static void mnld_destroy_mutex(mnld_mutex_enum mutex_idx);
+
+static void mnld_take_mutex(mnld_mutex_enum mutex_idx);
+
+static void mnld_give_mutex(mnld_mutex_enum mutex_idx);
+
+static void mnld_create_mutex( mnld_mutex_enum mutex_idx){
+    // mutex index is not within the supported range
+    if (mutex_idx >= MNLD_MUTEX_MAX)
+    {
+        LOGD("mnld_create_mutex fail,mutex_idx error\n");
+        return;
+    }
+
+    if (pthread_mutex_init(&g_mnldMutex[mutex_idx], NULL))
+    {
+        LOGD("mnld_create_mutex fail(%s)\n", strerror(errno));
+    }
+}
+
+static void mnld_destroy_mutex(mnld_mutex_enum mutex_idx){
+
+    if (mutex_idx >= MNLD_MUTEX_MAX)
+    {
+        LOGD("mnld_destroy_mutex fail,mutex_idx error\n");
+        return;
+    }
+
+    if (pthread_mutex_destroy(&g_mnldMutex[mutex_idx]))
+    {
+        LOGD("mnld_destroy_mutex fail(%s)\n", strerror(errno));
+    }
+}
+
+static void mnld_take_mutex(mnld_mutex_enum mutex_idx){
+
+    if (mutex_idx >= MNLD_MUTEX_MAX)
+    {
+        LOGD("mnld_take_mutex fail,mutex_idx error\n");
+        return;
+    }
+
+    if (pthread_mutex_lock(&g_mnldMutex[mutex_idx]))
+    {
+        LOGD("mnld_take_mutex fail(%s)\n", strerror(errno));
+    }
+}
+
+static void mnld_give_mutex(mnld_mutex_enum mutex_idx){
+
+    if (mutex_idx >= MNLD_MUTEX_MAX)
+    {
+        LOGD("mnld_give_mutex fail,mutex_idx error\n");
+        return;
+    }
+
+    if (pthread_mutex_unlock(&g_mnldMutex[mutex_idx]))
+    {
+        LOGD("mnld_give_mutex fail(%s)\n", strerror(errno));
+    }
+}
+
+void gps_stop_dbglog_release_condition(void) {
+    g_gpsdbglogThreadExit = true;
+    release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+    release_condition(&lock_for_sync[PINGPANG_FLUSH_LOCK]);
+    LOGD("exit while, gps_dbg_log thread exit\n");
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  gps_dbg_log_exit_flush
+ * DESCRIPTION
+ *  Set exit flag to true and release condition let gps debug log thread exit.
+ *  Will do GPS debug log flush and pingpang buffer free when thread exit.
+ *  And wait seconds for flush(fwrite) blocking issue.
+ * PARAMETERS
+ *  force_exit      [IN] force exit mnld process, to avoid resource leakage issue.
+ * RETURNS
+ *  None
+ *****************************************************************************/
+void gps_dbg_log_exit_flush(int force_exit) {
+     int cnt = 0;
+
+    gps_stop_dbglog_release_condition(); //Exit gps debug log thread, will flush gps debug log when exit
+    do {
+        if (pthread_dbg_log == C_INVALID_TID)//The thread has exited, will clear pthread_dbg_log at gps dbg log thread exit time
+        {
+            LOGD("gpsdbglog thread exit OK!");
+            break;
+        } else {//The thread still alive
+            if((cnt % GPSDBGLOG_EXIT_RETRY_SGL_INTERVAL == 0)) {
+                gps_stop_dbglog_release_condition(); //Exit gps debug log thread, will flush gps debug log when exit
+            }
+            usleep(GPSDBGLOG_EXIT_RETRY_SLEEP);
+            //Wait here to flush gps debug log, to avoid blocked in flush(fwrite)
+            cnt++;
+        }
+    } while(cnt < GPSDBGLOG_EXIT_RETRY_CNT);
+
+    if(cnt >= GPSDBGLOG_EXIT_RETRY_CNT) {
+        LOGW("GPS debug log may be not flushed completely!!!");
+        if(force_exit == 1) {  //Process exit to avoid resource leakage issue, process will restart
+            mnld_block_exit();
+        }
+    }
+}
+
+void gps_log_file_rename(char *filename_cur) {
+    char tmp_suffix = 'a'-1;
+    char filename1[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    char filename2[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    int indx = 0;
+
+    if (filename_cur == NULL) {
+        LOGE("[gps_log_file_rename]: NULL Pointer!!!");
+        return;
+    }
+
+    MNLD_STRNCPY(filename1, filename_cur, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    indx = strlen(filename1) - strlen(LOG_FILE_WRITING_EXTEN_NAME);
+
+    if(strncmp(&(filename1[indx]), LOG_FILE_WRITING_EXTEN_NAME, strlen(LOG_FILE_WRITING_EXTEN_NAME)) != 0) {
+        LOGE("[gps_log_file_rename]: file extension name not match:%s", filename1);
+        return;
+    }
+
+    filename1[indx] = '\0';//remove ".nmac"
+
+    //Get new file name , storage into filename2
+    do {
+        if(tmp_suffix < 'a') {
+            snprintf(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_EXTEN_NAME, filename1);
+        } else if(tmp_suffix <= 'z') {
+            snprintf(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s_%c"LOG_FILE_EXTEN_NAME, filename1, tmp_suffix);
+        } else {
+            snprintf(filename2, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_EXTEN_NAME, filename1);
+            break;
+        }
+        tmp_suffix++;
+    } while (access(filename2, F_OK) == 0);  //File has existed
+
+    LOGD("Writing file: %s, rename to:%s", filename_cur, filename2);
+    if(rename(filename_cur, filename2) != 0) {
+       LOGE("[gps_log_file_rename]:rename fail:%s", strerror(errno));
+    }
+}
+
+/*************Check the debug file valid or not***************/
+int mnl_debug_file_check(char * dbg_file)
+{
+    char dirname[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+    int index = 0;
+
+    if(NULL == dbg_file) {
+        LOGE("[%s] NULL dbg_file\r\n",__func__);
+        return MTK_GPS_ERROR;
+    }
+
+    MNLD_STRNCPY(dirname, dbg_file, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    for(index=strlen(dirname)-1;index>1;index--) {
+        if(dirname[index] == '/') {
+            break;
+        }
+    }
+    dirname[index+1] = '\0';
+
+    LOGD("dirname:%s\r\n",dirname);
+    if (0 != access(dirname, F_OK|R_OK)) {  // Check if the dir exist, can read,return value 0:success, -1 : fail
+        LOGE("Access gps debug log dir(%s) fail(%s)!\r\n", dirname, strerror(errno));
+        if(ENOENT == errno) {//No such dir
+            LOGD("try to create it");
+            if (mnl_init_gps_data_path(dirname, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN) == -1) {  // mkdir ,if fail print the fail info to main log
+                LOGE("mkdir %s fail(%s)", dirname, strerror(errno));
+                return MTK_GPS_ERROR;
+             }
+        } else {
+            return MTK_GPS_ERROR;
+        }
+    }
+    MNLD_STRNCPY(storagePath, dirname, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    return MTK_GPS_SUCCESS;
+}
+
+static int get_mtklog_path(char *logpath) {
+    char mtklogpath[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    char temp[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    unsigned int len;
+
+    char* ptr;
+    ptr = strchr(logpath, ',');
+    if (ptr) {
+        MNLD_STRNCPY(temp, ptr + 1, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        LOGD("logpath for mtklogger socket msg: %s", temp);
+    } else {
+        LOGD("logpath for mtklogger socket msg has not ',': %s", temp);
+        MNLD_STRNCPY(logpath, MTK_GPS_DATA_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        return 0;
+    }
+
+    len = strlen(temp);
+    if (len != 0  && temp[len-1] != '/') {
+        temp[len++] = '/';
+        if (len < GPS_DEBUG_LOG_FILE_NAME_MAX_LEN) {
+            temp[len] = '\0';
+        }
+    }
+    if (len <= GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - strlen(PATH_SUFFIX)) {
+        sprintf(logpath, "%smtklog/gpsdbglog/", temp);
+        LOGD("get_mtklog_path:logpath is %s", logpath);
+    }
+
+    if (len <= GPS_DEBUG_LOG_FILE_NAME_MAX_LEN-7) {
+        snprintf(mtklogpath, sizeof(mtklogpath), "%smtklog/", temp);
+        if (0 != access(mtklogpath, F_OK)) {    // if mtklog dir is not exit, mkdir
+             LOGD("access dir error(%s), Try to create dir", mtklogpath);
+             if (mkdir(mtklogpath, 0775) == -1) {
+                 MNLD_STRNCPY(logpath, MTK_GPS_DATA_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);  // if mkdir fail, set default path
+                 LOGD("mkdir %s fail(%s), set default logpath(%s)", mtklogpath, strerror(errno), logpath);
+             }
+        }
+    }
+    return 1;
+}
+static int mode = 0;
+int mtklogger2mnl_hdlr(int fd) {
+    int ret = 0;
+    int read_len;
+    char ans[255] = {0};
+    char buff_msg[253] = {0};
+
+    read_len = safe_recvfrom(fd, buff_msg, sizeof(buff_msg) - 1);
+    if (read_len <= 0) {
+        LOGE("mtklogger2mnl_hdlr() safe_recvfrom() failed read_len=%d, reason=[%s]%d",
+            read_len, strerror(errno), errno);
+        return -1;
+    }
+
+    // response "msg,1" to mtklogger
+    snprintf(ans, sizeof(ans), "%s,1", buff_msg);
+    LOGD("notify client, recv %s from mtklogger, ans: %s\n", buff_msg, ans);
+    if (strstr(buff_msg, "set_storage_path")) {  // buff is "set_storage_path,storagePath"
+        MNLD_STRNCPY(storagePath_mtklogger_set, buff_msg, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        get_mtklog_path(storagePath_mtklogger_set);
+        write(fd, ans, strlen(ans));
+    } else if (!strncmp(buff_msg, "deep_start,1", 12)) {
+        time_t tm;
+        struct tm *p;
+        static char GPSLog_timestamp[GPSLog_TIMESTRING_LEN];
+
+        time(&tm);
+        p = localtime(&tm);
+
+        // GPS debug log dir is not exit, mkdir, before add time string, return value 0:success, -1 : fail
+        if (0 != access(storagePath_mtklogger_set, F_OK)) {
+            LOGE("Create dir %s\r\n", strerror(errno));
+            if (mkdir(storagePath_mtklogger_set, 0775) == -1) {
+               // mkdir before GPSLog_%timestamp%,if fail print the fail info to main log
+                LOGE("mkdir %s fail(%s)", storagePath, strerror(errno));
+             }
+        }
+
+        memset(GPSLog_timestamp, 0x00, sizeof(GPSLog_timestamp));
+        snprintf(GPSLog_timestamp, sizeof(GPSLog_timestamp), "GPSLog_%04d_%02d%02d_%02d%02d%02d",
+        1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+        p->tm_hour, p->tm_min, p->tm_sec);
+
+        snprintf(storagePath, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s%s/", storagePath_mtklogger_set, GPSLog_timestamp);
+
+        // strncat(storagePath, GPSLog_timestamp, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+
+        LOGD("storagePath:%s\n", storagePath);
+
+        gps_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+        LOGD("gps_debuglog_state:%d", gps_debuglog_state);
+
+        #if ANDROID_MNLD_PROP_SUPPORT
+        property_set(GPS_LOG_PERSIST_STATE, GPS_LOG_PERSIST_VALUE_ENABLE);
+        property_set(GPS_LOG_PERSIST_PATH, storagePath);
+        #endif
+        write(fd, ans, strlen(ans));
+
+        mode = 0;
+        MNLD_STRNCPY(gps_debuglog_file_name, storagePath, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        strncat(gps_debuglog_file_name, log_filename_suffix, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - strlen(gps_debuglog_file_name));
+
+        LOGD("gps_debuglog_file_name:%s\n", gps_debuglog_file_name);
+
+        if (mnld_is_gps_or_ofl_started_done()) {
+            ret = mtk_gps_set_debug_type(gps_debuglog_state);
+            if (MTK_GPS_ERROR == ret) {
+                LOGE("deep_start,1,mtk_gps_set_debug_type fail");
+            } else {
+                LOGD("start gpsdbglog successfully\n");
+            }
+            fg_create_dir_done = 0;
+            release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+        }
+    } else if (!strncmp(buff_msg, "deep_start,2", 12)) {
+        gps_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+        LOGD("gps_debuglog_state:%d", gps_debuglog_state);
+
+        #if ANDROID_MNLD_PROP_SUPPORT
+        property_set(GPS_LOG_PERSIST_STATE, GPS_LOG_PERSIST_VALUE_ENABLE);
+        property_set(GPS_LOG_PERSIST_PATH, storagePath);
+        #endif
+        write(fd, ans, strlen(ans));
+
+        MNLD_STRNCPY(gps_debuglog_file_name, LOG_FILE, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        MNLD_STRNCPY(storagePath, LOG_FILE_PATH, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+        if (mnld_is_gps_or_ofl_started_done()) {
+            ret = mtk_gps_set_debug_type(gps_debuglog_state);
+            if (MTK_GPS_ERROR == ret) {
+                LOGE("deep_start,2,mtk_gps_set_debug_type fail");
+            } else {
+                LOGD("start gpsdbglog successfully\n");
+            }
+            fg_create_dir_done = 0;
+            release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+        }
+
+        mode = 1;
+    } else if (!strncmp(buff_msg, "deep_stop", 9)) {
+        gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+        LOGD("gps_debuglog_state:%d", gps_debuglog_state);
+
+        #if ANDROID_MNLD_PROP_SUPPORT
+        property_set(GPS_LOG_PERSIST_STATE, GPS_LOG_PERSIST_VALUE_DISABLE);
+        property_set(GPS_LOG_PERSIST_PATH, GPS_LOG_PERSIST_VALUE_NONE);
+        #endif
+        write(fd, ans, strlen(ans));
+
+        if (mnld_is_gps_or_ofl_started_done()) {
+            ret = mtk_gps_set_debug_type(gps_debuglog_state);
+            if (MTK_GPS_ERROR== ret) {
+                LOGE("deep_stop, mtk_gps_set_debug_type fail");
+            } else {
+                LOGD("stop gpsdbglog successfully\n");
+            }
+            release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+        }
+        mnl2mpe_set_log_path(storagePath, 0, 0);
+        mode = 0;
+    } else {
+        write(fd, ans, strlen(ans));
+        LOGE("unknown message: %s\n", buff_msg);
+    }
+    return 0;
+}
+
+void mtklogger_mped_reboot_message_update(void) {
+    if (gps_debuglog_state == MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD) {
+        mnl2mpe_set_log_path(storagePath, 0, mode);
+    } else if (gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD) {
+        mnl2mpe_set_log_path(storagePath, 1, mode);
+    }
+}
+void* gps_dbg_log_thread(void* arg) {
+    size_t count = 0;
+    LOGD("create: %.8X, arg = %p\r\n", (unsigned int)pthread_self(), arg);
+    pthread_detach(pthread_self());
+
+    init_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+    init_condition(&lock_for_sync[PINGPANG_FLUSH_LOCK]);
+    #if defined(__ANDROID_OS__)
+    GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+    #elif defined(__LINUX_OS__)
+    FILE_FCLOSE(g_hLogFile);
+    #endif
+    if (gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD) {
+        LOGD("gps_debuglog_state: MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD");
+        create_debug_log_file();
+        mnl2mpe_set_log_path(storagePath, 1, 0); //Notify MPE to enable log and pass the log path to MPE, the 3rd param is unused
+    }
+
+    if ((access(storagePath, F_OK|R_OK|W_OK)) == 0) {
+        DirLogSize = gps_log_dir_check(storagePath);
+    }
+
+    while (!g_gpsdbglogThreadExit) {
+        get_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+        //LOGD("get_condition PINGPANG_WRITE_LOCK");
+        if (gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD && !g_gpsdbglogThreadExit) {
+            if (fg_create_dir_done == 0){
+                mtklog_gps_set_debug_file(gps_debuglog_file_name);
+                mnl2mpe_set_log_path(storagePath, 1, 0); //Notify MPE to enable log and pass the log path to MPE, the 3rd param is unused
+            }
+
+            if (0 != access(storagePath, F_OK|R_OK|W_OK)) {  // return value 0:success, -1 : fail
+                LOGE("Access gps debug log dir fail(%s)!\r\n", strerror(errno));
+                #if defined(__ANDROID_OS__)
+                GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+                #elif defined(__LINUX_OS__)
+                FILE_FCLOSE(g_hLogFile);
+                #endif
+
+                if (mnld_is_gps_or_ofl_started_done()) {
+                    if (MTK_GPS_ERROR == mtk_gps_set_debug_type(gps_debuglog_state)) {
+                        LOGE("GPS_DEBUGLOG_DISABLE, mtk_gps_set_debug_type fail");
+                    } else {
+                        LOGD("GPS_DEBUGLOG_DISABLE, stop gpsdbglog successfully\n");
+                    }
+                }
+            }
+            if (g_hLogFile != NULL) {
+                if (Current_FileSize + PINGPANG_BUFFER_SIZE > MAX_DBG_LOG_FILE_SIZE) {
+                    //char tmpfilename[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN]={0};
+                    Filenum++;
+                    #if defined(__ANDROID_OS__)
+                    GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+                    #elif defined(__LINUX_OS__)
+                    FILE_FCLOSE(g_hLogFile);
+                    #endif
+                    DirLogSize = DirLogSize + Current_FileSize;
+                    snprintf(gsGpsLogFileName_full, sizeof(gsGpsLogFileName_full), "%s-%d", gsGpsLogFileName, Filenum);
+                    strncat(gsGpsLogFileName_full, LOG_FILE_WRITING_EXTEN_NAME, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - strlen(gsGpsLogFileName_full));
+                    #if ANDROID_MNLD_PROP_SUPPORT
+                    property_set(GPS_LOG_PERSIST_FLNM, strstr(gsGpsLogFileName_full, log_filename_suffix));
+                    #endif
+                    g_hLogFile = fopen(gsGpsLogFileName_full, "w");
+                    if (NULL == g_hLogFile) {
+                        LOGE("open file fail, NULL == g_hLogFile\r\n");
+                        break;
+                    }
+                    if (DirLogSize  > (size_t)(MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE)
+                        || (total_file_count + Filenum) > GPS_DBG_LOG_FILE_NUM_LIMIT) {
+                        DirLogSize = gps_log_dir_check(storagePath);
+                    }
+
+                    Current_FileSize = 0;
+                }
+            }
+            if (g_hLogFile != NULL) {
+                count = gps_dbg_log_pingpang_write(&ping_pang_buffer_body, g_hLogFile);
+                Current_FileSize = count + Current_FileSize;
+            }
+        } else {
+            if ((ping_pang_buffer_body.start_address_buffer1 != NULL)
+                && (ping_pang_buffer_body.start_address_buffer2 != NULL)) {
+                //LOGD("debuglog switch closed, flush gpsdbglog to flash from pingpang\r\n");
+                if (g_hLogFile != NULL) {
+                    gps_dbg_log_pingpang_flush(&ping_pang_buffer_body, g_hLogFile);
+                }
+                gps_dbg_log_pingpang_free();
+                #if defined(__ANDROID_OS__)
+                GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+                #elif defined(__LINUX_OS__)
+                FILE_FCLOSE(g_hLogFile);
+                #endif
+            }
+        }
+    }
+
+    if (g_hLogFile != NULL) {
+        if ((ping_pang_buffer_body.start_address_buffer1 != NULL)
+            && (ping_pang_buffer_body.start_address_buffer2 != NULL)) {
+            // flush
+            //LOGD("thread will exit,flush gpsdbglog to flash from pingpang\r\n");
+            gps_dbg_log_pingpang_flush(&ping_pang_buffer_body, g_hLogFile);
+
+            // free pingpang
+            //LOGD("free pingpang buffer now\r\n");
+            gps_dbg_log_pingpang_free();
+        }
+
+        #if defined(__ANDROID_OS__)
+        GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);
+        #elif defined(__LINUX_OS__)
+        FILE_FCLOSE(g_hLogFile);
+        #endif
+
+        LOGD("close log file\r\n");
+    }
+
+    mnld_destroy_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    pthread_dbg_log = C_INVALID_TID;
+    return NULL;
+}
+
+int gps_dbg_log_thread_init() {
+    mnld_create_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    g_gpsdbglogThreadExit = false;
+    if (!g_pingpang_init && (gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD)) {
+        if (MTK_GPS_ERROR == gps_dbg_log_pingpang_init()) {
+            g_gpsdbglogThreadExit = true;
+            LOGE("gps dbg log pingpang init fail, thread exit");
+        }
+    }
+    pthread_create(&pthread_dbg_log, NULL, gps_dbg_log_thread, NULL);
+    return 0;
+}
+
+int create_mtklogger2mnl_fd() {
+    static int socket_fd = 0;
+
+#if defined(__LINUX_OS__)
+    socket_fd = socket_local_server("gpslogd", SOCK_STREAM);
+#elif defined(__ANDROID_OS__)
+    socket_fd = socket_local_server("gpslogd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+#endif
+    if (socket_fd < 0) {
+        LOGE("create server fail(%s)", strerror(errno));
+        return -1;
+    }
+    LOGD("socket_fd = %d", socket_fd);
+
+    if (listen(socket_fd, 5) < 0) {
+        LOGE("listen socket fail(%s)", strerror(errno));
+        close(socket_fd);
+        return -1;
+    }
+
+    return socket_fd;
+}
+
+static int FindGPSlogFile(char Filename[]) {
+    int i;
+    int GPSlogNamelen = 0;
+
+    GPSlogNamelen = strlen(log_filename_suffix);
+
+    for (i = 0; i < GPSlogNamelen; i++) {
+        if (Filename[i]!= log_filename_suffix[i]) {
+            return MTK_GPS_ERROR;
+        }
+    }
+    return MTK_GPS_SUCCESS;
+}
+
+static size_t GetFileSize(char *filename) {
+    char dir_filename[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+    struct stat statbuff;
+
+    memset(dir_filename, 0x00, sizeof(dir_filename));
+
+    if (NULL == filename) {
+        LOGE("[GetFileSize][error]: File name is NULL!!\r\n");
+        return 0;
+    }
+
+    // LOGD("[GetFileSize]File name:%s!\r\n", filename);
+    snprintf(dir_filename, sizeof(dir_filename), "%s%s", storagePath,
+            filename);
+
+    if (stat(dir_filename, &statbuff) < 0) {
+        LOGE("[GetFileSize][error]: open file(%s) state fail(%s)!\r\n", dir_filename, strerror(errno));
+        return 0;
+    } else {
+        return statbuff.st_size;  // return the file size
+    }
+}
+
+/*static int CmpStrFile(char a[], char b[]) {  // compare two log files
+    char *pa = a, *pb = b;
+    while (*pa == *pb) {
+        pa++;
+        pb++;
+    }
+    return (*pa - *pb);
+}*/
+
+static int CmpFileTime(char *filename1, char *filename2) {
+    char dir_filename1[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+    char dir_filename2[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+    struct stat statbuff1;
+    struct stat statbuff2;
+
+    memset(dir_filename1, 0x00, sizeof(dir_filename1));
+    memset(dir_filename2, 0x00, sizeof(dir_filename2));
+
+    if (NULL == filename1 || NULL == filename2) {
+        LOGE("[CmpFileTime][error]: File name is NULL!!\r\n");
+        return 0;
+    }
+    // LOGD("[CmpFileTime]File name1:%s, filename2:%s!!\r\n", filename1, filename2);
+
+    snprintf(dir_filename1, sizeof(dir_filename1), "%s%s", storagePath, filename1);
+    snprintf(dir_filename2, sizeof(dir_filename2), "%s%s", storagePath, filename2);
+
+    if (stat(dir_filename1, &statbuff1) < 0) {
+        LOGD("[CmpFileTime][error]: open file(%s) state  fail(%s)!!\r\n", dir_filename1, strerror(errno));
+        return 0;
+    }
+
+    if (stat(dir_filename2, &statbuff2) < 0) {
+        LOGD("[CmpFileTime][error]: open file(%s) state  fail(%s)!!\r\n", dir_filename2, strerror(errno));
+        return 0;
+    }
+    return (statbuff1.st_mtime-statbuff2.st_mtime);
+}
+
+static INT32 create_debug_log_file() {
+    time_t tm;
+    struct tm *p;
+    char file_tree[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    FILE* fd = NULL;
+
+    time(&tm);
+    p = localtime(&tm);
+    if (strlen((const char*)gps_debuglog_file_name) && (p != NULL)) {  // if filename length > 0
+        // initialize debug log (use OPEN_ALWAYS to append debug log)
+        // GPS debug log dir is not exit, mkdir, return value 0:success, -1 : fail
+        if (mnl_init_gps_data_path(storagePath, MNL_GPS_DATA_PATH_MAX_LENGTH) == -1)
+        {  // mkdir ,if fail print the fail info to main log
+            LOGD("Try to create dir(%s)\r\n", storagePath);
+            if (mkdir(storagePath, 0775) == -1) {  // mkdir ,if fail print the fail info to main log
+                LOGE("mkdir %s fail(%s)", storagePath, strerror(errno));
+                return MTK_GPS_ERROR;
+             } else {  // Create dir successfully
+                snprintf(file_tree, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%sfile_tree.txt", storagePath_mtklogger_set);
+                fd = fopen(file_tree, "at");  // Write the latest storage path to the end of file_tree.txt
+                if (NULL != fd) {
+                    fwrite(storagePath, 1, strlen(storagePath), fd);
+                    fwrite("\n", 1, 1, fd);
+                    fclose(fd);
+                } else {
+                    LOGE("write file %s fail(%s)", file_tree, strerror(errno));
+                }
+             }
+        }
+
+        memset(gsGpsLogFileName, 0x00, sizeof(gsGpsLogFileName));
+        snprintf(gsGpsLogFileName, sizeof(gsGpsLogFileName), "%s.%04d%02d%02d%02d%02d%02d", gps_debuglog_file_name,
+        1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+        p->tm_hour, p->tm_min, p->tm_sec);
+        Filenum = 0;
+        #if defined(__ANDROID_OS__)
+        GPSLOG_FCLOSE(g_hLogFile, gsGpsLogFileName_full);// close file before open,  if the file has been open.
+        #elif defined(__LINUX_OS__)
+        FILE_FCLOSE(g_hLogFile);
+        #endif
+
+        snprintf(gsGpsLogFileName_full, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s"LOG_FILE_WRITING_EXTEN_NAME, gsGpsLogFileName);
+        #if ANDROID_MNLD_PROP_SUPPORT
+        property_set(GPS_LOG_PERSIST_FLNM, strstr(gsGpsLogFileName_full, log_filename_suffix));
+        #endif
+
+        int LogFile_fd = open(gsGpsLogFileName_full, O_RDWR|O_NONBLOCK|O_CREAT, 0660);
+        if (LogFile_fd < 0) {
+            LOGE("open file fail(%s)", strerror(errno));
+            return MTK_GPS_ERROR;
+        } else {
+            int flags = fcntl(LogFile_fd, F_GETFL, 0);
+            if (fcntl(LogFile_fd, F_SETFL, flags|O_NONBLOCK) < 0) {
+                LOGD("fcntl logFile_fd fail");
+            }
+            g_hLogFile = fdopen(LogFile_fd, "w");
+        }
+        LOGD("file(%s) created successfully(0x%x)\r\n", gsGpsLogFileName, (unsigned int)g_hLogFile);
+
+        Current_FileSize = 0;
+        fg_create_dir_done = 1;
+        return MTK_GPS_SUCCESS;
+    }
+    LOGD("create_debug_log_file fail");
+    return MTK_GPS_ERROR;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtklog_gps_set_debug_file
+ * DESCRIPTION
+ *  Set the GPS debug file name(include the path name) in running time
+ * PARAMETERS
+ *  file_name         [IN]   the debug file name needs to be changed
+ * RETURNS
+ *  success(MTK_GPS_SUCCESS); failure (MTK_GPS_ERROR)
+ *****************************************************************************/
+static INT32 mtklog_gps_set_debug_file(char* file_name) {
+    if (NULL == file_name) {  // Null pointer, return error
+        LOGE("file_name is NULL pointer! \r\n");
+        return MTK_GPS_ERROR;
+    }
+// The length of file_name is too long, return error
+    if (GPS_DEBUG_LOG_FILE_NAME_MAX_LEN <= (strlen(file_name) + 1)) {
+        LOGE("file_name is too long! \r\n");
+        return MTK_GPS_ERROR;
+    }
+
+    if (!g_pingpang_init) {
+        if (MTK_GPS_ERROR == gps_dbg_log_pingpang_init()) {
+            g_gpsdbglogThreadExit = true;
+            LOGE("gps dbg log pingpang init fail, thread exit");
+        }
+    }
+
+    if (MTK_GPS_ERROR == create_debug_log_file()) {
+        LOGD("create debug file(%s) error\r\n", file_name);
+    } else {  // Create file success, check dir size
+        DirLogSize = gps_log_dir_check(storagePath);
+    }
+
+    return MTK_GPS_SUCCESS;
+}
+
+size_t gps_log_dir_check(char * dirname) {   // file size check
+    char temp_filename[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+    char OldGpsFile[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+    size_t DirLogSize_temp;
+    DIR *p_dir;
+    char OldFile[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN];
+
+    struct dirent *p_dirent;
+    do {
+        if (0 != access(dirname, F_OK|R_OK)) {  // Check if the dir exist, can read,return value 0:success, -1 : fail
+            LOGE("Access gps debug log dir fail(%s)!\r\n", strerror(errno));
+            return MTK_GPS_ERROR;
+        }
+
+        if ((p_dir = opendir(dirname)) == NULL) {
+            LOGE("open dir error(%s)\r\n", strerror(errno));
+            return MTK_GPS_ERROR;
+        } else {
+            LOGD("open dir sucess\r\n");
+        }
+
+        total_file_count = 0;
+        memset(OldGpsFile, 0x00, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);  // For compare file name,set a max char value
+        DirLogSize_temp = 0;
+
+        while ((p_dirent = readdir(p_dir)) && !g_gpsdbglogThreadExit) {
+            if (NULL == p_dirent || (0 != access(dirname, F_OK))) {  // return value 0:success, -1 : fail
+                LOGE("Access gps debug log dir fail(%s)!\r\n", dirname);
+                break;
+            }
+            if (strcmp(p_dirent->d_name, ".") == 0 || strcmp(p_dirent->d_name, "..") == 0) {  // Ignore the "." & ".."
+                continue;  // while((p_dirent=readdir(p_dir)) && !g_gpsdbglogThreadExit)
+            }
+
+            if (GPS_DEBUG_LOG_FILE_NAME_MAX_LEN > strlen(p_dirent->d_name)) {
+                memset(temp_filename, 0 , GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+                MNLD_STRNCPY(temp_filename, (void *)&p_dirent->d_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - 1);
+            } else {  // The length of d_name is too long, ignore this file
+                LOGD("d_name is too long!\r\n");
+                continue;
+            }
+
+            if (FindGPSlogFile(temp_filename) == MTK_GPS_SUCCESS) {
+                // LOGD("%s is a GPS debug log file!\r\n", temp_filename);
+
+                DirLogSize_temp = GetFileSize(temp_filename) + DirLogSize_temp;
+                total_file_count++;
+                if (strncmp(OldGpsFile, temp_filename, strlen(log_filename_suffix)) != 0) {
+                    MNLD_STRNCPY(OldGpsFile, temp_filename, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - 1);
+                    LOGD("copy file name to OldGpsFile: %s, and continue\r\n", OldGpsFile);
+                    continue;  // while((p_dirent=readdir(p_dir)) && !g_gpsdbglogThreadExit)
+                }
+
+                if (CmpFileTime(temp_filename, OldGpsFile) < 0) {  // Find the latest old file
+                    memset(OldGpsFile, '\0', GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+                    MNLD_STRNCPY(OldGpsFile, temp_filename, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN - 1);
+                }
+            }
+        }
+        LOGD("DirLogSize_temp:%d, the latest OldGpsFile:%s!\r\n", DirLogSize_temp, OldGpsFile);
+        closedir(p_dir);
+        if (DirLogSize_temp >= (MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE)
+            || (total_file_count > GPS_DBG_LOG_FILE_NUM_LIMIT)) {
+            // Over size or the number of GPS debug log file over the limitation
+            // when OldGpsFile is small, it will cause many re-calculation in the second loop.  need to avoid it.
+            size_t ret = 0;
+
+            ret = GetFileSize(OldGpsFile);
+            memset(OldFile, 0x00, sizeof(OldFile));
+            snprintf(OldFile, sizeof(OldFile), "%s%s", storagePath, OldGpsFile);
+
+            LOGD("need delete OldFile:%s\r\n", OldFile);
+
+            if (remove(OldFile) != 0) {  // Error handle
+                LOGW("Remove file %s error(%s)!\r\n", OldFile, strerror(errno));
+            }
+            DirLogSize_temp = DirLogSize_temp - ret;
+        }
+
+        LOGD("After remove file gpsdebug log dir size:%d!\r\n", DirLogSize_temp);
+    }while (((DirLogSize_temp > (MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE))
+    || (total_file_count > GPS_DBG_LOG_FILE_NUM_LIMIT)) && !g_gpsdbglogThreadExit);
+
+    if ((DirLogSize_temp <= (MAX_DBG_LOG_DIR_SIZE - MAX_DBG_LOG_FILE_SIZE)) && g_gpsdbglogThreadExit) {
+        LOGD("gps_log_dir_check interrupted size=%d!!\r\n", DirLogSize_temp);
+    }
+    LOGD("dir size:%d\r\n", DirLogSize_temp);
+    return DirLogSize_temp;
+}
+
+INT32 mnl_sys_alps_gps_dbg2file_mnld(const char* buffer, UINT32 length) {
+    if (mtk_gps_log_is_hide() == 1) {   //Forbit to print gps debug log
+         return MTK_GPS_SUCCESS;
+    }
+
+    if ((gps_debuglog_state == MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD) \
+                 && (ping_pang_buffer_body.next_write != NULL)) {
+        gps_dbg_log_pingpang_copy(&ping_pang_buffer_body, buffer, length);
+    } else {
+        LOGD("will not copy to pingpang, DebugType:%d, buffer1:%p, buffer2:%p, g_hLogFile:%p\r\n",
+            gps_debuglog_state, ping_pang_buffer_body.start_address_buffer1,
+            ping_pang_buffer_body.start_address_buffer2, g_hLogFile);
+    }
+
+    return MTK_GPS_SUCCESS;
+}
+
+// if return error , gpsdbglog will not be writen
+static INT32 gps_dbg_log_pingpang_init() {
+    LOGD("gps_dbg_log_pingpang_init");
+    mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    memset(&ping_pang_buffer_body, 0x00, sizeof(ping_pang_buffer_body));
+    if (((ping_pang_buffer_body.start_address_buffer1 = calloc(1, PINGPANG_BUFFER_SIZE)) == NULL) || \
+        ((ping_pang_buffer_body.start_address_buffer2 = calloc(1, PINGPANG_BUFFER_SIZE)) == NULL)) {
+        if (ping_pang_buffer_body.start_address_buffer1 != NULL) {
+            free(ping_pang_buffer_body.start_address_buffer1);
+            ping_pang_buffer_body.start_address_buffer1 = NULL;
+        }
+        if (ping_pang_buffer_body.start_address_buffer2 != NULL) {
+            free(ping_pang_buffer_body.start_address_buffer2);
+           ping_pang_buffer_body.start_address_buffer2 = NULL;
+        }
+        mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+        return MTK_GPS_ERROR;
+    }
+    // lenth_to_write_buffer1 = 0;
+    // lenth_to_write_buffer2 = 0;
+    ping_pang_buffer_body.buffer1_state = WRITING;
+    ping_pang_buffer_body.buffer2_state = WRITABLE;
+    // buffer1_state = WRITING;
+    // buffer2_state = WRITABLE;
+    // ping_pang_buffer_body.p_buffer1_lenth_to_write = &lenth_to_write_buffer1;
+    // ping_pang_buffer_body.p_buffer2_lenth_to_write = &lenth_to_write_buffer2;
+    ping_pang_buffer_body.end_address_buffer1 = ping_pang_buffer_body.start_address_buffer1 + PINGPANG_BUFFER_SIZE-2;
+    ping_pang_buffer_body.end_address_buffer2 = ping_pang_buffer_body.start_address_buffer2 + PINGPANG_BUFFER_SIZE-2;
+    ping_pang_buffer_body.next_write = ping_pang_buffer_body.start_address_buffer1;
+
+    g_pingpang_init = true;
+    mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    return MTK_GPS_SUCCESS;
+}
+
+static INT32 gps_dbg_log_pingpang_copy(ping_pang_buffer* pingpang, const char* buffer, INT32 len) {
+    if ((len >= PINGPANG_BUFFER_SIZE-1) || (len < 0)) {
+        LOGW("len = %d out of range\n", len);
+        return MTK_GPS_ERROR;
+    }
+    mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    if (pingpang->next_write == NULL) {
+        LOGW("next_write is NULL\n");
+        return MTK_GPS_ERROR;
+    }
+    if ((pingpang->buffer1_state == WRITING) && (pingpang->buffer2_state != WRITING)) {
+        if (pingpang->next_write+len > pingpang->end_address_buffer1) {
+            if (pingpang->buffer2_state == WRITABLE) {
+                pingpang->buffer1_lenth_to_write = pingpang->next_write - pingpang->start_address_buffer1;
+                pingpang->next_write = pingpang->start_address_buffer2;
+                pingpang->buffer2_state = WRITING;
+                pingpang->buffer1_state = READABLE;
+                release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+            } else {
+                memset(pingpang->start_address_buffer1, 0x0, PINGPANG_BUFFER_SIZE);
+                pingpang->next_write = pingpang->start_address_buffer1;
+                pingpang->num_loose++;
+                LOGD("loose log ,num is %d \r\n", pingpang->num_loose);
+            }
+        }
+    } else if ((pingpang->buffer2_state == WRITING) && (pingpang->buffer1_state != WRITING)) {
+        if (pingpang->next_write+len > pingpang->end_address_buffer2) {
+            if (pingpang->buffer1_state == WRITABLE) {
+                pingpang->buffer2_lenth_to_write = pingpang->next_write - pingpang->start_address_buffer2;
+                pingpang->next_write = pingpang->start_address_buffer1;
+                pingpang->buffer1_state = WRITING;
+                pingpang->buffer2_state = READABLE;
+                release_condition(&lock_for_sync[PINGPANG_WRITE_LOCK]);
+            } else {
+                memset(pingpang->start_address_buffer2, 0x0, PINGPANG_BUFFER_SIZE);
+                pingpang->next_write = pingpang->start_address_buffer2;
+                pingpang->num_loose++;
+                LOGD("loose log ,num is %d \r\n", pingpang->num_loose);
+            }
+        }
+    } else {
+        LOGE("abnormal happens, buffer1_state=%d, buffer2_state=%d\r\n", pingpang->buffer1_state, pingpang->buffer2_state);
+        mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+        return MTK_GPS_ERROR;
+    }
+
+    memcpy(pingpang->next_write, buffer, len);
+    pingpang->next_write += len;
+    mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    return MTK_GPS_SUCCESS;
+}
+
+// the real write to flash
+static size_t gps_dbg_log_pingpang_write(ping_pang_buffer* pingpang, FILE* filp) {
+    size_t count = 0;
+    if ((pingpang->buffer1_state == READABLE)\
+        && (pingpang->buffer2_state != READABLE)\
+        && ((pingpang->buffer1_lenth_to_write) != 0)) {
+        pingpang->buffer1_state = READING;
+        count = fwrite(pingpang->start_address_buffer1, 1, pingpang->buffer1_lenth_to_write, filp);
+        memset(pingpang->start_address_buffer1, 0x0, PINGPANG_BUFFER_SIZE);
+        pingpang->buffer1_lenth_to_write = 0;
+        pingpang->buffer1_state = WRITABLE;
+    } else if ((pingpang->buffer2_state == READABLE)\
+        && (pingpang->buffer1_state != READABLE)\
+        && ((pingpang->buffer2_lenth_to_write) != 0)) {
+        pingpang->buffer2_state = READING;
+        count = fwrite(pingpang->start_address_buffer2, 1, pingpang->buffer2_lenth_to_write, filp);
+        memset(pingpang->start_address_buffer2, 0x0, PINGPANG_BUFFER_SIZE);
+        pingpang->buffer2_lenth_to_write = 0;
+        pingpang->buffer2_state = WRITABLE;
+    } else {
+        return count;
+    }
+    LOGD("write to flash %d bytes\n", count);
+    return count;
+}
+
+// when mnl exit or mtklogger set 1 to 0, there is a need free pingpang buffer
+static INT32 gps_dbg_log_pingpang_free() {
+    mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    if (ping_pang_buffer_body.start_address_buffer1 != NULL) {
+        free(ping_pang_buffer_body.start_address_buffer1);
+    }
+    if (ping_pang_buffer_body.start_address_buffer2 != NULL) {
+        free(ping_pang_buffer_body.start_address_buffer2);
+    }
+    memset(&ping_pang_buffer_body, 0x00, sizeof(ping_pang_buffer_body));
+    // lenth_to_write_buffer1 = 0;
+    // lenth_to_write_buffer2 = 0;
+    // buffer1_state = NOTINIT;
+    // buffer2_state = NOTINIT;
+
+    g_pingpang_init = false;
+    LOGD("free pingpang buffer\r\n");
+    mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    return MTK_GPS_SUCCESS;
+}
+
+// when mnl exit or mtklogger set 1 to 0, there is a need to flush the data to flash from buffer
+static INT32 gps_dbg_log_pingpang_flush(ping_pang_buffer * pingpang, FILE* filp) {
+    char* tmp_next_write = NULL;
+    mnld_take_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    tmp_next_write = pingpang->next_write;
+    if ((pingpang->buffer1_state == WRITING) && (pingpang->buffer2_state != WRITING)) {
+        if (pingpang->buffer2_state == READABLE) {
+            fwrite(pingpang->start_address_buffer2, 1, pingpang->buffer2_lenth_to_write, filp);
+        }
+        fwrite(pingpang->start_address_buffer1, 1, tmp_next_write - pingpang->start_address_buffer1, filp);
+    } else if ((pingpang->buffer2_state == WRITING) && (pingpang->buffer1_state != WRITING)) {
+        if (pingpang->buffer1_state == READABLE) {
+            fwrite(pingpang->start_address_buffer1, 1, pingpang->buffer1_lenth_to_write, filp);
+        }
+        fwrite(pingpang->start_address_buffer2, 1, tmp_next_write - pingpang->start_address_buffer2, filp);
+    } else {
+        LOGE("abnormal happens\r\n");
+    }
+    LOGD("flush gpsdbg to flash done!\r\n");
+    mnld_give_mutex(MNLD_MUTEX_PINGPANG_WRITE);
+    return MTK_GPS_SUCCESS;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  gps_dbg_log_property_load
+ * DESCRIPTION
+ *  Load properties to set gps_debuglog_state, storagePath, gps_debuglog_file_name and
+ *  to rename the legacy gps debug log .nmac to .nma.
+ *  The legacy gps debug log file name has been stored in GPS_LOG_PERSIST_PATH & GPS_LOG_PERSIST_FLNM
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  None
+ *****************************************************************************/
+void gps_dbg_log_property_load(void) {
+#if ANDROID_MNLD_PROP_SUPPORT
+        char path_result[PROPERTY_VALUE_MAX] = {0};
+        char flnm_result[PROPERTY_VALUE_MAX] = {0};
+        char state_result[PROPERTY_VALUE_MAX] = {0};
+        char filename_full[GPS_DEBUG_LOG_FILE_NAME_MAX_LEN] = {0};
+
+        if(property_get(GPS_LOG_PERSIST_STATE, state_result, NULL) != 0) {
+            if(state_result[0] == '1') {
+                gps_debuglog_state = MTK_GPS_ENABLE_DEBUG_MSG_WR_BY_MNLD;
+            } else {
+                gps_debuglog_state = MTK_GPS_DISABLE_DEBUG_MSG_WR_BY_MNLD;
+            }
+        }
+
+        if ((property_get(GPS_LOG_PERSIST_PATH, path_result, NULL) != 0)
+            && (strcmp(path_result, GPS_LOG_PERSIST_VALUE_NONE) != 0)) {
+            MNLD_STRNCPY(storagePath, path_result, PROPERTY_VALUE_MAX);
+            snprintf(gps_debuglog_file_name, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s%s", storagePath, log_filename_suffix);
+
+            if((property_get(GPS_LOG_PERSIST_FLNM, flnm_result, NULL) != 0)
+            && (strcmp(flnm_result, GPS_LOG_PERSIST_VALUE_NONE) != 0)
+            && ((strlen(path_result) + strlen(flnm_result)) < GPS_DEBUG_LOG_FILE_NAME_MAX_LEN)) {
+                snprintf(filename_full, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN, "%s%s", path_result, flnm_result);
+                LOGD("Rename legacy gpsdbgfile:%s", filename_full);
+                gps_log_file_rename(filename_full);
+            } else {
+                LOGE("length fail: %s(len:%d), %s(len:%d)", path_result, strlen(path_result), flnm_result, strlen(flnm_result));
+            }
+        }
+#endif
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl2hal_interface.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl2hal_interface.c
new file mode 100644
index 0000000..492d293
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl2hal_interface.c
@@ -0,0 +1,581 @@
+#include "mnl2hal_interface.h"
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mpe.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl2hal"
+#endif
+
+int mnl2hal_mnld_reboot() {
+    LOGD("mnl2hal_mnld_reboot");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_MNLD_REBOOT);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_location(gps_location location) {
+    //LOGD("mnl2hal_location");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_LOCATION);
+    put_binary(buff, &offset, (const char*)&location, sizeof(location));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_status(gps_status status) {
+    LOGD("mnl2hal_gps_status  status=%d", status);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_STATUS);
+    put_binary(buff, &offset, (const char*)&status, sizeof(status));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_sv(gnss_sv_info sv) {
+    //LOGD("mnl2hal_gps_sv  num=%d", sv.num_svs);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_SV);
+    put_binary(buff, &offset, (const char*)&sv, sizeof(sv));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_nmea(int64_t timestamp, const char* nmea, int length) {
+    #ifdef CONFIG_GPS_ENG_LOAD
+    if ('$' == nmea[0] && (strncmp(&nmea[3],"RMC", 3)==0)) {
+        LOGD("timestamp=%llu, len=%d, nmea=%s",timestamp, length, nmea);
+    }
+    #endif
+
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_NMEA);
+    put_long(buff, &offset, timestamp);
+    put_string(buff, &offset, nmea);
+    put_int(buff, &offset, length);
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_capabilities(gps_capabilites capabilities) {
+    LOGD("mnl2hal_gps_capabilities  capabilities=0x%x", capabilities);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_CAPABILITIES);
+    put_binary(buff, &offset, (const char*)&capabilities, sizeof(capabilities));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_measurements(gps_data data) {
+    LOGD("mnl2hal_gps_measurements");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_MEASUREMENTS);
+    put_binary(buff, &offset, (const char*)&data, sizeof(data));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gps_navigation(gps_nav_msg msg) {
+    LOGD("mnl2hal_gps_navigation");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GPS_NAVIGATION);
+    put_binary(buff, &offset, (const char*)&msg, sizeof(msg));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gnss_measurements(gnss_data data) {
+    LOGD("mnl2hal_gnss_measurements");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GNSS_MEASUREMENTS);
+    put_binary(buff, &offset, (const char*)&data, sizeof(data));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_gnss_navigation(gnss_nav_msg msg) {
+    LOGD("mnl2hal_gnss_navigation");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_GNSS_NAVIGATION);
+    put_binary(buff, &offset, (const char*)&msg, sizeof(msg));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+
+int mnl2hal_request_wakelock() {
+    LOGD("mnl2hal_request_wakelock");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_WAKELOCK);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_release_wakelock() {
+    LOGD("mnl2hal_release_wakelock");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_RELEASE_WAKELOCK);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_utc_time() {
+    LOGD("mnl2hal_request_utc_time");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_UTC_TIME);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_data_conn(struct sockaddr_storage addr) {
+    LOGD("mnl2hal_request_data_conn");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_DATA_CONN);
+    put_binary(buff, &offset, (const char*)&addr, sizeof(addr));
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_release_data_conn() {
+    LOGD("mnl2hal_release_data_conn");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_RELEASE_DATA_CONN);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_ni_notify(int session_id, agps_notify_type type, const char* requestor_id,
+    const char* client_name, ni_encoding_type requestor_id_encoding,
+    ni_encoding_type client_name_encoding) {
+    LOGD("mnl2hal_request_ni_notify");
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_NI_NOTIFY);
+    put_int(buff, &offset, session_id);
+    put_int(buff, &offset, type);
+    put_string(buff, &offset, requestor_id);
+    put_string(buff, &offset, client_name);
+    put_int(buff, &offset, requestor_id_encoding);
+    put_int(buff, &offset, client_name_encoding);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_set_id(request_setid flags) {
+    LOGD("mnl2hal_request_set_id  flag=0x%x", flags);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_SET_ID);
+    put_int(buff, &offset, flags);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_ref_loc(request_refloc flags) {
+    LOGD("mnl2hal_request_ref_loc  flag=0x%x", flags);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_REF_LOC);
+    put_int(buff, &offset, flags);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_vzw_debug_screen_output(const char* str) {
+    LOGD("mnl2hal_vzw_debug_screen_output, str=%s", str);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_VZW_DEBUG_OUTPUT);
+    put_string(buff, &offset, str);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_update_gnss_name(const char* str, int len) {
+    LOGD("mnl2hal_update_gnss_name, str=%s, len=%d", str, len);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_UPDATE_GNSS_NAME);
+    put_int(buff, &offset, len);
+    put_string(buff, &offset, str);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+int mnl2hal_request_nlp(bool type) {
+    LOGD("mnl2hal_request_nlp, type=%d", type);
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, HAL_MNL_INTERFACE_VERSION);
+
+    put_int(buff, &offset, MNL2HAL_REQUEST_NLP);
+    put_byte(buff, &offset, type);
+
+    return safe_sendto(MTK_MNL2HAL, buff, offset);
+}
+
+// -1 means failure
+int hal2mnl_hdlr(int fd, hal2mnl_interface* hdlr) {
+    char buff[HAL_MNL_BUFF_SIZE] = {0};
+    int offset = 0;
+    int ver;
+    hal2mnl_cmd cmd;
+    int read_len;
+    int ret = 0;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("hal2mnl_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+    ver = get_int(buff, &offset, sizeof(buff));
+    UNUSED(ver);
+    cmd = get_int(buff, &offset, sizeof(buff));
+
+    switch (cmd) {
+    case HAL2MNL_HAL_REBOOT: {
+        if (hdlr->hal_reboot) {
+            hdlr->hal_reboot();
+        } else {
+            LOGE("hal_reboot is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_INIT: {
+        if (hdlr->gps_init) {
+            hdlr->gps_init();
+        } else {
+            LOGE("gps_init is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_START: {
+        if (hdlr->gps_start) {
+            hdlr->gps_start();
+        } else {
+            LOGE("gps_start is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_STOP: {
+        if (hdlr->gps_stop) {
+            hdlr->gps_stop();
+        } else {
+            LOGE("gps_stop is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_CLEANUP: {
+        if (hdlr->gps_cleanup) {
+            hdlr->gps_cleanup();
+        } else {
+            LOGE("gps_cleanup is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_INJECT_TIME: {
+        if (hdlr->gps_inject_time) {
+            int64_t time = get_long(buff, &offset, sizeof(buff));
+            int64_t time_reference = get_long(buff, &offset, sizeof(buff));
+            int uncertainty = get_int(buff, &offset, sizeof(buff));
+            hdlr->gps_inject_time(time, time_reference, uncertainty);
+        } else {
+            LOGE("gps_inject_time is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_INJECT_LOCATION: {
+        if (hdlr->gps_inject_location) {
+            double lat = get_double(buff, &offset, sizeof(buff));
+            double lng = get_double(buff, &offset, sizeof(buff));
+            float acc = get_float(buff, &offset, sizeof(buff));
+            hdlr->gps_inject_location(lat, lng, acc);
+        } else {
+            LOGE("gps_inject_location is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_DELETE_AIDING_DATA: {
+        if (hdlr->gps_delete_aiding_data) {
+            int flags = get_int(buff, &offset, sizeof(buff));
+            hdlr->gps_delete_aiding_data(flags);
+        } else {
+            LOGE("gps_delete_aiding_data is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_SET_POSITION_MODE: {
+        if (hdlr->gps_set_position_mode) {
+            gps_pos_mode mode = get_int(buff, &offset, sizeof(buff));
+            gps_pos_recurrence recurrence = get_int(buff, &offset, sizeof(buff));
+            int min_interval = get_int(buff, &offset, sizeof(buff));
+            int preferred_acc = get_int(buff, &offset, sizeof(buff));
+            int preferred_time = get_int(buff, &offset, sizeof(buff));
+            bool lowPowerMode = get_byte(buff, &offset, sizeof(buff));
+            hdlr->gps_set_position_mode(mode, recurrence, min_interval,
+                preferred_acc, preferred_time, lowPowerMode);
+        } else {
+            LOGE("gps_set_position_mode is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_DATA_CONN_OPEN: {
+        if (hdlr->data_conn_open) {
+            char* apn = get_string(buff, &offset, sizeof(buff));
+            hdlr->data_conn_open(apn);
+        } else {
+            LOGE("data_conn_open is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_DATA_CONN_OPEN_WITH_APN_IP_TYPE: {
+        if (hdlr->data_conn_open_with_apn_ip_type) {
+            char* apn = get_string(buff, &offset, sizeof(buff));
+            apn_ip_type ip_type = get_int(buff, &offset, sizeof(buff));
+            hdlr->data_conn_open_with_apn_ip_type(apn, ip_type);
+        } else {
+            LOGE("data_conn_open_with_apn_ip_type is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_DATA_CONN_CLOSED: {
+        if (hdlr->data_conn_closed) {
+            hdlr->data_conn_closed();
+        } else {
+            LOGE("data_conn_closed is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_DATA_CONN_FAILED: {
+        if (hdlr->data_conn_failed) {
+            hdlr->data_conn_failed();
+        } else {
+            LOGE("data_conn_failed is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_SET_SERVER: {
+        if (hdlr->set_server) {
+            agps_type type = get_int(buff, &offset, sizeof(buff));
+            char* hostname = get_string(buff, &offset, sizeof(buff));
+            int port = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_server(type, hostname, port);
+        } else {
+            LOGE("set_server is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_SET_REF_LOCATION: {
+        if (hdlr->set_ref_location) {
+            cell_type type = get_int(buff, &offset, sizeof(buff));
+            int mcc = get_int(buff, &offset, sizeof(buff));
+            int mnc = get_int(buff, &offset, sizeof(buff));
+            int lac = get_int(buff, &offset, sizeof(buff));
+            int cid = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_ref_location(type, mcc, mnc, lac, cid);
+        } else {
+            LOGE("set_ref_location is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_SET_ID: {
+        if (hdlr->set_id) {
+            agps_id_type type = get_int(buff, &offset, sizeof(buff));
+            char* setid = get_string(buff, &offset, sizeof(buff));
+            hdlr->set_id(type, setid);
+        } else {
+            LOGE("set_id is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_NI_MESSAGE: {
+        if (hdlr->ni_message) {
+            char msg[1024] = {0};
+            int len = get_binary(buff, &offset, msg, sizeof(buff), sizeof(msg));
+            hdlr->ni_message(msg, len);
+        } else {
+            LOGE("ni_message is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_NI_RESPOND: {
+        if (hdlr->ni_respond) {
+            int notif_id = get_int(buff, &offset, sizeof(buff));
+            ni_user_response_type user_response  = get_int(buff, &offset, sizeof(buff));
+            hdlr->ni_respond(notif_id, user_response);
+        } else {
+            LOGE("ni_respond is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_UPDATE_NETWORK_STATE: {
+        if (hdlr->update_network_state) {
+            int connected = get_int(buff, &offset, sizeof(buff));
+            network_type type = get_int(buff, &offset, sizeof(buff));
+            int roaming  = get_int(buff, &offset, sizeof(buff));
+            char* extra_info = get_string(buff, &offset, sizeof(buff));
+            hdlr->update_network_state(connected, type, roaming, extra_info);
+        } else {
+            LOGE("update_network_state is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_UPDATE_NETWORK_AVAILABILITY: {
+        if (hdlr->update_network_availability) {
+            int available = get_int(buff, &offset, sizeof(buff));
+            char* apn = get_string(buff, &offset, sizeof(buff));
+            hdlr->update_network_availability(available, apn);
+        } else {
+            LOGE("update_network_availability is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GNSS_CONFIG: {
+    if (hdlr->update_gnss_config) {
+        int length = get_int(buff, &offset, sizeof(buff));
+        char* config_data = get_string(buff, &offset, sizeof(buff));
+        hdlr->update_gnss_config(config_data, length);
+    } else {
+        LOGE("update_gnss_config is NULL");
+        ret = -1;
+    }
+    break;
+    }
+    case HAL2MNL_GPS_MEASUREMENT: {
+        if (hdlr->set_gps_measurement) {
+            bool enabled = get_int(buff, &offset, sizeof(buff));
+            bool enableFullTracking = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_gps_measurement(enabled, enableFullTracking);
+        } else {
+            LOGE("set_gps_measurement is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_GPS_NAVIGATION: {
+        if (hdlr->set_gps_navigation) {
+            bool enabled = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_gps_navigation(enabled);
+        } else {
+            LOGE("set_gps_navigation is NULL");
+            ret = -1;
+        }
+        break;
+    }
+    case HAL2MNL_VZW_DEBUG: {
+        if (hdlr->set_vzw_debug) {
+            bool enabled = get_int(buff, &offset, sizeof(buff));
+            hdlr->set_vzw_debug(enabled);
+        } else {
+            LOGE("set_vzw_debug is NULL");
+            ret = -1;
+        }
+        break;
+    }
+#if defined(__LINUX_OS__)
+    case HAL2MNL_SEND_PMTK: {
+        if (hdlr->send_pmtk) {
+            char msg[MTK_PMTK_CMD_MAX_SIZE] = {0};
+            int len = get_binary(buff, &offset, msg, sizeof(buff), sizeof(msg));
+            hdlr->send_pmtk(msg, len);
+        } else {
+            LOGE("send_pmtk is NULL");
+            ret = -1;
+        }
+        break;
+    }
+#endif
+    default: {
+        LOGE("unknown cmd=%d", cmd);
+        ret = -1;
+        break;
+    }
+    }
+
+    return ret;
+}
+
+// -1 means failure
+int create_hal2mnl_fd() {
+    int fd = socket_bind_udp(MTK_HAL2MNL);
+    socket_set_blocking(fd, 0);
+    return fd;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl_common.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl_common.c
new file mode 100644
index 0000000..2b5c5f0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnl_common.c
@@ -0,0 +1,337 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#define _MNL_COMMON_C_
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <stdio.h>   /* Standard input/output definitions */
+#include <string.h>  /* String function definitions */
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "mnl_common.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnl_linux"
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#define MNL_CONFIG_STATUS "persist.vendor.radio.mnl.prop"
+#endif
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+
+/******************************************************************************
+ * Functions
+******************************************************************************/
+#if defined(READ_PROPERTY_FROM_FILE)
+/******************************************************************************
+Sample for mnl.prop: (for emulator)
+-------------------------------------------------------------------------------
+init.speed=38400
+link.speed=38400
+dev.dsp=/dev/ttyS3
+dev.gps=/dev/gps
+bee.path=/bee
+pmtk.conn=socket
+pmtk.socket.port=7000
+#pmtk.conn=serial
+#pmtk.serial.dev=/dev/ttygserial
+debug.nema=1 (0:none; 1:normal; 2:full)
+debug.mnl=1
+******************************************************************************/
+const char *mnl_prop_path[] = {
+    MTK_GPS_DATA_PATH"mnl.prop",   /*mainly for target*/
+    "/sbin/mnl.prop",   /*mainly for emulator*/
+};
+#define PROPBUF_SIZE 512
+static char propbuf[512];
+extern int epo_setconfig;
+#define IS_SPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+/******************************************************************************
+* Read property from file and overwritting the existing property
+******************************************************************************/
+int get_prop(char *pStr, char** ppKey, char** ppVal) {
+    int len = (int)strlen(pStr);
+    char *end = pStr + len;
+    char *key = NULL, *val = NULL;
+
+    if (!len) {
+        return -1;    // no data
+    }
+    else if (pStr[0] == '#') {   /*ignore comment*/
+        *ppKey = *ppVal = NULL;
+        return 0;
+    } else if (pStr[len-1] != '\n') {
+        if (len >= PROPBUF_SIZE-1) {
+            LOGE("%s: buffer is not enough!!\n", __FUNCTION__);
+            return -1;
+        } else {
+            pStr[len] = '\n';
+        }
+    }
+    key = pStr;
+    while ((*pStr != '=') && (pStr < end)) pStr++;
+    if (pStr >= end) {
+        LOGE("%s: '=' is not found!!\n", __FUNCTION__);
+        return -1;    // format error
+    }
+
+    *pStr++ = '\0';
+    while (IS_SPACE(*pStr) && (pStr < end)) pStr++;    // skip space chars
+    val = pStr;
+    while (!IS_SPACE(*pStr) && (pStr < end)) pStr++;
+    *pStr = '\0';
+    *ppKey = key;
+    *ppVal = val;
+    return 0;
+}
+/*****************************************************************************/
+int set_prop(MNL_CONFIG_T* prConfig, char* key, char* val) {
+    if (!strcmp(key, "init.speed")) {
+        prConfig->init_speed = atoi(val);
+    } else if (!strcmp(key, "link.speed")) {
+        prConfig->link_speed = atoi(val);
+    } else if (!strcmp(key, "dev.dsp")) {
+    if (strlen(val) < sizeof(prConfig->dev_dsp))
+            MNLD_STRNCPY(prConfig->dev_dsp, val, sizeof(prConfig->dev_dsp));
+    } else if (!strcmp(key, "dev.gps")) {
+    if (strlen(val) < sizeof(prConfig->dev_gps))
+        MNLD_STRNCPY(prConfig->dev_gps, val,sizeof(prConfig->dev_gps));
+    } else if (!strcmp(key, "bee.path")) {
+    if (strlen(val) < sizeof(prConfig->bee_path))
+            MNLD_STRNCPY(prConfig->bee_path, val, sizeof(prConfig->bee_path));
+    } else if (!strcmp(key, "pmtk.serial.dev")) {
+    if (strlen(val) < sizeof(prConfig->dev_dbg))
+            MNLD_STRNCPY(prConfig->dev_dbg, val,sizeof(prConfig->dev_dbg));
+    } else if (!strcmp(key, "pmtk.conn")) {
+        if (!strcmp(val, "serial"))
+            prConfig->pmtk_conn = PMTK_CONNECTION_SERIAL;
+        else if (!strcmp(val, "socket"))
+            prConfig->pmtk_conn = PMTK_CONNECTION_SOCKET;
+    }
+    else if (!strcmp(key, "pmtk.serial.port")) {
+        prConfig->socket_port = atoi(val);
+    }
+    else if (!strcmp(key, "debug.debug_nmea")) {
+        /* it will be set to enable_dbg_log */
+        prConfig->debug_nmea = (atoi(val) > 0) ? (1) : (0);
+    } else if (!strcmp(key, "debug.mnl")) {
+        prConfig->debug_mnl  = strtol(val, NULL, 16);
+    } else if (!strcmp(key, "debug.dbg2file")) {
+        prConfig->dbg2file  = atoi(val);
+    } else if (!strcmp(key, "debug.filename")) {
+        MNLD_STRNCPY(prConfig->debug_file_name, val, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+    } else if (!strcmp(key, "timeout.monitor")) {
+        prConfig->timeout_monitor = atoi(val);
+    } else if (!strcmp(key, "timeout.init")) {
+        prConfig->timeout_init = atoi(val);
+    } else if (!strcmp(key, "timeout.sleep")) {
+        prConfig->timeout_sleep = atoi(val);
+    } else if (!strcmp(key, "timeout.pwroff")) {
+        prConfig->timeout_pwroff = atoi(val);
+    } else if (!strcmp(key, "timeout.wakeup")) {
+        prConfig->timeout_wakeup = atoi(val);
+    } else if (!strcmp(key, "timeout.ttff")) {
+        prConfig->timeout_ttff = atoi(val);
+    } else if (!strcmp(key, "delay.reset_dsp")) {
+        prConfig->delay_reset_dsp = atoi(val);
+    } else if (!strcmp(key, "EPO_enabled")) {
+        prConfig->EPO_enabled = atoi(val);
+        epo_setconfig = 1;
+    } else if (!strcmp(key, "BEE_enabled")) {
+        prConfig->BEE_enabled = atoi(val);
+    } else if (!strcmp(key, "SUPL_enabled")) {
+        prConfig->SUPL_enabled = atoi(val);
+    } else if (!strcmp(key, "SUPLSI_enabled")) {
+        prConfig->SUPLSI_enabled = atoi(val);
+    } else if (!strcmp(key, "EPO_priority")) {
+        prConfig->EPO_priority = atoi(val);
+    } else if (!strcmp(key, "BEE_priority")) {
+        prConfig->BEE_priority = atoi(val);
+    } else if (!strcmp(key, "SUPL_priority")) {
+        prConfig->SUPL_priority = atoi(val);
+    } else if (!strcmp(key, "AVAILIABLE_AGE")) {
+        prConfig->AVAILIABLE_AGE = atoi(val);
+    } else if (!strcmp(key, "RTC_DRIFT")) {
+        prConfig->RTC_DRIFT = atoi(val);
+    } else if (!strcmp(key, "TIME_INTERVAL")) {
+        prConfig->TIME_INTERVAL = atoi(val);
+    } else if (!strcmp(key, "TEST_MACHINE")) {
+        prConfig->u1AgpsMachine = atoi(val);
+    } else if (!strcmp(key, "ACC_SNR")) {
+        prConfig->ACCURACY_SNR = atoi(val);
+    } else if (!strcmp(key, "GNSS_MODE")) {
+        prConfig->GNSSOPMode = atoi(val);
+    } else if (!strcmp(key, "DBGLOG_FILE_MAX")) {
+        prConfig->dbglog_file_max_size = atoi(val);
+    } else if (!strcmp(key, "DBGLOG_FOLDER_MAX")) {
+        prConfig->dbglog_folder_max_size = atoi(val);
+    } else if ((!strcmp(key, "OFFLOAD_enabled"))) {
+        prConfig->OFFLOAD_enabled = atoi(val);
+    } else if ((!strcmp(key, "OFFLOAD_testMode"))) {
+        prConfig->OFFLOAD_testMode = atoi(val);
+    } else if ((!strcmp(key, "OFFLOAD_switchMode"))) {
+        prConfig->OFFLOAD_switchMode = atoi(val);
+    } else if ((!strcmp(key, "fix_interval"))) {
+        prConfig->fix_interval = atoi(val);
+    } else if ((!strcmp(key, "pps_mode"))) {
+        prConfig->pps_mode = atoi(val);
+    } else if ((!strcmp(key, "pps_delay"))) {
+        prConfig->pps_delay = atoi(val);
+    } else if ((!strcmp(key, "pps_polarity"))) {
+        prConfig->pps_polarity = atoi(val);
+    } else if ((!strcmp(key, "pps_duty"))) {
+        prConfig->pps_duty = atoi(val);
+    } else if ((!strcmp(key, "elev_mask"))) {
+        prConfig->elev_mask = atoi(val);
+    }
+    return 0;
+}
+/*****************************************************************************/
+int read_prop(MNL_CONFIG_T* prConfig, const char* name) {
+    FILE *fp = fopen(name, "rb");
+    char *key, *val;
+    if (!fp) {
+        LOGD("%s: open %s fail!\n", __FUNCTION__, name);
+        return -1;
+    }
+    while (fgets(propbuf, sizeof(propbuf), fp)) {
+        if (get_prop(propbuf, &key, &val)) {
+            LOGD("%s: Get Property fails!!\n", __FUNCTION__);
+            fclose(fp);
+            return -1;
+        }
+        if (!key || !val)
+            continue;
+        // LOGD("%s: Get Property: '%s' => '%s'\n", __FUNCTION__, key, val);
+        if (set_prop(prConfig, key, val)) {
+            LOGE("%s: Set Property fails!!\n", __FUNCTION__);
+            fclose(fp);
+            return -1;
+        }
+    }
+    fclose(fp);
+    return 0;
+}
+/*****************************************************************************/
+int mnl_utl_load_property(MNL_CONFIG_T* prConfig) {
+    int idx;
+    int cnt = sizeof(mnl_prop_path)/sizeof(mnl_prop_path[0]);
+    int res = 0;
+    epo_setconfig = 0;
+    for (idx = 0; idx < cnt; idx++) {
+        if (!read_prop(prConfig, mnl_prop_path[idx]))
+            break;
+    }
+#if ANDROID_MNLD_PROP_SUPPORT
+    // Add for reading property set by YGPS
+    char result[PROPERTY_VALUE_MAX] = {0};
+    if (property_get(MNL_CONFIG_STATUS, result, NULL)) {
+        prConfig->dbg2file = result[2] - '0';
+#ifdef CONFIG_GPS_MT3303
+        prConfig->dbg2file = result[6] - '0';
+#endif
+        LOGD("dbg2file: %d\n", prConfig->dbg2file);
+        prConfig->debug_nmea = result[3] - '0';
+        LOGD("debug_nmea:%d \n", prConfig->debug_nmea);
+        prConfig->BEE_enabled = result[4] - '0';
+        LOGD("BEE_enabled: %d", prConfig->BEE_enabled);
+        // prConfig->test_mode = result[5] - '0';
+        // LOGD("test_mode: %d", prConfig->test_mode);
+    } else {
+        LOGE("Config is not set yet, ignore");
+    }
+#endif
+    if (idx < cnt)  /* successfully read property from file */  {
+        LOGD("[setting] reading from %s\n", mnl_prop_path[idx]);
+        res = 0;
+    } else {
+        LOGD("[setting] load default value\n");
+        res = -1;
+    }
+    LOGD("dev_dsp/dev_gps : %s %s,init_speed/link_speed: %d %d\n",
+        prConfig->dev_dsp, prConfig->dev_gps,
+        prConfig->init_speed, prConfig->link_speed);
+    LOGD("pmtk_conn/socket_port/dev_dbg : %d %d %s\n",
+        prConfig->pmtk_conn, prConfig->socket_port, prConfig->dev_dbg);
+    LOGD("debug_nmea/debug_mnl: %d 0x%04X,nmea2file/dbg2file: %d/%d\n",
+        prConfig->debug_nmea, prConfig->debug_mnl, prConfig->nmea2file, prConfig->dbg2file);
+    LOGD("time-out: %d %d %d %d %d %d\n", prConfig->timeout_init,
+        prConfig->timeout_monitor, prConfig->timeout_wakeup, prConfig->timeout_ttff,
+        prConfig->timeout_sleep, prConfig->timeout_pwroff);
+    LOGD("EPO_Enabled: %d,BEE_Enabled: %d,SUPL_Enabled: %d,SUPLSI_Enabled: %d\n",
+        prConfig->EPO_enabled, prConfig->BEE_enabled, prConfig->SUPL_enabled, prConfig->SUPLSI_enabled);
+    LOGD("EPO_priority: %d,BEE_priority: %d, SUPL_priority: %d\n",
+        prConfig->EPO_priority, prConfig->BEE_priority, prConfig->SUPL_priority);
+    LOGD("AVAILIABLE_AGE: %d,RTC_DRIFT: %d,TIME_INTERVAL: %d\n",
+        prConfig->AVAILIABLE_AGE, prConfig->RTC_DRIFT, prConfig->TIME_INTERVAL);
+    return res;
+}
+#endif
+
+/*****************************************************************************/
+int str2int(const char*  p, const char*  end) {
+    int   result = 0;
+    int   len    = end - p;
+    int   sign = 1;
+
+    if (*p == '-') {
+        sign = -1;
+        p++;
+        len = end - p;
+    }
+
+    for (; len > 0; len--, p++) {
+        int  c;
+
+        if (p >= end)
+            return -1;
+
+        c = *p - '0';
+        if ((unsigned)c >= 10)
+            return -1;
+
+        result = result*10 + c;
+    }
+    return  sign*result;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld.c
new file mode 100644
index 0000000..295c502
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld.c
@@ -0,0 +1,2944 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>  // struct sockaddr_in
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <inttypes.h>
+
+#include "mnld.h"
+#include "mnld_utile.h"
+#include "mnl_common.h"
+#include "mtk_gps.h"
+#include "agps_agent.h"
+#include "mtk_lbs_utility.h"
+#include "mnl2hal_interface.h"
+#include "mnl2agps_interface.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "epo.h"
+#include "qepo.h"
+#include "mtknav.h"
+#include "op01_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+#include "mtk_flp_main.h"
+#include "mnl_flp_test_interface.h"
+#include "mtk_geofence_main.h"
+#include "gps_dbg_log.h"
+#include "mpe.h"
+#include "mnl_at_interface.h"
+#include "Mnld2NlpUtilsInterface.h"
+#include "mtk_flp_screen_monitor.h"
+#include "Meta2MnldInterface.h"
+#include "Mnld2DebugInterface.h"
+#include "Debug2MnldInterface.h"
+#include "mtk_auto_log.h"
+
+extern int network_count;
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+int log_dbg_level = L_DEBUG;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld"
+#endif
+
+static void mnld_fsm(mnld_gps_event event, int data1, int data2, void* data3);
+
+static mnld_context g_mnld_ctx;
+UINT8 sv_type_agps_set = 0;
+UINT8 sib8_16_enable = 0;
+UINT8 lppe_enable = 0;// if mnl support lppe, use this variable to determin on or off, else, it is invalid
+mnl_agps_agps_settings g_settings_from_agps;
+MTK_GPS_MNL_INFO mtk_gps_mnl_info;// include lib information:vertion and if support lppe
+mnl_agps_gnss_settings g_settings_to_agps = {
+    .gps_satellite_support     = 1,
+    .glonass_satellite_support = 0,
+    .beidou_satellite_support  = 0,
+    .galileo_satellite_support = 0,
+};
+extern int gps_epo_type;
+#if ANDROID_MNLD_PROP_SUPPORT
+extern char chip_id[PROPERTY_VALUE_MAX];
+#else
+extern char chip_id[100];
+#endif
+volatile UINT8 enable_debug2app = DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG;
+
+/*****************************************
+MNLD FSM
+*****************************************/
+static const char* get_mnld_gps_state_str(mnld_gps_state input) {
+    switch (input) {
+    case MNLD_GPS_STATE_IDLE:
+        return "IDLE";
+    case MNLD_GPS_STATE_STARTING:
+        return "STARTING";
+    case MNLD_GPS_STATE_STARTED:
+        return "STARTED";
+    case MNLD_GPS_STATE_STOPPING:
+        return "STOPPING";
+    case MNLD_GPS_STATE_OFL_STARTING:
+        return "OFL_STARTING";
+    case MNLD_GPS_STATE_OFL_STARTED:
+        return "OFL_STARTED";
+    case MNLD_GPS_STATE_OFL_STOPPING:
+        return "OFL_STOPPING";
+    default:
+        break;
+    }
+    return "UNKNOWN";
+}
+
+static const char* get_mnld_gps_event_str(mnld_gps_event input) {
+    switch (input) {
+    case GPS_EVENT_START:
+        return "START";
+    case GPS_EVENT_STOP:
+        return "STOP";
+    case GPS_EVENT_RESET:
+        return "RESET";
+    case GPS_EVENT_START_DONE:
+        return "START_DONE";
+    case GPS_EVENT_STOP_DONE:
+        return "STOP_DONE";
+    case GPS_EVENT_OFFLOAD_START:
+        return "OFFLOAD_START";
+    default:
+        break;
+    }
+    return "UNKNOWN";
+}
+
+static void do_gps_reset_hdlr() {
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    if (agps->need_reset_ack) {
+        agps->need_reset_ack = false;
+        mnl2agps_reset_gps_done();
+    }
+}
+
+static void do_gps_started_hdlr(int si_assist_req) {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    if (hal->need_open_ack) {
+        hal->need_open_ack = false;
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_ENGINE_ON);
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_BEGIN);
+        mnl2agps_gps_open(si_assist_req);
+    }
+
+    if (agps->need_open_ack) {
+        agps->need_open_ack = false;
+        mnl2agps_open_gps_done();
+    }
+
+    if (flp->need_open_ack) {
+        flp->need_open_ack = false;
+        /*add open ack message to flp*/
+        LOGD("MNLD_FLP_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_flp_ofl_gps_open_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_flp_hbd_gps_open_done();
+            }
+        } else { //always host
+            LOGD("HBD auto mode");
+            mnld_flp_hbd_gps_open_done();
+        }
+        mnl2agps_gps_open(si_assist_req);
+    }
+
+    if (geofence->need_open_ack) {
+        geofence->need_open_ack = false;
+        /*add open ack message to gfc*/
+        LOGD("MNLD_GFC_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_gfc_ofl_gps_open_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_gfc_hbd_gps_open_done();
+            }
+        } else { //always host
+            LOGD("HBD auto mode");
+            mnld_gfc_hbd_gps_open_done();
+        }
+        mnl2agps_gps_open(si_assist_req);
+    }
+
+    if (flp_test->need_open_ack) {
+        flp_test->need_open_ack = false;
+        /*add open ack message to flp_test*/
+    }
+
+    if (at_cmd_test->need_open_ack) {
+        at_cmd_test->need_open_ack = false;
+        /*add open ack message to at_cmd_test*/
+    }
+
+    if (factory->need_open_ack) {
+        factory->need_open_ack = false;
+        /*add open ack message to factory*/
+    }
+
+    if (enable_debug2app == DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG) {
+        Mnld2DebugInterface_mnldUpdateGpsStatus(&g_mnld_ctx.fds.fd_debug_client,
+            MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED);
+    }
+
+    do_gps_reset_hdlr();
+
+    if (g_mnld_ctx.gps_status.delete_aiding_flag) {
+        start_timer(g_mnld_ctx.gps_status.timer_reset, MNLD_GPS_RESET_TIMEOUT);
+        gps_control_gps_reset(g_mnld_ctx.gps_status.delete_aiding_flag);
+        g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+    }
+}
+
+static void do_gps_stopped_hdlr() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    if (hal->need_close_ack) {
+        hal->need_close_ack = false;
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_END);
+        mnl2hal_gps_status(MTK_GPS_STATUS_SESSION_ENGINE_OFF);
+        mnl2agps_gps_close();
+    }
+
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    if (agps->need_close_ack) {
+        agps->need_close_ack = false;
+        mnl2agps_close_gps_done();
+    }
+
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    if (flp->need_close_ack) {
+        flp->need_close_ack = false;
+        /* add close ack message to flp*/
+        LOGD("MNLD_FLP_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_flp_ofl_gps_close_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_flp_hbd_gps_close_done();
+            }
+        } else { //always host
+            LOGD("HBD auto mode");
+            mnld_flp_hbd_gps_close_done();
+        }
+    }
+
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    if (geofence->need_close_ack) {
+        geofence->need_close_ack = false;
+        /* add close ack message to geofence*/
+        LOGD("MNLD_GFC_DEBUG:support_auto_switch:%d,offload_auto:%d",mnld_support_auto_switch_mode(),mnld_offload_is_auto_mode());
+        if (mnld_support_auto_switch_mode()) {   //New offload auto switch mode
+            LOGD("Auto switch mode");
+            if (mnld_offload_is_auto_mode()) {
+                LOGD("Offload Auto mode");
+                mnld_gfc_ofl_gps_close_done();
+            } else {
+                LOGD("HBD auto mode");
+                mnld_gfc_hbd_gps_close_done();
+            }
+        } else {
+            LOGD("HBD auto mode");
+            mnld_gfc_hbd_gps_close_done();
+        }
+    }
+
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    if (flp_test->need_close_ack) {
+        flp_test->need_close_ack = false;
+        /* add close ack message to flp_test*/
+    }
+
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    if (at_cmd_test->need_close_ack) {
+        at_cmd_test->need_close_ack = false;
+        /* add close ack message to at_cmd_test*/
+    }
+
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    if (factory->need_close_ack) {
+        factory->need_close_ack = false;
+        /* add close ack message to factory*/
+    }
+    if (enable_debug2app == DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG) {
+        Mnld2DebugInterface_mnldUpdateGpsStatus(&g_mnld_ctx.fds.fd_debug_client,
+            MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STOPPED);
+    }
+    Mnld2NlpUtilsInterface_cancelNlpLocation(&g_mnld_ctx.fds.fd_nlp_utils, NLP_REQUEST_SRC_MNL);
+    #ifdef MTK_ADR_SUPPORT
+    mnl2adr_close_gps_done();
+    #endif
+    do_gps_reset_hdlr();
+}
+
+static bool is_all_gps_client_exit() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    if (hal->gps_used == false && agps->gps_used == false && flp->gps_used == false
+        && flp_test->gps_used == false && at_cmd_test->gps_used == false && factory->gps_used == false
+ && geofence->gps_used == false) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+static bool is_a_gps_client_exist() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    if (hal->gps_used == true || agps->gps_used == true || flp->gps_used == true || flp_test->gps_used == true
+        || at_cmd_test->gps_used == true || factory->gps_used == true || geofence->gps_used == true) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void mtk_gps_clear_gps_user() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+
+    if (hal->gps_used)
+        hal->gps_used = false;
+    if (agps->gps_used)
+        agps->gps_used = false;
+    if (flp->gps_used)
+        flp->gps_used = false;
+    if (flp_test->gps_used)
+        flp_test->gps_used = false;
+    if (geofence->gps_used)
+        geofence->gps_used = false;
+    if (at_cmd_test->gps_used)
+        at_cmd_test->gps_used = false;
+    if (factory->gps_used)
+        factory->gps_used = false;
+}
+int mtk_gps_get_gps_user() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    int gps_user = GPS_USER_UNKNOWN;
+
+    if (hal->gps_used)
+        gps_user |= GPS_USER_APP;
+    if (agps->gps_used)
+        gps_user |= GPS_USER_AGPS;
+    if (flp->gps_used)
+        gps_user |= GPS_USER_FLP;
+    if (flp_test->gps_used)
+        gps_user |= GPS_USER_OFL_TEST;
+    if (geofence->gps_used)
+        gps_user |= GPS_USER_GEOFENCE;
+    if (at_cmd_test->gps_used)
+        gps_user |= GPS_USER_AT_CMD;
+    if (factory->gps_used)
+        gps_user |= GPS_USER_META;
+    return gps_user;
+}
+
+int is_flp_user_exist() {
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    return flp->gps_used;
+}
+
+int is_geofence_user_exist() {
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    return geofence->gps_used;
+}
+
+
+static bool is_all_hbd_gps_client_exit() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    if (hal->gps_used == false && agps->gps_used == false && at_cmd_test->gps_used == false
+        && factory->gps_used == false) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+static bool is_a_hbd_gps_client_exist() {
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    mnld_gps_client* at_cmd_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    if (hal->gps_used == true || agps->gps_used == true || at_cmd_test->gps_used == true
+        || factory->gps_used == true) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+extern int start_time_out;
+extern int nmea_data_time_out;
+static void fsm_gps_state_idle(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGD("fsm_gps_state_idle() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+    switch (event) {
+    case GPS_EVENT_START: {
+        if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+            mnl2hal_request_wakelock();
+        }
+        #if ANDROID_MNLD_PROP_SUPPORT
+        if (get_gps_cmcc_log_enabled()) {
+            op01_log_gps_start();
+        }
+        #else
+        op01_log_gps_start();
+        #endif
+        g_mnld_ctx.gps_status.gps_start_time = get_tick();
+        g_mnld_ctx.gps_status.wait_first_location = true;
+        g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+        int gps_user = mtk_gps_get_gps_user();
+        // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+        if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            LOGE("gps_user: %d, not run MNL start timer\n", gps_user);
+            LOGE("still enable start timer");
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        } else {
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        }
+        gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+        g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        break;
+    }
+    case GPS_EVENT_STOP: {
+        do_gps_stopped_hdlr();
+        break;
+    }
+    case GPS_EVENT_RESET: {
+        do_gps_reset_hdlr();
+        break;
+    }
+    case GPS_EVENT_OFFLOAD_START: {
+        if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+            mnl2hal_request_wakelock();
+        }
+        #if ANDROID_MNLD_PROP_SUPPORT
+        if (get_gps_cmcc_log_enabled()) {
+            op01_log_gps_start();
+        }
+        #else
+        op01_log_gps_start();
+        #endif
+        g_mnld_ctx.gps_status.gps_start_time = get_tick();
+        g_mnld_ctx.gps_status.wait_first_location = true;
+        g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STARTING;
+        int gps_user = mtk_gps_get_gps_user();
+        // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+        if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            LOGE("gps_user: %d, not run MNL start timer\n", gps_user);
+            LOGE("still enable start timer");
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        } else {
+            start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+        }
+        gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+        g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        break;
+    }
+    case GPS_EVENT_START_DONE:
+        // Need fix by MNL,it will send MTK_AGPS_CB_START_REQ to mnld when stopping or started.
+        // LOGE("fsm_gps_state_stopping() unexpected event=%d", event);
+        // break;
+    case GPS_EVENT_STOP_DONE:
+    default: {
+        LOGE("fsm_gps_state_idle() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+static void fsm_gps_state_starting(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGD("data2=%d,data3=%p", data2, data3);
+    switch (event) {
+    case GPS_EVENT_STOP: {
+        // Need to handle starting-stop event for FLP offload like started-stop
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            #if 1
+            LOGE("!NOT! handle starting stop event for offload");
+            #else
+            LOGE("fsm_gps_state_starting, handle starting stop event for offload");
+            do_gps_started_hdlr(0);
+            if (is_all_gps_client_exit()) {
+                g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STOPPING;
+                start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+                gps_control_gps_stop();
+            }
+            #endif
+        }
+        break;
+    }
+    case GPS_EVENT_START:
+    case GPS_EVENT_OFFLOAD_START:
+    case GPS_EVENT_RESET: {
+        // do nothing
+        break;
+    }
+    case GPS_EVENT_START_DONE: {
+        stop_timer(g_mnld_ctx.gps_status.timer_start);
+        do_gps_started_hdlr(data1);
+        if (is_all_gps_client_exit()) {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STOPPING;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        } else {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTED;
+            //Update mtknav and qepo if download finish before start done.
+            if (mtknav_update_flag == true) {
+                mtknav_update_mtknav_file(mtknav_res);
+                mtknav_update_flag = false;
+            }
+            if (qepo_update_flag == true) {
+                qepo_update_quarter_epo_file(qepo_dl_res);
+                qepo_update_flag = false;
+            }
+            if (qepo_BD_update_flag == true) {
+                qepo_update_quarter_epo_bd_file(qepo_bd_dl_res);
+                qepo_BD_update_flag = false;
+            }
+            if (qepo_GA_update_flag == true) {
+                qepo_update_quarter_epo_ga_file(qepo_ga_dl_res);
+                qepo_GA_update_flag = false;
+            }
+            if (is_a_hbd_gps_client_exist() || !(mnld_support_auto_switch_mode())) {
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_MODE;
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_MODE;
+                if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                    mnld_flp_session.id = mnld_flp_gen_new_session();
+                    mnld_flp_session.pre_type = mnld_flp_session.type;
+                    g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                    mnld_flp_session_update();
+                }
+                if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                    mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                    mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                    g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                    mnld_gfc_session_update();
+                }
+            } else {
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_MODE;
+                mnld_flp_session.pre_type = mnld_flp_session.type;
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_MODE;
+                mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                start_timer(g_mnld_ctx.gps_status.timer_switch_ofl_mode, MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT);
+            }
+        }
+        break;
+    }
+    case GPS_EVENT_STOP_DONE:
+    default: {
+        LOGE("fsm_gps_state_starting() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+static void fsm_gps_state_started(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGE("fsm_gps_state_started() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+    switch (event) {
+    case GPS_EVENT_START: {
+        do_gps_started_hdlr(0);
+        break;
+    }
+    case GPS_EVENT_STOP: {
+        if (is_all_gps_client_exit()) {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STOPPING;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            stop_timer(g_mnld_ctx.gps_status.timer_switch_ofl_mode);
+            gps_control_gps_stop();
+        } else {
+            do_gps_stopped_hdlr();
+            if (is_all_hbd_gps_client_exit() && mnld_support_auto_switch_mode()) {
+                start_timer(g_mnld_ctx.gps_status.timer_switch_ofl_mode, MNLD_GPS_SWITCH_OFL_MODE_TIMEOUT);
+            }
+        }
+        break;
+    }
+    case GPS_EVENT_RESET: {
+        if (g_mnld_ctx.gps_status.delete_aiding_flag) {
+            start_timer(g_mnld_ctx.gps_status.timer_reset, MNLD_GPS_RESET_TIMEOUT);
+            gps_control_gps_reset(g_mnld_ctx.gps_status.delete_aiding_flag);
+            g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        }
+        break;
+    }
+    case GPS_EVENT_START_DONE:
+        // MNL restart.
+        if (GPS_USER_APP & mtk_gps_get_gps_user()) {
+            mnl2agps_reaiding_req();
+        }
+        LOGE("fsm_gps_state_started() unexpected event=%d", event);
+        break;
+    case GPS_EVENT_OFFLOAD_START:
+        // Do nothing
+        LOGE("fsm_gps_state_started() unexpected event=%d", event);
+        break;
+    case GPS_EVENT_STOP_DONE:
+    default: {
+        LOGE("fsm_gps_state_started() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+static void fsm_gps_state_stopping(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGE("fsm_gps_state_stopping() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+    switch (event) {
+    case GPS_EVENT_START:
+    case GPS_EVENT_STOP: {
+        // do nothing
+        break;
+    }
+    case GPS_EVENT_RESET: {
+        do_gps_reset_hdlr();
+        break;
+    }
+    case GPS_EVENT_STOP_DONE: {
+        stop_timer(g_mnld_ctx.gps_status.timer_stop);
+        do_gps_stopped_hdlr();
+        if (is_a_gps_client_exist()) {
+            LOGD("OFFLOAD debug: restarting");
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STARTING;
+            int gps_user = mtk_gps_get_gps_user();
+            // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+            if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                LOGE("gps_user: %d\n", gps_user);
+            } else {
+                start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+            }
+            gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+            g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        } else {
+            LOGD("OFFLOAD debug: stop done");
+            if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+                mnl2hal_release_wakelock();
+            }
+            #if ANDROID_MNLD_PROP_SUPPORT
+            if (get_gps_cmcc_log_enabled()) {
+                op01_log_gps_stop();
+            }
+            #else
+            op01_log_gps_stop();
+            #endif
+            g_mnld_ctx.gps_status.gps_stop_time = get_tick();
+            g_mnld_ctx.gps_status.wait_first_location = false;
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_IDLE;
+            LOGD("OFFLOAD debug: update session");
+
+            if(mnld_support_auto_switch_mode()) {
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+                if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                    mnld_flp_session.id = mnld_flp_gen_new_session();
+                    mnld_flp_session.pre_type = mnld_flp_session.type;
+                    g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                    mnld_flp_session_update();
+                }
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+                if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                    mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                    mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                    g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                    mnld_gfc_session_update();
+                }
+            }
+        }
+        break;
+    }
+    case GPS_EVENT_OFFLOAD_START:
+    case GPS_EVENT_START_DONE:
+        // MNL restart.
+        LOGE("fsm_gps_state_stopping() unexpected event=%d", event);
+        break;
+    default: {
+        LOGE("fsm_gps_state_stopping() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+static void fsm_gps_state_ofl_starting(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGD("fsm_gps_state_starting() data2=%d,data3=%p\n", data2, data3);
+    switch (event) {
+    case GPS_EVENT_STOP: {
+        // Need to handle starting-stop event for FLP offload like started-stop
+        if (mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+            #if 1
+            LOGE("fsm_gps_state_starting, !NOT! handle starting stop event for offload");
+            #else
+            LOGE("fsm_gps_state_starting, handle starting stop event for offload");
+            do_gps_started_hdlr(0);
+            if (is_all_gps_client_exit()) {
+                g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_STOPPING;
+                start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+                gps_control_gps_stop();
+            }
+            #endif
+        }
+        break;
+    }
+    case GPS_EVENT_START:
+    case GPS_EVENT_OFFLOAD_START:
+    case GPS_EVENT_RESET: {
+        // do nothing
+        break;
+    }
+    case GPS_EVENT_START_DONE: {
+        stop_timer(g_mnld_ctx.gps_status.timer_start);
+        do_gps_started_hdlr(data1);
+        if (is_all_gps_client_exit() || is_a_hbd_gps_client_exist()) {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STOPPING;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        } else {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STARTED;
+            mnld_flp_session.type = MNLD_FLP_CAPABILITY_OFL_MODE;
+            mnld_gfc_session.type = MNLD_GFC_CAPABILITY_OFL_MODE;
+        }
+        break;
+    }
+    case GPS_EVENT_STOP_DONE:
+    default: {
+        LOGE("fsm_gps_state_starting() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+static void fsm_gps_state_ofl_started(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGE("fsm_gps_state_started() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+    switch (event) {
+    case GPS_EVENT_START: {
+        do_gps_started_hdlr(0);
+        if (is_a_hbd_gps_client_exist()) {
+            //flp
+            g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+            g_mnld_ctx.gps_status.clients.flp.need_open_ack = false;
+            g_mnld_ctx.gps_status.clients.flp.need_close_ack = false;
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STOPPING;
+            //geofence
+            g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+            g_mnld_ctx.gps_status.clients.geofence.need_open_ack = false;
+            g_mnld_ctx.gps_status.clients.geofence.need_close_ack = false;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        }
+        break;
+    }
+    case GPS_EVENT_STOP: {
+        if (is_flp_user_exist() || is_geofence_user_exist()) {
+            do_gps_stopped_hdlr();
+            LOGW("GPS_EVENT_STOP cmd sent by error user!!");
+        } else {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STOPPING;
+            start_timer(g_mnld_ctx.gps_status.timer_stop, MNLD_GPS_STOP_TIMEOUT);
+            gps_control_gps_stop();
+        }
+        break;
+    }
+    case GPS_EVENT_RESET: {
+        //if (g_mnld_ctx.gps_status.delete_aiding_flag) {
+        //    start_timer(g_mnld_ctx.gps_status.timer_reset, MNLD_GPS_RESET_TIMEOUT);
+        //    gps_control_gps_reset(g_mnld_ctx.gps_status.delete_aiding_flag);
+        //    g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        //}
+        break;
+    }
+    case GPS_EVENT_START_DONE:
+        // MNL restart.
+        if (GPS_USER_APP & mtk_gps_get_gps_user()) {
+            mnl2agps_reaiding_req();
+        }
+        LOGE("fsm_gps_state_started() unexpected event=%d", event);
+        break;
+    case GPS_EVENT_OFFLOAD_START:
+        LOGE("fsm_gps_state_started() unexpected event=%d", event);
+        break;
+    case GPS_EVENT_STOP_DONE:
+    default: {
+        LOGE("fsm_gps_state_started() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+static void fsm_gps_state_ofl_stopping(mnld_gps_event event, int data1, int data2, void* data3) {
+    LOGE("fsm_gps_state_stopping() data1=%d,data2=%d,data3=%p\n", data1, data2, data3);
+    switch (event) {
+    case GPS_EVENT_START:
+    case GPS_EVENT_STOP: {
+        // do nothing
+        break;
+    }
+    case GPS_EVENT_RESET: {
+        do_gps_reset_hdlr();
+        break;
+    }
+    case GPS_EVENT_STOP_DONE: {
+        stop_timer(g_mnld_ctx.gps_status.timer_stop);
+        do_gps_stopped_hdlr();
+        if ((is_flp_user_exist() || is_geofence_user_exist()) && is_all_hbd_gps_client_exit()) {
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_OFL_STARTING;
+            int gps_user = mtk_gps_get_gps_user();
+            // if no other users except GPS_USER_FLP or GPS_USER_OFL_TEST, bypass restart
+            if (((gps_user & (GPS_USER_FLP | GPS_USER_OFL_TEST| GPS_USER_GEOFENCE)) == gps_user) && mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode())) {
+                LOGE("gps_user: %d\n", gps_user);
+            } else {
+                start_timer(g_mnld_ctx.gps_status.timer_start, start_time_out);
+            }
+            gps_control_gps_start(g_mnld_ctx.gps_status.delete_aiding_flag);
+            g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+        } else {
+            if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+                mnl2hal_release_wakelock();
+            }
+            #if ANDROID_MNLD_PROP_SUPPORT
+            if (get_gps_cmcc_log_enabled()) {
+                op01_log_gps_stop();
+            }
+            #else
+            op01_log_gps_stop();
+            #endif
+            g_mnld_ctx.gps_status.gps_stop_time = get_tick();
+            g_mnld_ctx.gps_status.wait_first_location = false;
+            g_mnld_ctx.gps_status.gps_state = MNLD_GPS_STATE_IDLE;
+
+            if (is_a_hbd_gps_client_exist()) {  //some hbd user exist, must switch to AP mode and start gps
+                mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_MODE;
+                if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                    mnld_flp_session.id = mnld_flp_gen_new_session();
+                    mnld_flp_session.pre_type = mnld_flp_session.type;
+                    g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                    mnld_flp_session_update();
+                }
+                mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_MODE;
+                if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                    mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                    mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                    g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                    mnld_gfc_session_update();
+                }
+                mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+            } else {   // flp user exit normally and no user exist, so switch to idle state directly
+                if(mnld_support_auto_switch_mode()) {
+                    mnld_flp_session.type = MNLD_FLP_CAPABILITY_AP_OFL_MODE;
+                    if (mnld_flp_session.type != mnld_flp_session.pre_type) {
+                        mnld_flp_session.id = mnld_flp_gen_new_session();
+                        mnld_flp_session.pre_type = mnld_flp_session.type;
+                        g_mnld_ctx.gps_status.clients.flp.gps_used = false;
+                        mnld_flp_session_update();
+                    }
+                    mnld_gfc_session.type = MNLD_GFC_CAPABILITY_AP_OFL_MODE;
+                    if (mnld_gfc_session.type != mnld_gfc_session.pre_type) {
+                        mnld_gfc_session.id = mnld_gfc_gen_new_session();
+                        mnld_gfc_session.pre_type = mnld_gfc_session.type;
+                        g_mnld_ctx.gps_status.clients.geofence.gps_used = false;
+                        mnld_gfc_session_update();
+                    }
+                }
+            }
+        }
+        break;
+    }
+    case GPS_EVENT_OFFLOAD_START:
+    case GPS_EVENT_START_DONE:
+        // MNL restart.
+        LOGE("fsm_gps_state_stopping() unexpected event=%d", event);
+        break;
+    default: {
+        LOGE("fsm_gps_state_stopping() unexpected gps_event=%d", event);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+int mnld_gps_controller_mnl_nmea_timeout(void) {
+    if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+        // stop_timer(g_mnld_ctx.gps_status.timer_nmea_monitor);
+        start_timer(g_mnld_ctx.gps_status.timer_nmea_monitor, nmea_data_time_out);
+    }
+    return 0;
+}
+
+int mnld_gps_start_nmea_monitor() {
+    if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+        start_timer(g_mnld_ctx.gps_status.timer_nmea_monitor, nmea_data_time_out);
+    }
+    return 0;
+}
+
+int mnld_gps_stop_nmea_monitor() {
+    if (g_mnld_ctx.gps_status.timer_nmea_monitor != 0) {
+        stop_timer(g_mnld_ctx.gps_status.timer_nmea_monitor);
+    }
+    return 0;
+}
+
+static int mnld_fsm_offload_old_user = 0;
+static int mnld_fsm_offload_lp_mode = 0;
+static int mnld_fsm_offload_fwk_wakelock = 0;
+static void mnld_fsm(mnld_gps_event event, int data1, int data2, void* data3) {
+    mnld_gps_state gps_state = g_mnld_ctx.gps_status.gps_state;
+
+    if (!(mnl_offload_is_enabled() &&
+            (mnld_offload_is_auto_mode() || mnld_offload_is_always_on_mode()))) {
+        LOGD("mnld_fsm() state=[%s] event=[%s]",
+            get_mnld_gps_state_str(gps_state), get_mnld_gps_event_str(event));
+    } else {
+        // Wakelock control for FLP offload user
+        int user_bitmap;
+        user_bitmap = mtk_gps_get_gps_user();
+        LOGD("mnld_fsm() state=[%s] event=[%s], user=0x%08x, old user=0x%08x",
+            get_mnld_gps_state_str(gps_state), get_mnld_gps_event_str(event),
+            user_bitmap, mnld_fsm_offload_old_user);
+
+        // Libmnl.so need to know once the users changed, then
+        // it can notify connsys to enter low power mode or NMEA mode
+        mtk_gps_ofl_set_user(user_bitmap);
+
+        // If only FLP offload user or No user, should stop nmea timer
+        if ((user_bitmap & (GPS_USER_FLP | GPS_USER_OFL_TEST | GPS_USER_GEOFENCE)) == user_bitmap) {
+            if (!mnld_fsm_offload_lp_mode) {
+                LOGD("mnld_fsm() enter offload lp mode");
+                mnld_gps_stop_nmea_monitor();
+                gps_control_kernel_wakelock_give();
+                if (mnld_fsm_offload_fwk_wakelock) {
+                    mnl2hal_release_wakelock();
+                    mnld_fsm_offload_fwk_wakelock = 0;
+                }
+                mnld_fsm_offload_lp_mode = 1;
+            }
+        } else {
+            if (mnld_fsm_offload_lp_mode) {
+                LOGD("mnld_fsm() leave offload lp mode");
+                mnl2hal_request_wakelock();
+                gps_control_kernel_wakelock_take();
+                mnld_gps_start_nmea_monitor();
+                mnld_fsm_offload_lp_mode = 0;
+                mnld_fsm_offload_fwk_wakelock = 1;
+            }
+        }
+        mnld_fsm_offload_old_user = user_bitmap;
+    }
+
+    switch (gps_state) {
+    case MNLD_GPS_STATE_IDLE: {
+        fsm_gps_state_idle(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_STARTING: {
+        fsm_gps_state_starting(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_STARTED: {
+        fsm_gps_state_started(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_STOPPING: {
+        fsm_gps_state_stopping(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_OFL_STARTING: {
+        fsm_gps_state_ofl_starting(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_OFL_STARTED: {
+        fsm_gps_state_ofl_started(event, data1, data2, data3);
+        break;
+    }
+    case MNLD_GPS_STATE_OFL_STOPPING: {
+        fsm_gps_state_ofl_stopping(event, data1, data2, data3);
+        break;
+    }
+    default: {
+        LOGE("mnld_fsm() unexpected gps_state=%d", gps_state);
+        CRASH_TO_DEBUG();
+        break;
+    }
+    }
+}
+
+/*****************************************
+HAL -> MNL
+*****************************************/
+static void hal_reboot() {
+    LOGW("hal_reboot");
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    hal->gps_used = false;
+    hal->need_open_ack = false;
+    hal->need_close_ack = false;
+    hal->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSREBOOT);
+#endif    
+}
+
+static void hal_gps_init() {
+    LOGW("hal_gps_init");
+    g_mnld_ctx.gps_status.is_gps_init = true;
+    mnl2agps_gps_init();
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSENABLE);
+#endif
+}
+
+static void hal_gps_start() {
+    LOGI("hal_gps_start");
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    hal->gps_used = true;
+    hal->need_open_ack = true;
+    hal->need_close_ack = false;
+    hal_start_gps_trigger_epo_download();
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSSTART);
+#endif
+}
+
+static void hal_gps_stop() {
+    LOGI("hal_gps_stop");
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    hal->gps_used = false;
+    hal->need_open_ack = false;
+    hal->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSSTOP);
+#endif
+}
+
+static void hal_gps_cleanup() {
+    LOGI("hal_gps_cleanup");
+    g_mnld_ctx.gps_status.is_gps_init = false;
+    mnl2agps_gps_cleanup();
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GPSDISABLE);
+#endif
+}
+
+static void hal_gps_inject_time(int64_t time, int64_t time_reference, int uncertainty) {
+    LOGD("hal_gps_inject_time  time=%"PRId64" time_reference=%"PRId64" uncertainty=%d",
+        time, time_reference, uncertainty);
+    // TODO libmnl.so
+    ntp_context  ntp_inject;
+
+    memset(&ntp_inject, 0, sizeof(ntp_context));
+    ntp_inject.time = time;
+    ntp_inject.timeReference = time_reference;
+    ntp_inject.uncertainty = uncertainty;
+    if (mnld_is_gps_started_done()) {
+#ifndef CONFIG_GPS_MT3303
+        mtk_gps_inject_ntp_time((MTK_GPS_NTP_T*)&ntp_inject);
+#else
+        mt3333_controller_inject_time(time, time_reference, uncertainty);
+#endif
+    }
+}
+
+static void hal_gps_inject_location(double lat, double lng, float acc) {
+    int ret = 0;
+    MTK_GPS_NLP_T nlp_inject;
+    nlp_context context;
+    bool alt_valid = false;
+    float altitude = 0.0f;
+    bool source_valid = true;
+    bool source_gnss = false;
+    bool source_nlp = true;
+    bool source_sensor = false;
+
+    // LOGW("lat=%f lng=%f acc=%f", lat, lng, acc);
+    memset(&nlp_inject, 0, sizeof(MTK_GPS_NLP_T));
+    memset(&context, 0, sizeof(nlp_context));
+    if (clock_gettime(CLOCK_MONOTONIC , &context.ts) == -1) {
+        LOGE("clock_gettime failed reason=[%s]\n", strerror(errno));
+        return;
+    }
+    nlp_inject.accuracy = acc;
+    nlp_inject.lattidude = lat;
+    nlp_inject.longitude = lng;
+    nlp_inject.timeReference[0] = (UINT32)context.ts.tv_sec;
+    nlp_inject.timeReference[1] = (UINT32)context.ts.tv_nsec;
+    nlp_inject.started = mnld_is_gps_started_done();
+    nlp_inject.type = 0;
+    if (mnld_is_gps_started_done()) {
+#ifndef CONFIG_GPS_MT3303
+        mtk_gps_inject_nlp_location(&nlp_inject);
+#else
+        mt3333_controller_inject_location(lat, lng, acc);
+#endif
+    }
+    ret = mnl2agps_location_sync(lat, lng, acc, alt_valid, altitude, source_valid, source_gnss, source_nlp, source_sensor);
+    LOGD("ret = %d\n", ret);
+    if (0 == ret) {
+        LOGD("mnl2agps_location_sync success\n");
+    }
+}
+
+static void hal_gps_delete_aiding_data(int flags) {
+    LOGW("hal_gps_delete_aiding_data  flags=0x%x", flags);
+    mnl2agps_delete_aiding_data(flags);
+    mnld_gps_client* hal = &g_mnld_ctx.gps_status.clients.hal;
+    hal->need_reset_ack = false;    // HAL no need the ACK
+    g_mnld_ctx.gps_status.delete_aiding_flag |= flags;
+    mnld_fsm(GPS_EVENT_RESET, 0, 0, NULL);
+#ifdef CONFIG_GPS_MT3303
+    extern int is_ygps_delete_data ;
+    if(g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_IDLE){
+        is_ygps_delete_data = 1;    
+        
+         if (flags == GPS_DELETE_RTI){
+             g_mnld_ctx.gps_status.delete_aiding_flag = 0;
+            is_ygps_delete_data = 0;
+         }
+    }
+#endif    
+}
+
+static void hal_gps_set_position_mode(gps_pos_mode mode, gps_pos_recurrence recurrence,
+        int min_interval, int preferred_acc, int preferred_time, bool lowPowerMode) {
+    LOGD("hal_gps_set_position_mode  mode=%d recurrence=%d min_interval=%d preferred_acc=%d preferred_time=%d lowPowerMode=%d",
+        mode, recurrence, min_interval, preferred_acc, preferred_time, lowPowerMode);
+    mnl2agps_set_position_mode(mode);
+}
+
+static void hal_data_conn_open(const char* apn) {
+    LOGD("hal_data_conn_open  apn=[%s]", apn);
+    mnl2agps_data_conn_open(apn);
+}
+
+static void hal_data_conn_open_with_apn_ip_type(const char* apn, apn_ip_type ip_type) {
+    LOGD("hal_data_conn_open_with_apn_ip_type  apn=[%s] ip_type=%d", apn, ip_type);
+    mnl2agps_data_conn_open_ip_type(apn, ip_type);
+}
+
+static void hal_data_conn_closed() {
+    LOGD("hal_data_conn_closed");
+    mnl2agps_data_conn_closed();
+}
+
+static void hal_data_conn_failed() {
+    LOGD("hal_data_conn_failed");
+    mnl2agps_data_conn_failed();
+}
+
+static void hal_set_server(agps_type type, const char* hostname, int port) {
+    LOGD("hal_set_server  type=%d hostname=[%s] port=%d", type, hostname, port);
+    mnl2agps_set_server(type, hostname, port);
+}
+
+static void hal_set_ref_location(cell_type type, int mcc, int mnc, int lac, int cid) {
+    LOGD("hal_set_ref_location  type=%d mcc=%d mnc=%d lac=%d cid=%d", type, mcc, mnc, lac, cid);
+    mnl2agps_set_ref_loc(type, mcc, mnc, lac, cid);
+}
+
+static void hal_set_id(agps_id_type type, const char* setid) {
+    LOGD("hal_set_id  type=%d setid=[%s]", type, setid);
+    mnl2agps_set_set_id(type, setid);
+}
+
+static void hal_ni_message(char* msg, int len) {
+    LOGD("hal_ni_message, len=%d", len);
+    mnl2agps_ni_message(msg, len);
+}
+
+#if defined(__LINUX_OS__)
+static void hal_send_pmtk(const char* msg, int len) {
+    LOGD("hal_send_pmtk");
+
+    if(len < MTK_PMTK_CMD_MAX_SIZE)
+    {
+        gps_controller_rcv_pmtk(msg);
+    }else{
+        LOGW("len over spec:%d\r\n",len);
+    }
+}
+#endif
+
+static void hal_ni_respond(int notif_id, ni_user_response_type user_response) {
+    LOGD("hal_ni_respond  notif_id=%d user_response=%d", notif_id, user_response);
+    mnl2agps_ni_respond(notif_id, user_response);
+}
+
+static void hal_update_network_state(int connected, network_type type, int roaming,
+        const char* extra_info) {
+    LOGD("hal_update_network_state  connected=%d type=%d roaming=%d extra_info=[%s]",
+        connected, type, roaming, extra_info);
+    mnl2agps_update_network_state(connected, type, roaming, extra_info);
+    mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+
+    if (connected == 1) {
+        network_count++;
+    } else if (connected == 0) {
+        network_count--;
+        if (network_count < 0) {
+            network_count = 0;
+        }
+    }
+    LOGD("hal_update_network_state network_count=%d", network_count);
+
+    epo_status->is_network_connected = connected;
+    if (type == NETWORK_TYPE_WIFI) {
+        epo_status->is_wifi_connected = connected;
+    } else {
+        epo_status->is_wifi_connected = false;
+    }
+
+    if (mnld_is_gps_or_ofl_started()) {
+        epo_read_cust_config();
+        if (connected && epo_status->is_epo_downloading == false &&
+            epo_downloader_is_file_invalid() && epo_is_epo_download_enabled()) {
+            epo_status->is_epo_downloading = true;
+            epo_downloader_start();
+        }
+    } else if (type == NETWORK_TYPE_WIFI) {
+        epo_read_cust_config();
+        if (connected && epo_status->is_epo_downloading == false && epo_is_wifi_trigger_enabled() &&
+            epo_downloader_is_file_invalid() && epo_is_epo_download_enabled()) {
+            epo_status->is_epo_downloading = true;
+            epo_downloader_start();
+        }
+    }
+}
+
+void hal_start_gps_trigger_epo_download() {
+    mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+    LOGD("is_network_connected=%d,is_epo_downloading=%d",
+      epo_status->is_network_connected, epo_status->is_epo_downloading);
+    epo_read_cust_config();
+    if (epo_status->is_epo_downloading == false
+        && epo_downloader_is_file_invalid() && epo_is_epo_download_enabled()) {
+        epo_status->is_epo_downloading = true;
+        epo_downloader_start();
+    }
+}
+
+bool is_network_connected() {
+    mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+    return epo_status->is_network_connected;
+}
+
+bool is_wifi_network_connected() {
+    mnl_epo_status* epo_status = &g_mnld_ctx.epo_status;
+    return epo_status->is_wifi_connected;
+}
+
+static void hal_update_network_availability(int available, const char* apn) {
+    LOGD("available=%d apn=[%s]", available, apn);
+    mnl2agps_update_network_availability(available, apn);
+}
+
+static void hal_set_gps_measurement(bool enabled, bool enableFullTracking) {
+    LOGD("enabled=%d, flag=%d", enabled, enableFullTracking);
+    g_mnld_ctx.gps_status.is_gps_meas_enabled = enabled;
+    // TODO: set parameter to MNL
+}
+
+static void hal_set_gps_navigation(bool enabled) {
+    LOGD("enabled=%d", enabled);
+    g_mnld_ctx.gps_status.is_gps_navi_enabled = enabled;
+}
+
+static void hal_set_vzw_debug(bool enabled) {
+    LOGD("enabled=%d", enabled);
+    mnl2agps_vzw_debug_screen_enable(enabled);
+}
+
+static void hal_update_gnss_config(const char* config_data, int length) {
+    int ret = mnl2agps_update_configuration(config_data, length);
+    LOGD("length=%d, ret=%d", length, ret);
+}
+
+static hal2mnl_interface g_hal2mnl_interface = {
+    hal_reboot,
+    hal_gps_init,
+    hal_gps_start,
+    hal_gps_stop,
+    hal_gps_cleanup,
+    hal_gps_inject_time,
+    hal_gps_inject_location,
+    hal_gps_delete_aiding_data,
+    hal_gps_set_position_mode,
+    hal_data_conn_open,
+    hal_data_conn_open_with_apn_ip_type,
+    hal_data_conn_closed,
+    hal_data_conn_failed,
+    hal_set_server,
+    hal_set_ref_location,
+    hal_set_id,
+    hal_ni_message,
+    hal_ni_respond,
+    hal_update_network_state,
+    hal_update_network_availability,
+    hal_set_gps_measurement,
+    hal_set_gps_navigation,
+    hal_set_vzw_debug,
+    hal_update_gnss_config,
+#if defined(__LINUX_OS__)
+    hal_send_pmtk,
+#endif
+};
+
+/*****************************************
+AGPSD -> MNL
+*****************************************/
+#ifdef MTK_AGPS_SUPPORT
+static void agps_reboot() {
+    LOGW("agps_reboot");
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    agps->gps_used = false;
+    agps->need_open_ack = false;
+    agps->need_close_ack = false;
+    agps->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void agps_open_gps_req(int show_gps_icon) {
+    LOGW("agps_open_gps_req  show_gps_icon=%d", show_gps_icon);
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    agps->gps_used = true;
+    agps->need_open_ack = true;
+    agps->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void agps_close_gps_req() {
+    LOGW("agps_close_gps_req");
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    agps->gps_used = false;
+    agps->need_open_ack = false;
+    agps->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void agps_reset_gps_req(int flags) {
+    LOGW("agps_reset_gps_req  flags=0x%x", flags);
+    if (flags == 0) {
+        mnl2agps_reset_gps_done();
+        return;
+    }
+    g_mnld_ctx.gps_status.delete_aiding_flag |= flags;
+    mnld_gps_client* agps = &g_mnld_ctx.gps_status.clients.agps;
+    agps->need_reset_ack = true;
+    mnld_fsm(GPS_EVENT_RESET, 0, 0, NULL);
+}
+
+static void agps_session_done() {
+    LOGW("agps_session_done");
+    // TODO libmnl.so
+    gps_controller_agps_session_done();
+}
+
+static void agps_ni_notify(int session_id, mnl_agps_notify_type type,
+      const char* requestor_id, const char* client_name) {
+    LOGD("agps_ni_notify  session_id=%d type=%d requestor_id=[%s] client_name=[%s]",
+        session_id, type, requestor_id, client_name);
+    int usc2_len;
+    char ucs2_buff[1024];
+    char requestorId[1024] = {0};
+    char clientName[1024] = {0};
+
+    memset(ucs2_buff, 0, sizeof(ucs2_buff));
+    usc2_len = asc_str_to_usc2_str(ucs2_buff, requestor_id);
+    raw_data_to_hex_string(requestorId, ucs2_buff, usc2_len);
+
+    memset(ucs2_buff, 0, sizeof(ucs2_buff));
+    usc2_len = asc_str_to_usc2_str(ucs2_buff, client_name);
+    raw_data_to_hex_string(clientName, ucs2_buff, usc2_len);
+
+    mnl2hal_request_ni_notify(session_id, type, requestorId, clientName,
+        NI_ENCODING_TYPE_UCS2, NI_ENCODING_TYPE_UCS2);
+}
+
+static void agps_data_conn_req(int ipaddr, int is_emergency) {
+    LOGD("agps_data_conn_req  ipaddr=0x%x is_emergency=%d", ipaddr, is_emergency);
+    UNUSED(is_emergency);
+    struct sockaddr_storage addr;
+    memset(&addr, 0, sizeof(addr));
+    struct sockaddr_in *in = (struct sockaddr_in*)&addr;
+    addr.ss_family = AF_INET;
+    in->sin_addr.s_addr = ipaddr;
+    mnl2hal_request_data_conn(addr);
+}
+
+static void agps_data_conn_release() {
+    LOGD("agps_data_conn_release");
+    mnl2hal_release_data_conn();
+}
+
+static void agps_set_id_req(int flags) {
+    LOGD("agps_set_id_req  flags=%d", flags);
+    mnl2hal_request_set_id(flags);
+}
+
+static void agps_ref_loc_req(int flags) {
+    LOGD("agps_ref_loc_req  flags=%d", flags);
+    mnl2hal_request_ref_loc(flags);
+}
+
+static void agps_rcv_pmtk(const char* pmtk) {
+    // LOGD("agps_rcv_pmtk  pmtk=%s", pmtk);
+    // TODO libmnl.so
+    gps_controller_rcv_pmtk(pmtk);
+}
+
+static void agps_gpevt(gpevt_type type) {
+    LOGD("agps_gpevt  type=%d", type);
+    UNUSED(type);
+}
+static void agps_rcv_lppe_common_iono(const char* data, int len)
+{
+    LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_IONO, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+          gnss_ha_assist_ack_struct ack;
+          memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+          ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_IONO;
+          mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+}
+static void agps_rcv_lppe_common_trop(const char* data, int len)
+{
+    LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_TROP, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+         gnss_ha_assist_ack_struct ack;
+         memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+         ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_TROP;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_rcv_lppe_common_alt(const char* data, int len)
+{
+    LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_ALT, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+         gnss_ha_assist_ack_struct ack;
+         memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+         ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_ALT;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_rcv_lppe_common_solar(const char* data, int len)
+{
+     LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_SOLAR, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+         gnss_ha_assist_ack_struct ack;
+         memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+         ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_SOLAR;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_rcv_lppe_common_ccp(const char* data, int len)
+{
+    LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_COMMON_CCP, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+         gnss_ha_assist_ack_struct ack;
+         memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+         ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_COMMON_CCP;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_rcv_lppe_generic_ccp(const char* data, int len)
+{
+    LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_CCP, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+         gnss_ha_assist_ack_struct ack;
+         memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+         ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_CCP;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_rcv_lppe_generic_dm(const char* data, int len)
+{
+    LOGD("rcv_lppe_data\n");
+    if (mnld_is_gps_and_ofl_stopped()) {
+        LOGD("rcv_lppe_data: MNL stopped, return");
+        return;
+    }
+    int ret = mtk_agps_set_param_with_payload_len(MTK_MSG_AGPS_MSG_SUPL_LPPE_ASSIST_GENERIC_DM, data, MTK_MOD_DISPATCHER, MTK_MOD_AGENT,len);
+    if (ret != 0) {
+        LOGD("mtk_agps_set_param fail, MTK_MSG_AGPS_MSG_SUPL_LPPE\n");
+    }else{
+         gnss_ha_assist_ack_struct ack;
+         memset((char*)(&ack),0x0,sizeof(gnss_ha_assist_ack_struct));
+         ack.type=AGPS_MD_HUGE_DATA_TYPE_LPPE_AGNSS_PROVIDE_ASSIST_DATA_GENERIC_DM;
+         mnl2agps_lppe_assist_data_provide_ack((char*)(&ack), sizeof(gnss_ha_assist_ack_struct));
+    }
+
+}
+static void agps_location(mnl_agps_agps_location* location) {
+    if (mtk_gps_log_is_hide() == 0) {
+        LOGD("agps_location  lat,lng %f,%f acc=%f used=%d",
+            location->latitude, location->longitude, location->accuracy, location->accuracy_used);
+    }
+
+    gps_location loc;
+    memset(&loc, 0, sizeof(loc));
+    loc.flags |= MTK_GPS_LOCATION_HAS_LAT_LONG;
+    loc.lat = location->latitude;
+    loc.lng = location->longitude;
+    if (location->altitude_used) {
+        loc.flags |= MTK_GPS_LOCATION_HAS_ALT;
+        loc.alt = location->altitude;
+    }
+    if (location->speed_used) {
+        loc.flags |= MTK_GPS_LOCATION_HAS_SPEED;
+        loc.speed = location->speed;
+    }
+    if (location->bearing_used) {
+        loc.flags |= MTK_GPS_LOCATION_HAS_BEARING;
+        loc.bearing = location->bearing;
+    }
+    if (location->accuracy_used) {
+        loc.flags |= MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+        loc.h_accuracy = location->accuracy;
+    }
+    if (location->timestamp_used) {
+        loc.timestamp = location->timestamp;
+    }
+    mnl2hal_location(loc);
+    MTK_GPS_NLP_T c2k_cell_location;
+    nlp_context context;
+    memset(&c2k_cell_location, 0, sizeof(MTK_GPS_NLP_T));
+    memset(&context, 0, sizeof(nlp_context));
+    if (clock_gettime(CLOCK_MONOTONIC , &context.ts) == -1) {
+        LOGE("clock_gettime failed reason=[%s]\n", strerror(errno));
+        return;
+    }
+    LOGD("ts.tv_sec = %ld, ts.tv_nsec = %ld\n",
+        context.ts.tv_sec, context.ts.tv_nsec);
+
+    c2k_cell_location.lattidude = location->latitude;
+    c2k_cell_location.longitude = location->longitude;
+    c2k_cell_location.accuracy = location->accuracy;
+    c2k_cell_location.timeReference[0] = (UINT32)context.ts.tv_sec;
+    c2k_cell_location.timeReference[1] = (UINT32)context.ts.tv_nsec;
+    c2k_cell_location.type = 0;
+    c2k_cell_location.started = 1;
+    if (mtk_gps_log_is_hide() == 0) {
+        LOGD("inject cell location lati= %f, longi = %f, accuracy = %f\n",
+            c2k_cell_location.lattidude, c2k_cell_location.longitude, c2k_cell_location.accuracy);
+    }
+    if (mnld_is_gps_started_done()) {
+        mtk_gps_inject_nlp_location(&c2k_cell_location);
+    }
+}
+
+static void agps_ni_notify2(int session_id,
+    mnl_agps_notify_type type, const char* requestor_id, const char* client_name,
+    mnl_agps_ni_encoding_type requestor_id_encoding,
+    mnl_agps_ni_encoding_type client_name_encoding) {
+    LOGD("agps_ni_notify2  session_id=%d type=%d requestor_id_encoding=%d client_name_encoding=%d",
+        session_id, type, requestor_id_encoding, client_name_encoding);
+    mnl2hal_request_ni_notify(session_id, type, requestor_id, client_name, requestor_id_encoding, client_name_encoding);
+}
+
+static void agps_data_conn_req2(struct sockaddr_storage* addr, int is_emergency) {
+    LOGD("agps_data_conn_req2  is_emergency=%d", is_emergency);
+    UNUSED(is_emergency);
+    mnl2hal_request_data_conn(*addr);
+}
+#endif
+
+static int get_agnss_capability(const UINT8 sv_type_agps_set, const UINT8 sv_type, char *pmtk_str) {
+    char tmp[64]={0};
+    int agps_cap = 0;
+    int aglonass_cap = 0;
+    int abeidou_cap = 0;
+    int agalileo_cap = 0;
+    int gnss_num = 0;
+
+    // Axxx Enable. with HW support condition
+    if (((sv_type_agps_set & 0x21) == 0x21) && ((sv_type & 0x01) == 0x01)) {
+        agps_cap = 1;
+    }
+    if (((sv_type_agps_set & 0x12) == 0x12) && ((sv_type & 0x02) == 0x02)) {
+        aglonass_cap = 1;
+    }
+    if (((sv_type_agps_set & 0x44) == 0x44) && ((sv_type & 0x04) == 0x04)) {
+        abeidou_cap = 1;
+    }
+    if (((sv_type_agps_set & 0x88) == 0x88) && ((sv_type & 0x08) == 0x08)) {
+        agalileo_cap = 1;
+    }
+    gnss_num = agps_cap + aglonass_cap + abeidou_cap + agalileo_cap;
+
+    sprintf(pmtk_str, "$PMTK764,0,0,0");
+    sprintf(tmp, ",%d", gnss_num);
+    strncat(pmtk_str, tmp, PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+
+    if (agps_cap) {
+        strncat(pmtk_str, ",0,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+    }
+    if (agalileo_cap) {
+        strncat(pmtk_str, ",3,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+    }
+    if (aglonass_cap) {
+        strncat(pmtk_str, ",4,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+    }
+    if (abeidou_cap) {
+        strncat(pmtk_str, ",5,128", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+    }
+    if (lppe_enable){
+        strncat(pmtk_str, ",1", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+        }else{
+          strncat(pmtk_str, ",0", PMTK_MAX_PKT_LENGTH - strlen(pmtk_str));
+      }
+    add_chksum(pmtk_str);
+    LOGD("MNLD_PMTK764: %s, agps_cap:%d, aglonass_cap:%d, abeidou_cap:%d, agalileo_cap:%d, lppe_support:%d\n",
+        pmtk_str, agps_cap, aglonass_cap, abeidou_cap, agalileo_cap, lppe_enable);
+    return 0;
+}
+
+void agps_settings_sync(mnl_agps_agps_settings* s) {
+    UINT8 sv_type;
+    int ret;
+
+    char pmtk_str[PMTK_MAX_PKT_LENGTH];
+    memset(pmtk_str, 0, sizeof(pmtk_str));
+
+    LOGD("agps setting, sib8_16_enable = %d, gps_sat_en = %d, glonass_sat_en = %d, \
+        beidou_sat_en = %d, galileo_sat_en = %d, a_glonass_sat_en = %d, \
+        a_gps_satellite_enable = %d, a_beidou_satellite_enable = %d, a_galileo_satellite_enable = %d, lppe_enable=%d\n",
+        s->sib8_16_enable,
+        s->gps_satellite_enable, s->glonass_satellite_enable,
+        s->beidou_satellite_enable, s->galileo_satellite_enable,
+        s->a_glonass_satellite_enable, s->a_gps_satellite_enable,
+        s->a_beidou_satellite_enable, s->a_galileo_satellite_enable,
+        s->lppe_enable);
+    g_settings_from_agps = *s;
+
+    sv_type_agps_set = 0;
+    sv_type_agps_set |= (g_settings_from_agps.a_galileo_satellite_enable & 0x01) << 7;
+    sv_type_agps_set |= (g_settings_from_agps.a_beidou_satellite_enable & 0x01) << 6;
+    sv_type_agps_set |= (g_settings_from_agps.a_gps_satellite_enable & 0x01) << 5;
+    sv_type_agps_set |= (g_settings_from_agps.a_glonass_satellite_enable & 0x01) << 4;
+    sv_type_agps_set |= (g_settings_from_agps.galileo_satellite_enable & 0x01) << 3;
+    sv_type_agps_set |= (g_settings_from_agps.beidou_satellite_enable & 0x01) << 2;
+    sv_type_agps_set |= (g_settings_from_agps.glonass_satellite_enable & 0x01) << 1;
+    sv_type_agps_set |= (g_settings_from_agps.gps_satellite_enable & 0x01);
+    sib8_16_enable = g_settings_from_agps.sib8_16_enable;
+    lppe_enable = g_settings_from_agps.lppe_enable && mtk_gps_mnl_info.support_lppe;
+    get_chip_sv_support_capability(&sv_type);
+    //LOGD("get_chip_sv_support_capability, sv_type = %d", sv_type);
+    g_settings_to_agps.gps_satellite_support = (sv_type) & (0x01);
+    g_settings_to_agps.glonass_satellite_support = ((sv_type) & (0x02)) >> 1;
+    g_settings_to_agps.beidou_satellite_support = ((sv_type) & (0x04)) >> 2;
+    g_settings_to_agps.galileo_satellite_support = ((sv_type) & (0x08)) >> 3;
+
+    ret = mnl2agps_agps_settings_ack(&g_settings_to_agps);
+    //LOGD("mnl2agps_agps_settings_ack done, ret = %d", ret);
+
+    if (mnld_is_gps_started_done()) {
+        ret = mtk_gps_set_param(MTK_PARAM_CMD_SWITCH_CONSTELLATION, &sv_type_agps_set);
+        LOGD("sent CMD_SWITCH_CONSTELLATION to mnl, sv_type_agps_set = 0x%x ,ret = %d", sv_type_agps_set, ret);
+
+        ret = mtk_gps_set_param(MTK_PARAM_CMD_SIB8_16_ENABLE, &sib8_16_enable);
+        LOGD("sent CMD_SIB8_16_ENABLE to mnl, sib8_16_enable = %d ,ret = %d", sib8_16_enable, ret);
+        if(mtk_gps_mnl_info.support_lppe){
+           ret = mtk_gps_set_param(MTK_PARAM_CMD_LPPE_ENABLE, &lppe_enable);
+            LOGD("sent MTK_PARAM_CMD_LPPE_ENABLE to mnl, lppe_enable = %d ,ret = %d", lppe_enable, ret);
+        }
+    } else {
+        LOGD("mnl stop, mnld send pmtk764 to agpsd\n");
+
+        // Generate PMTK764 and send to AGPSD
+        get_agnss_capability(sv_type_agps_set, sv_type, pmtk_str);
+        mnl2agps_pmtk(pmtk_str);
+    }
+}
+
+#ifdef MTK_AGPS_SUPPORT
+static void vzw_debug_screen_output(const char* str) {
+    LOGD("vzw_debug_screen_output  str=%s", str);
+    mnl2hal_vzw_debug_screen_output(str);
+}
+
+static agps2mnl_interface g_agps2mnl_interface = {
+    agps_reboot,
+    agps_open_gps_req,
+    agps_close_gps_req,
+    agps_reset_gps_req,
+    agps_session_done,
+    agps_ni_notify,
+    agps_data_conn_req,
+    agps_data_conn_release,
+    agps_set_id_req,
+    agps_ref_loc_req,
+    agps_rcv_pmtk,
+    agps_gpevt,
+    agps_location,
+    agps_ni_notify2,
+    agps_data_conn_req2,
+    agps_settings_sync,
+    vzw_debug_screen_output,
+    agps_rcv_lppe_common_iono,
+    agps_rcv_lppe_common_trop,
+    agps_rcv_lppe_common_alt,
+    agps_rcv_lppe_common_solar,
+    agps_rcv_lppe_common_ccp,
+    agps_rcv_lppe_generic_ccp,
+    agps_rcv_lppe_generic_dm
+};
+#endif
+
+/*****************************************
+META -> MNL
+*****************************************/
+static void meta_req_gnss_location(int source) {
+    LOGW("meta_req_gnss_location source: %d", source);
+    factory_mnld_gps_start();
+}
+
+static void meta_cancel_gnss_location(int source) {
+    LOGW("meta_cancel_gnss_location source: %d", source);
+    factory_mnld_gps_stop();
+}
+
+static Meta2MnldInterface_callbacks g_meta2mnl_callbacks = {
+    meta_req_gnss_location,
+    meta_cancel_gnss_location
+};
+/////// end of meta
+
+/*****************************************
+DEBUG -> MNL
+*****************************************/
+void mnld_gps_output_data_handle(char* buff, int off_set) {
+    char data[MNLD_TO_APP_BUFF_SIZE] = {0};
+    int offset = off_set;
+    main_out_put_data_type cmd;
+    int lenth = 0;
+
+    cmd = get_int(buff, &offset, MNLD_INTERNAL_BUFF_SIZE);
+
+    switch(cmd) {
+        case DATA_DEBUG2APP: {
+            lenth = get_binary(buff, &offset, data, MNLD_INTERNAL_BUFF_SIZE, sizeof(data));
+            LOGW("mnld send debug msg to app:%s", data);
+            Mnld2DebugInterface_mnldUpdateMessageInfo(&g_mnld_ctx.fds.fd_debug_client, data);
+            break;
+        }
+        default: {
+            LOGW("unkown main_out_put_data_type cmd:%d", cmd);
+            return;
+        }
+    }
+}
+
+int sys_gps_mnl_data2mnld_callback(const char *data, unsigned int length) {
+    char buff[MNLD_TO_APP_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, GPS2MAIN_EVENT_OUTPUT_DATA);
+    put_int(buff, &offset, DATA_DEBUG2APP);
+    put_binary(buff, &offset, data, length);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+static void debug_req_mnld_message(Debug2MnldInterface_DebugReqStatusCategory status) {
+    Mnld2DebugInterface_MnldGpsStatusCategory gps_status;
+    gps_status = (Mnld2DebugInterface_MnldGpsStatusCategory)(mnld_is_gps_started());
+    switch(status) {
+        case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_START_DEBUG:
+        case DEBUG2MNLD_INTERFACE_DEBUG_REQ_STATUS_CATEGORY_STOP_DEBUG:
+            enable_debug2app = status;
+            LOGW("receive debug request msg:%d", status);
+            if (MNLD2DEBUG_INTERFACE_MNLD_GPS_STATUS_CATEGORY_GPS_STARTED==gps_status) {
+                    if(mtk_gps_set_param(MTK_PARAM_CMD_DEBUG2APP_CONFIG, (const void *)&enable_debug2app)) {
+                        LOGW("send APP Debug msg to mnl fail");
+                    }
+            }
+            break;
+        default:
+            LOGW("receive wrong debug msg:%d, do nothing", status);
+            break;
+    }
+    Mnld2DebugInterface_mnldAckDebugReq(&g_mnld_ctx.fds.fd_debug_client);
+    Mnld2DebugInterface_mnldUpdateGpsStatus(&g_mnld_ctx.fds.fd_debug_client,gps_status);
+}
+
+
+static Debug2MnldInterface_callbacks g_debug2mnl_callbacks = {
+    debug_req_mnld_message
+};
+/////// end of debug
+
+/*static void flp2mnl_flp_reboot() {
+    LOGW("flp2mnl_flp_reboot");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = false;
+    flp->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void flp2mnl_gps_start() {
+    LOGW("flp2mnl_gps_start\n");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = true;
+    flp->need_open_ack = true;  // need to confirm flp deamon
+    flp->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void flp2mnl_gps_stop() {
+    LOGW("flp2mnl_gps_stop");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static int flp2mnl_flp_lpbk(char *buff, int len) {
+    int ret = 0;
+    if (-1 == mnl2flp_data_send((UINT8 *)buff, len)) {
+        LOGE("[FLP2MNLD]Send to HAL failed, %s\n", strerror(errno));
+        ret = -1;
+    }
+    else {
+        LOGD("[FLP2MNLD]Send to HAL successfully\n");
+    }
+    return ret;
+}
+
+static int flp2mnl_flp_data(MTK_FLP_OFFLOAD_MSG_T *prMsg) {
+    LOGD("[FLP2MNLD]to connsys: len=%d\n", prMsg->length);
+    if (prMsg->length > 0 && prMsg->length <= OFFLOAD_PAYLOAD_LEN) {
+        mtk_gps_ofl_send_flp_data((UINT8 *)&prMsg->data[0], prMsg->length);
+    } else {
+        LOGD("[FLP2MNLD]to connsys: length is invalid\n");
+    }
+    return 0;
+}
+*/
+
+static int mnld_flp_attach() {
+    LOGD("mnld_flp_attach");
+    if (-1 == mnld_flp_attach_done()) {
+        LOGE("Send attach done to FLP failed\n");
+    } else {
+        LOGD("Send attach done to FLP succeed\n");
+    }
+    return 0;
+}
+
+static void mnld_flp_hbd_gps_open() {
+    LOGD("mnld_flp_hbd_gps_open\n");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = true;
+    flp->need_open_ack = true;  // need to confirm flp deamon
+    flp->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void mnld_flp_hbd_gps_close() {
+    LOGD("mnld_flp_hbd_gps_close");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void mnld_flp_ofl_link_open() {
+    LOGD("mnld_flp_ofl_link_open\n");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = true;
+    flp->need_open_ack = true;  // need to confirm flp deamon
+    flp->need_close_ack = false;
+    mnld_flp_session.type = MNLD_FLP_CAPABILITY_OFL_MODE;
+    mnld_fsm(GPS_EVENT_OFFLOAD_START, 0, 0, NULL);
+}
+
+static void mnld_flp_ofl_link_close() {
+    LOGD("mnld_flp_ofl_link_close");
+    mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+    flp->gps_used = false;
+    flp->need_open_ack = false;
+    flp->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static int mnld_flp_ofl_link_send(MTK_FLP_MNL_MSG_T *prMsg) {
+    LOGD("mnld_flp_ofl_link_send to connsys: len=%d,session_id=%u\n", prMsg->length, prMsg->session);
+    if (prMsg->session == mnld_flp_session.id) {
+        if (prMsg->length > 0 && prMsg->length <= OFFLOAD_PAYLOAD_LEN) {
+            mtk_gps_ofl_send_flp_data((UINT8 *)&prMsg->data[0], prMsg->length);
+        } else {
+            LOGW("mnld_flp_ofl_link_send to connsys: length is invalid\n");
+        }
+    } else {
+        LOGW("session id doesn't match\n");
+    }
+    return 0;
+}
+
+static flp2mnl_interface g_flp2mnl_interface = {
+    mnld_flp_attach,
+    mnld_flp_hbd_gps_open,
+    mnld_flp_hbd_gps_close,
+    mnld_flp_ofl_link_open,
+    mnld_flp_ofl_link_close,
+    mnld_flp_ofl_link_send
+};
+
+/*
+static void gfc2mnl_gfc_reboot() {
+    LOGW("gfc2mnl_gfc_reboot");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = false;
+    geofence->need_open_ack = false;
+    geofence->need_close_ack = false;
+    geofence->need_reset_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void gfc2mnl_gps_start() {
+    LOGW("gfc2mnl_gps_start\n");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = true;
+    geofence->need_open_ack = true;  // need to confirm flp deamon
+    geofence->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void gfc2mnl_gps_stop() {
+    LOGW("gfc2mnl_gps_stop");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = false;
+    geofence->need_open_ack = false;
+    geofence->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+*/
+
+static int mnld_gfc_attach() {
+    LOGD("mnld_gfc_attach");
+    if (-1 == mnld_gfc_attach_done()) {
+        LOGE("Send attach done to GFC failed\n");
+    } else {
+        LOGD("Send attach done to GFC succeed\n");
+    }
+    return 0;
+}
+
+static void mnld_gfc_hbd_gps_open() {
+    LOGD("mnld_gfc_hbd_gps_open\n");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = true;
+    geofence->need_open_ack = true;
+    geofence->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+static void mnld_gfc_hbd_gps_close() {
+    LOGD("mnld_gfc_hbd_gps_close");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = false;
+    geofence->need_open_ack = false;
+    geofence->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static void mnld_gfc_ofl_link_open() {
+    LOGD("mnld_gfc_ofl_link_open\n");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = true;
+    geofence->need_open_ack = true;  // need to confirm flp deamon
+    geofence->need_close_ack = false;
+    mnld_gfc_session.type = MNLD_GFC_CAPABILITY_OFL_MODE;
+    mnld_fsm(GPS_EVENT_OFFLOAD_START, 0, 0, NULL);
+}
+
+static void mnld_gfc_ofl_link_close() {
+    LOGD("mnld_gfc_ofl_link_close");
+    mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+    geofence->gps_used = false;
+    geofence->need_open_ack = false;
+    geofence->need_close_ack = true;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+static int mnld_gfc_ofl_link_send(MTK_GFC_MNL_MSG_T *prMsg) {
+    LOGD("mnld_gfc_ofl_link_send to connsys: len=%d,session_id=%u\n", prMsg->length, prMsg->session);
+    if (prMsg->session == mnld_gfc_session.id) {
+        if (prMsg->length > 0 && prMsg->length <= OFFLOAD_PAYLOAD_LEN) {
+            mtk_gps_ofl_send_flp_data((UINT8 *)&prMsg->data[0], prMsg->length);
+        } else {
+            LOGW("mnld_gfc_ofl_link_send to connsys: length is invalid\n");
+        }
+    } else {
+        LOGW("session id doesn't match\n");
+    }
+    return 0;
+}
+
+static gfc2mnl_interface g_gfc2mnl_interface = {
+    mnld_gfc_attach,
+    mnld_gfc_hbd_gps_open,
+    mnld_gfc_hbd_gps_close,
+    mnld_gfc_ofl_link_open,
+    mnld_gfc_ofl_link_close,
+    mnld_gfc_ofl_link_send
+};
+
+/*
+void flp_test2mnl_gps_start() {
+    LOGD("flp_test2mnl_gps_start\n");
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    flp_test->gps_used = true;
+    flp_test->need_open_ack = false;  // need to confirm flp deamon
+    flp_test->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+void flp_test2mnl_gps_stop() {
+    LOGD("flp_test2mnl_gps_stop");
+    mnld_gps_client* flp_test = &g_mnld_ctx.gps_status.clients.flp_test;
+    flp_test->gps_used = false;
+    flp_test->need_open_ack = false;
+    flp_test->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+extern int ofl_lpbk_tst_start;
+extern int ofl_lpbk_tst_size;
+
+static int flp_test2mnl_flp_lpbk_start() {
+    char tmp_buf[1024];
+    int i;
+
+    LOGD("[OFL]lpbk start!");
+    for (i=0; i < ofl_lpbk_tst_size; i++) {
+        tmp_buf[i] = 0x80;
+    }
+    mtk_gps_ofl_send_flp_data((UINT8 *)&tmp_buf[0], ofl_lpbk_tst_size);
+    ofl_lpbk_tst_start = 1;
+    return 0;
+}
+
+static int flp_test2mnl_flp_lpbk_stop() {
+    LOGD("[OFL]lpbk stop!");
+    ofl_lpbk_tst_start = 0;
+
+    return 0;
+}
+
+#if 0
+static flp_test2mnl_interface g_flp_test2mnl_interface = {
+    flp_test2mnl_gps_start,
+    flp_test2mnl_gps_stop,
+    flp_test2mnl_flp_lpbk_start,
+    flp_test2mnl_flp_lpbk_stop,
+};
+#endif
+*/
+
+void factory_mnld_gps_start() {
+    LOGD("factory_mnld_gps_start\n");
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    factory->gps_used = true;
+    factory->need_open_ack = false;  // need to confirm flp deamon
+    factory->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+}
+
+
+void factory_mnld_gps_stop() {
+    LOGD("factory_mnld_gps_stop");
+    mnld_gps_client* factory = &g_mnld_ctx.gps_status.clients.factory;
+    factory->gps_used = false;
+    factory->need_open_ack = false;
+    factory->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+}
+
+// for AT cmd
+int at_test2mnl_gps_start(void) {
+    LOGD("at_test2mnl_gps_start\n");
+    mnld_gps_client* at_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    at_test->gps_used = true;
+    at_test->need_open_ack = false;  // need to confirm flp deamon
+    at_test->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_START, 0, 0, NULL);
+    return 0;
+}
+
+int at_test2mnl_gps_stop(void) {
+    LOGD("at_test2mnl_gps_stop");
+    mnld_gps_client* at_test = &g_mnld_ctx.gps_status.clients.at_cmd_test;
+    at_test->gps_used = false;
+    at_test->need_open_ack = false;
+    at_test->need_close_ack = false;
+    mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+    return 0;
+}
+
+/*****************************************
+ALL -> MAIN
+*****************************************/
+int mnld_gps_start_done(bool is_assist_req) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, GPS2MAIN_EVENT_START_DONE);
+    put_int(buff, &offset, is_assist_req);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_start_nmea_timeout() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, GPS2MAIN_EVENT_NMEA_TIMEOUT);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_stop_done() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, GPS2MAIN_EVENT_STOP_DONE);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_reset_done() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, GPS2MAIN_EVENT_RESET_DONE);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_gps_update_location(gps_location location) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, GPS2MAIN_EVENT_UPDATE_LOCATION);
+    put_binary(buff, &offset, (const char*)&location, sizeof(location));
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_epo_download_done(epo_download_result result) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, EPO2MAIN_EVENT_EPO_DONE);
+    put_int(buff, &offset, result);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_qepo_download_done(epo_download_result result) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, QEPO2MAIN_EVENT_QEPO_DONE);
+    put_int(buff, &offset, result);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_qepo_bd_download_done(epo_download_result result) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, QEPO2MAIN_EVENT_QEPO_BD_DONE);
+    put_int(buff, &offset, result);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_qepo_ga_download_done(epo_download_result result) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, QEPO2MAIN_EVENT_QEPO_GA_DONE);
+    put_int(buff, &offset, result);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+int mnld_mtknav_download_done(epo_download_result result) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, MTKNAV2MAIN_EVENT_MTKNAV_DONE);
+    put_int(buff, &offset, result);
+    return safe_sendto(MNLD_MAIN_SOCKET, buff, offset);
+}
+
+static int main_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main_internal_event cmd;
+    int read_len;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("main_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    cmd = get_int(buff, &offset, sizeof(buff));
+    switch (cmd) {
+    case GPS2MAIN_EVENT_START_DONE: {
+        int is_assist_req = get_int(buff, &offset, sizeof(buff));
+        LOGI("GPS2MAIN_EVENT_START_DONE  is_assist_req=%d", is_assist_req);
+        mnld_fsm(GPS_EVENT_START_DONE, is_assist_req, 0, NULL);
+        #ifdef MTK_ADR_SUPPORT
+        mnl2adr_open_gps_done();
+        #endif
+        break;
+    }
+    case GPS2MAIN_EVENT_STOP_DONE: {
+        LOGW("GPS2MAIN_EVENT_STOP_DONE");
+        mnld_fsm(GPS_EVENT_STOP_DONE, 0, 0, NULL);
+        break;
+    }
+    case GPS2MAIN_EVENT_RESET_DONE: {
+        LOGW("GPS2MAIN_EVENT_RESET_DONE");
+        stop_timer(g_mnld_ctx.gps_status.timer_reset);
+        do_gps_reset_hdlr();
+        break;
+    }
+    case GPS2MAIN_EVENT_NMEA_TIMEOUT: {
+        LOGD("GPS2MAIN_EVENT_NMEA_TIMEOUT");
+        if (mnld_is_gps_started_done()) {
+            mtk_gps_clear_gps_user();
+            LOGD("set nmea timeout event to main thread\n");
+            mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+            // send the reboot message to the related modules
+            mnl2hal_mnld_reboot();
+            mnl2agps_mnl_reboot();
+            mnl2flp_mnld_reboot();
+            mnl2gfc_mnld_reboot();
+            #ifdef MTK_ADR_SUPPORT
+                mnl2adr_mnl_reboot();
+            #endif
+        }
+        break;
+        }
+    case GPS2MAIN_EVENT_UPDATE_LOCATION: {
+        gps_location location;
+        get_binary(buff, &offset, (char*)&location, sizeof(buff), sizeof(gps_location));
+        bool alt_valid = (location.flags & MTK_GPS_LOCATION_HAS_ALT)? true : false;
+        bool source_valid = true;
+        bool source_gnss = true;
+        bool source_nlp = false;
+        bool source_sensor = false;
+        float valid_acc = (location.flags & MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY)? location.h_accuracy : 2000;
+        if (mtk_gps_log_is_hide() == 0) {
+            LOGW("GPS2MAIN_EVENT_UPDATE_LOCATION  lat=%f lng=%f acc=%f",
+                location.lat, location.lng, valid_acc);
+        }
+        LOGD("wait_first_location=%d\n", g_mnld_ctx.gps_status.wait_first_location);
+        mnl2agps_location_sync(location.lat, location.lng, (int)valid_acc, alt_valid, (float)location.alt, source_valid, source_gnss, source_nlp, source_sensor);
+        if (g_mnld_ctx.gps_status.wait_first_location) {
+            g_mnld_ctx.gps_status.wait_first_location = false;
+            g_mnld_ctx.gps_status.gps_ttff = get_tick() - g_mnld_ctx.gps_status.gps_start_time;
+            #if ANDROID_MNLD_PROP_SUPPORT
+            if (get_gps_cmcc_log_enabled()) {
+                op01_log_gps_location(location.lat, location.lng, g_mnld_ctx.gps_status.gps_ttff);
+            }
+            #else
+            op01_log_gps_location(location.lat, location.lng, g_mnld_ctx.gps_status.gps_ttff);
+            #endif
+        }
+        LOGD("location_sync done\n");
+        break;
+    }
+    case EPO2MAIN_EVENT_EPO_DONE: {
+        epo_download_result result = get_int(buff, &offset, sizeof(buff));
+        LOGD("EPO2MAIN_EVENT_EPO_DONE  result=%d", result);
+        g_mnld_ctx.epo_status.is_epo_downloading = false;
+        // TODO libmnl.so to inject the EPO
+        bool started = mnld_is_gps_or_ofl_started_done();
+        if (result == EPO_DOWNLOAD_RESULT_SUCCESS) {
+            if (started) {
+                epo_update_epo_file();
+            }
+        } else {
+            unlink(EPO_UPDATE_HAL);
+        }
+        break;
+    }
+    case QEPO2MAIN_EVENT_QEPO_DONE: {
+        epo_download_result result = get_int(buff, &offset, sizeof(buff));
+        bool started = mnld_is_gps_or_ofl_started_done();
+        LOGD("QEPO2MAIN_EVENT_QEPO_DONE  result=%d started=%d\n", result, started);
+        if (started) {
+            qepo_update_quarter_epo_file(result);
+        } else {
+            LOGW("qepo download finsh before GPS start done");
+            qepo_update_flag = true;
+        }
+        break;
+    }
+    case QEPO2MAIN_EVENT_QEPO_BD_DONE: {
+        epo_download_result result = get_int(buff, &offset, sizeof(buff));
+        bool started = mnld_is_gps_or_ofl_started_done();
+        LOGD("QEPO2MAIN_EVENT_QEPO_BD_DONE  result=%d started=%d\n", result, started);
+        if (started) {
+            qepo_update_quarter_epo_bd_file(result);
+        } else {
+            LOGW("qepo BD download finsh before GPS start done");
+            qepo_BD_update_flag = true;
+        }
+        break;
+    }
+    case QEPO2MAIN_EVENT_QEPO_GA_DONE: {
+        epo_download_result result = get_int(buff, &offset, sizeof(buff));
+        bool started = mnld_is_gps_or_ofl_started_done();
+        LOGD("QEPO2MAIN_EVENT_QEPO_GA_DONE  result=%d started=%d\n", result, started);
+        if (started) {
+            qepo_update_quarter_epo_ga_file(result);
+        } else {
+            LOGW("qepo GA download finsh before GPS start done");
+            qepo_GA_update_flag = true;
+        }
+        break;
+    }
+    case MTKNAV2MAIN_EVENT_MTKNAV_DONE: {
+        epo_download_result result = get_int(buff, &offset, sizeof(buff));
+        bool started = mnld_is_gps_or_ofl_started_done();
+        LOGD("MTKNAV2MAIN_EVENT_MTKNAV_DONE  result=%d started=%d\n", result, started);
+        if (started) {
+            mtknav_update_mtknav_file(result);
+        } else {
+            LOGW("mtknav download finsh before GPS start done");
+            mtknav_update_flag = true;
+        }
+        break;
+    }
+    case GPS2MAIN_EVENT_OUTPUT_DATA: {
+        mnld_gps_output_data_handle(buff, offset);
+        break;
+    }
+    }
+    return 0;
+}
+
+/*****************************************
+Threads
+*****************************************/
+static void mnld_main_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mnld_main_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("mnld_main_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void mnld_gps_start_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mnld_gps_start_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("mnld_gps_start_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void mnld_gps_stop_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mnld_gps_stop_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("mnld_gps_stop_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void mnld_gps_reset_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mnld_gps_reset_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("mnld_gps_reset_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void mnld_gps_switch_ofl_mode_timeout() {
+    if (is_all_hbd_gps_client_exit()) {
+        LOGD("switch to offload mode timer timeout, flp user prepare to stop gps");
+        mnld_gps_client* flp = &g_mnld_ctx.gps_status.clients.flp;
+        mnld_gps_client* geofence = &g_mnld_ctx.gps_status.clients.geofence;
+        //flp
+        flp->gps_used = false;
+        flp->need_open_ack = false;
+        flp->need_close_ack = false;
+        //geofence
+        geofence->gps_used = false;
+        geofence->need_open_ack = false;
+        geofence->need_close_ack = false;
+        mnld_fsm(GPS_EVENT_STOP, 0, 0, NULL);
+    } else {
+        LOGD("switch to offload mode timer timeout. But some HBD user exist, so not stop gps");
+    }
+}
+
+void gps_mnld_restart_mnl_process(void) {
+    LOGD("gps_mnld_restart_mnl_process\n");
+    mnld_gps_start_nmea_timeout();
+}
+
+void mnld_gps_request_nlp(int src) {
+    LOGD("mnld_gps_request_nlp src: %d", src);
+    //Mnld2NlpUtilsInterface_reqNlpLocation(&g_mnld_ctx.fds.fd_nlp_utils, src);
+    mnl2hal_request_nlp((bool)src);
+}
+
+static void* mnld_main_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    timer_t hdlr_timer = init_timer(mnld_main_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("mnld_main_thread() epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+#ifdef MTK_AGPS_SUPPORT
+    int fd_agps = g_mnld_ctx.fds.fd_agps;
+#endif
+    int fd_hal = g_mnld_ctx.fds.fd_hal;
+    int fd_flp = g_mnld_ctx.fds.fd_flp;
+    int fd_flp_test = g_mnld_ctx.fds.fd_flp_test;
+    int fd_geofence = g_mnld_ctx.fds.fd_geofence;
+    int fd_at_cmd = g_mnld_ctx.fds.fd_at_cmd;
+    int fd_int = g_mnld_ctx.fds.fd_int;
+    int fd_mtklogger = g_mnld_ctx.fds.fd_mtklogger;
+    int fd_mtklogger_client = g_mnld_ctx.fds.fd_mtklogger_client = -1;
+    int fd_meta = g_mnld_ctx.fds.fd_meta;
+    int fd_debug = g_mnld_ctx.fds.fd_debug;
+#ifdef MTK_AGPS_SUPPORT
+    if (epoll_add_fd(epfd, fd_agps) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_agps failed");
+        return 0;
+    }
+#endif
+    if (epoll_add_fd(epfd, fd_hal) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_hal failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_flp) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_flp failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_geofence) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_geofence failed");
+        return 0;
+    }
+    //if (epoll_add_fd(epfd, fd_flp_test) == -1) {
+    //    LOGE("mnld_main_thread() epoll_add_fd() failed for fd_flp_test failed");
+    //    return 0;
+    //}
+    if (epoll_add_fd(epfd, fd_at_cmd) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_at_cmd failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_int) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_int failed");
+        return 0;
+    }
+    if (epoll_add_fd(epfd, fd_mtklogger) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_mtklogger failed");
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, fd_meta) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_meta failed");
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, fd_debug) == -1) {
+        LOGE("mnld_main_thread() epoll_add_fd() failed for fd_debug failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n = 0;
+        #ifdef CONFIG_GPS_ENG_LOAD
+        LOGD("mnld_main_thread() enter wait\n");
+        #endif
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n > 1) {
+            LOGD("n=%d\n", n);
+        } else if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("mnld_main_thread() epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        start_timer(hdlr_timer, MNLD_MAIN_HANDLER_TIMEOUT);
+        for (i = 0; i < n; i++) {
+        #ifdef MTK_AGPS_SUPPORT
+            if (events[i].data.fd == fd_agps) {
+                if (events[i].events & EPOLLIN) {
+                    //LOGD("agps2mnl_hdlr msg");
+                    agps2mnl_hdlr(fd_agps, &g_agps2mnl_interface);
+                }
+            } else
+        #endif
+            if (events[i].data.fd == fd_hal) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("hal2mnl_hdlr msg");
+                    hal2mnl_hdlr(fd_hal, &g_hal2mnl_interface);
+                }
+            } else if (events[i].data.fd == fd_flp) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("flp2mnl_hdlr msg");
+                    mtk_hal2flp_main_hdlr(fd_flp, &g_flp2mnl_interface);
+                }
+            }  else if (events[i].data.fd == fd_geofence) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("gfc2mnl_hdlr msg");
+                    mtk_hal2gfc_main_hdlr(fd_geofence, &g_gfc2mnl_interface);
+                }
+            } else if (events[i].data.fd == fd_flp_test) {
+                    if (events[i].events & EPOLLIN) {
+                    LOGD("fd_flp_test msg");
+                    //flp_test2mnl_hdlr(fd_flp_test, &g_flp_test2mnl_interface);
+                }
+            } else if (events[i].data.fd == fd_at_cmd) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("at_cmd2mnl_hdlr msg");
+                    at_cmd2mnl_hdlr(fd_at_cmd);
+                }
+            } else if (events[i].data.fd == fd_int) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("main_event_hdlr msg");
+                    main_event_hdlr(fd_int);
+                }
+            } else if (events[i].data.fd == fd_mtklogger) {
+                if (events[i].events & EPOLLIN) {
+                        struct sockaddr addr;
+                        socklen_t alen = sizeof(addr);
+                        if (fd_mtklogger_client >= 0) {  // mtklogger exeception exit,  then reconnect
+                            LOGD("mtklogger old client_fd = %d, epoll_del it\n", fd_mtklogger_client);
+                            epoll_del_fd(epfd, fd_mtklogger_client);
+                            close(fd_mtklogger_client);
+                            g_mnld_ctx.fds.fd_mtklogger_client = -1;
+                        }
+                        fd_mtklogger_client = accept(fd_mtklogger, &addr, &alen);
+                        if (fd_mtklogger_client < 0) {
+                            LOGE("accept failed, %s", strerror(errno));
+                            return 0;
+                        }
+                        g_mnld_ctx.fds.fd_mtklogger_client = fd_mtklogger_client;
+                        LOGD("mtklogger new client fd: %d", fd_mtklogger_client);
+                        if (epoll_add_fd(epfd, fd_mtklogger_client) == -1) {
+                            LOGE("mnld_main_thread() epoll_add_fd() failed for fd_mtklogger_client failed");
+                            return 0;
+                    }
+                }
+            } else if (events[i].data.fd == fd_mtklogger_client) {
+                if ((events[i].events & (EPOLLERR|EPOLLHUP)) != 0) {
+                    LOGE("wait fd_mtklogger_client EPOLLERR|EPOLLHUP");
+                    epoll_del_fd(epfd, fd_mtklogger_client);
+                    close(fd_mtklogger_client);
+                    fd_mtklogger_client = g_mnld_ctx.fds.fd_mtklogger_client = -1;
+                    break;
+                } else if ((events[i].events & EPOLLIN) != 0) {
+                    LOGD("mtklogger2mnl_hdlr msg");
+                    start_timer(hdlr_timer, MNLD_GPS_LOG_HANDLER_TIMEOUT);  // mkdir in external sdcard  so slowly
+                    mtklogger2mnl_hdlr(fd_mtklogger_client);
+                }
+            } else if (events[i].data.fd == fd_meta) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("meta2mnl_event_hdlr msg");
+                    Meta2MnldInterface_receiver_read_and_decode(fd_meta, &g_meta2mnl_callbacks);
+                }
+            } else if (events[i].data.fd == fd_debug) {
+                if (events[i].events & EPOLLIN) {
+                    LOGD("debug2mnl_event_hdlr msg");
+                    Debug2MnldInterface_receiver_read_and_decode(fd_debug, &g_debug2mnl_callbacks);
+                }
+            } else {
+                LOGE("mnld_main_thread() unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        stop_timer(hdlr_timer);
+    }
+    LOGE("mnld_main_thread() exit");
+    return 0;
+}
+
+static int mnld_init() {
+    pthread_t pthread_main;
+
+    // init fds
+#ifdef MTK_AGPS_SUPPORT
+    g_mnld_ctx.fds.fd_agps = create_agps2mnl_fd();
+    if (g_mnld_ctx.fds.fd_agps < 0) {
+        LOGE("create_agps2mnl_fd() failed");
+        return -1;
+    }
+#else
+    g_mnld_ctx.fds.fd_agps = 0;
+#endif
+
+    g_mnld_ctx.fds.fd_hal = create_hal2mnl_fd();
+    if (g_mnld_ctx.fds.fd_hal < 0) {
+        LOGE("create_hal2mnl_fd() failed");
+        return -1;
+    }
+
+    g_mnld_ctx.fds.fd_flp = create_flphal2mnl_fd();
+    if (g_mnld_ctx.fds.fd_flp < 0) {
+        LOGE("create_flphal2mnl_fd() failed");
+        return -1;
+    }
+    #if 0
+    g_mnld_ctx.fds.fd_flp_test = create_flp_test2mnl_fd();
+    if (g_mnld_ctx.fds.fd_flp_test < 0) {
+        LOGE("create_flp2mnl_fd() failed");
+        return -1;
+    }
+    #endif
+
+    g_mnld_ctx.fds.fd_geofence= create_gfchal2mnl_fd();
+    if (g_mnld_ctx.fds.fd_geofence< 0) {
+        LOGE("create_gfchal2mnl_fd() failed");
+        return -1;
+    }
+    g_mnld_ctx.fds.fd_at_cmd = create_at2mnl_fd();
+    if (g_mnld_ctx.fds.fd_at_cmd < 0) {
+        LOGE("create_at2mnl_fd() failed");
+        return -1;
+    }
+    g_mnld_ctx.fds.fd_int = socket_bind_udp(MNLD_MAIN_SOCKET);
+    if (g_mnld_ctx.fds.fd_int < 0) {
+        LOGE("socket_bind_udp(MNLD_MAIN_SOCKET) failed");
+        return -1;
+    }
+    g_mnld_ctx.fds.fd_mtklogger = create_mtklogger2mnl_fd();
+    if (g_mnld_ctx.fds.fd_mtklogger < 0) {
+        LOGE("create_mtklogger2mnl_fd() failed");
+        return -1;
+    }
+    g_mnld_ctx.fds.fd_meta = mtk_socket_server_bind_local(META_TO_MNLD_SOCKET, SOCK_NS_ABSTRACT);
+    if (g_mnld_ctx.fds.fd_meta < 0) {
+        LOGE("create meta fd failed");
+        return -1;
+    }
+
+    g_mnld_ctx.fds.fd_debug = mtk_socket_server_bind_local(DEBUG_TO_MNLD_SOCKET, SOCK_NS_ABSTRACT);
+    if (g_mnld_ctx.fds.fd_debug < 0) {
+        LOGE("create debug fd failed");
+        return -1;
+    }
+
+    mtk_socket_client_init_local(&g_mnld_ctx.fds.fd_debug_client,
+            MNLD_TO_DEBUG_SOCKET, SOCK_NS_ABSTRACT);
+
+    mtk_socket_client_init_local(&g_mnld_ctx.fds.fd_nlp_utils,
+            MNLD_TO_NLP_UTILS_SOCKET, SOCK_NS_ABSTRACT);
+    // init timers
+    g_mnld_ctx.gps_status.timer_start = init_timer(mnld_gps_start_timeout);
+    if (g_mnld_ctx.gps_status.timer_start == (timer_t)-1) {
+        LOGE("init_timer(mnld_gps_start_timeout) failed");
+        return -1;
+    }
+
+    g_mnld_ctx.gps_status.timer_stop = init_timer(mnld_gps_stop_timeout);
+    if (g_mnld_ctx.gps_status.timer_stop == (timer_t)-1) {
+        LOGE("init_timer(mnld_gps_stop_timeout) failed");
+        return -1;
+    }
+
+    g_mnld_ctx.gps_status.timer_reset = init_timer(mnld_gps_reset_timeout);
+    if (g_mnld_ctx.gps_status.timer_reset == (timer_t)-1) {
+        LOGE("init_timer(mnld_gps_reset_timeout) failed");
+        return -1;
+    }
+
+    g_mnld_ctx.gps_status.timer_nmea_monitor = init_timer(gps_mnld_restart_mnl_process);
+    if (g_mnld_ctx.gps_status.timer_nmea_monitor == (timer_t)-1) {
+        LOGE("init_timer(gps_mnld_restart_mnl_process) failed");
+        return -1;
+    }
+
+    g_mnld_ctx.gps_status.timer_switch_ofl_mode = init_timer(mnld_gps_switch_ofl_mode_timeout);
+    if (g_mnld_ctx.gps_status.timer_switch_ofl_mode == (timer_t)-1) {
+        LOGE("init_timer(mnld_gps_switch_ofl_mode_timeout) failed");
+        return -1;
+    }
+
+    // init threads
+    pthread_create(&pthread_main, NULL, mnld_main_thread, NULL);
+
+    // send the reboot message to the related modules
+    mnl2hal_mnld_reboot();
+    mnl2agps_mnl_reboot();
+    mnl2flp_mnld_reboot();
+    mnl2gfc_mnld_reboot();
+    Mnld2DebugInterface_mnldUpdateReboot(&g_mnld_ctx.fds.fd_debug_client);
+    return 0;
+}
+
+bool mnld_is_gps_started() {
+    if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STARTING ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STARTED) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mnld_is_gps_or_ofl_started() {
+    if (mnld_is_gps_started() ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STARTING ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STARTED) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mnld_is_gps_started_done() {
+    if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STARTED) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mnld_is_gps_or_ofl_started_done() {
+    if (mnld_is_gps_started_done() ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STARTED) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mnld_is_gps_meas_enabled() {
+    return g_mnld_ctx.gps_status.is_gps_meas_enabled;
+}
+
+bool mnld_is_gps_navi_enabled() {
+    return g_mnld_ctx.gps_status.is_gps_navi_enabled;
+}
+
+// Due to gps_state extends from 4 states to 7 states (3 more for GPS offload),
+// mnld_is_gps_stopped might be overdue. Considering to deprecate this API,
+// and use mnld_is_gps_and_ofl_stopped as replace or change it.
+bool mnld_is_gps_stopped() {
+    if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_IDLE ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STOPPING) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mnld_is_gps_and_ofl_stopped() {
+    if (g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_IDLE ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_STOPPING ||
+        g_mnld_ctx.gps_status.gps_state == MNLD_GPS_STATE_OFL_STOPPING) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mnld_is_epo_download_finished() {
+    if (g_mnld_ctx.epo_status.is_epo_downloading == false) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+void daemon_parse_commandline(int argc, char *argv[])
+{
+    for (int i = 1; i < argc; i++)
+    {
+        if (strcmp("-d", argv[i]) == 0)
+        {
+            set_log_level(&log_dbg_level, atoi(argv[++i]));
+        }
+    }
+}
+
+int main(int argc, char** argv) {
+    daemon_parse_commandline(argc, argv);
+#ifdef CONFIG_GPS_MT3303
+    LOGI("mnld version=2017/08/05 19:39 start");
+#else
+    LOGI("mnld version=0.03, offload ver=%s\n", OFL_VER);
+#endif
+    memset(&g_mnld_ctx, 0, sizeof(g_mnld_ctx));
+    chip_detector();
+    /*get gps_epo_type begin*/
+    if (strcmp(chip_id, "0x6572") == 0 || strcmp(chip_id, "0x6582") == 0 || strcmp(chip_id, "0x6570") == 0 ||
+        strcmp(chip_id, "0x6580") == 0 || strcmp(chip_id, "0x6592") == 0 || strcmp(chip_id, "0x6571") == 0 ||
+        strcmp(chip_id, "0x8127") == 0 || strcmp(chip_id, "0x0335") == 0 ||strcmp(chip_id, "0x8163") == 0) {
+        gps_epo_type = 1;    // GPS only
+    } else if (strcmp(chip_id, "0x6630") == 0 || strcmp(chip_id, "0x6752") == 0 || strcmp(chip_id, "0x6755") == 0
+        || strcmp(chip_id, "0x6797") == 0 || strcmp(chip_id, "0x6632") == 0 || strcmp(chip_id, "0x6759") == 0
+        || strcmp(chip_id, "0x6763") == 0 || strcmp(chip_id, "0x6758") == 0 || strcmp(chip_id, "0x6739") == 0
+        || strcmp(chip_id, "0x6771") == 0 || strcmp(chip_id, "0x6775") == 0) {
+        gps_epo_type = 0;   // G+G
+    } else {
+        gps_epo_type = 0;   // Default is G+G
+    }
+    /*get gps_epo_type end*/
+    mnld_offload_check_capability();
+    if (mnl_init()) {
+        LOGE("mnl_init: %d (%s)\n", errno, strerror(errno));
+    }
+    flp_mnl_emi_download();
+#ifdef CONFIG_GPS_MT3303
+    mt3333_controller_init();
+#endif
+    if (!strncmp(argv[2], "meta", 4) || !strncmp(argv[2], "factory", 4)
+        || !strncmp(argv[0], "test", 4) || !strncmp(argv[2], "PDNTest", 7)) {
+        mnld_factory_test_entry(argc, argv);
+    } else {
+        gps_control_init();
+        epo_downloader_init();
+        qepo_downloader_init();
+        mtknav_downloader_init();
+        op01_log_init();
+        mpe_function_init(0);
+        flp_monitor_init();
+        mnld_init();
+#ifdef __TEST__
+        mnld_test_start();
+#else
+        block_here();
+        //Will go here after calling mnld_block_exit
+        //mnld_dump_exit();
+#endif
+    }
+#ifdef CONFIG_GPS_MT3303
+        LOGE("mnld version=2017/06/25 17:27 end");
+#endif    
+/*
+    LOGD("sizeof(mnld_context)=%d", sizeof(mnld_context));  // 48
+    LOGD("sizeof(gps_location)=%d", sizeof(gps_location));  // 56
+    LOGD("sizeof(gnss_sv)=%d", sizeof(gnss_sv ));           // 20
+    LOGD("sizeof(gnss_sv_info)=%d", sizeof(gnss_sv_info));  // 5124
+    LOGD("sizeof(gps_data)=%d", sizeof(gps_data ));         // 7752
+    LOGD("sizeof(gps_nav_msg)=%d", sizeof(gps_nav_msg));    // 80
+*/
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld_uti.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld_uti.c
new file mode 100644
index 0000000..207beb2
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mnld_uti.c
@@ -0,0 +1,358 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <stdio.h>   /* Standard input/output definitions */
+#include <string.h>  /* String function definitions */
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>  // For 'O_RDWR' & 'O_EXCL'
+#include <poll.h>
+#include "mnld_utile.h"
+#include <termios.h>
+
+#include "mnl_agps_interface.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#if defined(__ANDROID_OS__)
+#include <private/android_filesystem_config.h>
+#endif
+
+#if ANDROID_MNLD_PROP_SUPPORT
+#include <cutils/properties.h>
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mnld_uti"
+#endif
+
+extern int mtk_gps_sys_init();
+#if MTK_GPS_NVRAM
+extern ap_nvram_gps_config_struct stGPSReadback;
+#endif
+
+/*****************************************************************************/
+int read_NVRAM() {
+    int ret = 0;
+    ret = mtk_gps_sys_init();
+    #if MTK_GPS_NVRAM
+    if (strcmp(stGPSReadback.dsp_dev, "/dev/stpgps") == 0) {
+        LOGE("not 3332 UART port\n");
+        return 1;
+    }
+    #endif
+    return ret;
+}
+
+int init_3332_interface(const int fd) {
+    struct termios termOptions;
+    // fcntl(fd, F_SETFL, 0);
+
+    // Get the current options:
+    tcgetattr(fd, &termOptions);
+
+    // Set 8bit data, No parity, stop 1 bit (8N1):
+    termOptions.c_cflag &= ~PARENB;
+    termOptions.c_cflag &= ~CSTOPB;
+    termOptions.c_cflag &= ~CSIZE;
+    termOptions.c_cflag |= CS8 | CLOCAL | CREAD;
+
+    LOGD("GPS_Open: c_lflag=%x,c_iflag=%x,c_oflag=%x\n", termOptions.c_lflag, termOptions.c_iflag,
+                  termOptions.c_oflag);
+    // termOptions.c_lflag
+
+    // Raw mode
+    termOptions.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF | IXANY);
+    termOptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /*raw input*/
+    termOptions.c_oflag &= ~OPOST;  /*raw output*/
+
+    tcflush(fd, TCIFLUSH);  // clear input buffer
+    termOptions.c_cc[VTIME] = 10;  /* inter-character timer unused, wait 1s, if no data, return */
+    termOptions.c_cc[VMIN] = 0;  /* blocking read until 0 character arrives */
+
+     // Set baudrate to 38400 bps
+    cfsetispeed(&termOptions, B115200);  /*set baudrate to 115200, which is 3332 default bd*/
+    cfsetospeed(&termOptions, B115200);
+
+    tcsetattr(fd, TCSANOW, &termOptions);
+
+    return 0;
+}
+
+int hw_test_3332(const int fd) {
+    ssize_t bytewrite, byteread;
+    char buf[6] = {0};
+    char cmd[] = {0xAA, 0xF0, 0x6E, 0x00, 0x08, 0xFE, 0x1A, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0xC3, 0x01, 0xA5, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5A, 0x45, 0x00,
+                0x80, 0x04, 0x80, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+                0x96, 0x00, 0x6F, 0x3C, 0xDE, 0xDF, 0x8B, 0x6D, 0x04, 0x04, 0x00, 0xD2, 0x00,
+                0xB7, 0x00, 0x28, 0x00, 0x5D, 0x4A, 0x1E, 0x00, 0xC6, 0x37, 0x28, 0x00, 0x5D,
+                0x4A, 0x8E, 0x65, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0xFF, 0x00, 0x80, 0x00,
+                0x47, 0x00, 0x64, 0x00, 0x50, 0x00, 0xD8, 0x00, 0x50, 0x00, 0xBB, 0x00, 0x03,
+                0x00, 0x3C, 0x00, 0x6F, 0x00, 0x89, 0x00, 0x88, 0x00, 0x02, 0x00, 0xFB, 0x00,
+                0x01, 0x00, 0x00, 0x00, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x7A, 0x16, 0xAA, 0x0F};
+    char ack[] = {0xaa, 0xf0, 0x0e, 0x00, 0x31, 0xfe};
+
+    bytewrite = write(fd, cmd, sizeof(cmd));
+    if (bytewrite == sizeof(cmd)) {
+        usleep(500*000);
+        byteread = read(fd, buf, sizeof(buf));
+        LOGD("ack:%02x %02x %02x %02x %02x %02x\n",
+                 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+        if ((byteread == sizeof(ack)) && (memcmp(buf, ack, sizeof(ack)) == 0)) {
+            LOGD("it's 3332\n");
+            return 0;   /*0 means 3332, 1 means other GPS chips*/
+        }
+        return 1;
+    } else {
+        LOGE("write error, write API return is %zd, error message is %s\n", bytewrite, strerror(errno));
+        return 1;
+    }
+}
+
+int hand_shake() {
+#if MTK_GPS_NVRAM
+    int fd;
+#endif
+    int ret = -1;
+    int nv;
+    nv = read_NVRAM();
+
+    if (nv == 1)
+        return 1;
+    else if (nv == -1)
+        return -1;
+    else
+        LOGD("read NVRAM ok\n");
+#if MTK_GPS_NVRAM
+    fd = open(stGPSReadback.dsp_dev, O_RDWR | O_NOCTTY);
+    if (fd == -1) {
+        LOGE("GPS_Open: Unable to open - %s, %s\n", stGPSReadback.dsp_dev, strerror(errno));
+        return -1;
+    }
+    init_3332_interface(fd);   /*set UART parameter*/
+
+    ret = hw_test_3332(fd);   /*is 3332?    0:yes   1:no*/
+    close(fd);
+#endif
+    return ret;
+}
+
+int confirm_if_3332() {
+    int ret;
+    // power_on_3332();
+    ret = hand_shake();
+    // power_off_3332();
+    return ret;
+}
+#if ANDROID_MNLD_PROP_SUPPORT
+extern char chip_id[PROPERTY_VALUE_MAX];
+#else
+extern char chip_id[100];
+#endif
+void chip_detector() {
+#ifndef CONFIG_GPS_MT3303
+    int get_time = 20;
+    int res;
+#if ANDROID_MNLD_PROP_SUPPORT
+    while ((get_time-- != 0) && ((res = property_get("persist.vendor.connsys.chipid", chip_id, NULL)) < 6)) {
+        LOGE("get chip id fail, retry");
+        usleep(200000);
+    }
+
+    // chip id is like "0xXXXX"
+    if (res < 6) {
+       LOGE("combo_chip_id error: %s\n", chip_id);
+       return;
+    }
+
+    /* detect if there is 3332, yes set GPS property to 3332,
+    then else read from combo chip to see which GPS chip used */
+    res = confirm_if_3332();    /* 0 means 3332, 1 means not 3332, other value means error */
+    if (res == 0) {
+        strncpy(chip_id, "0x3332",sizeof(chip_id));
+        LOGD("we get MT3332\n");
+    }
+#else
+    strncpy(chip_id, "0x6630",sizeof(chip_id));
+#endif
+#else
+    strncpy(chip_id, "0x3303",sizeof(chip_id));
+#endif
+    LOGI("exit chip_detector\n");
+    LOGI("combo_chip_id is %s\n", chip_id);
+    return;
+}
+
+int buff_get_int(char* buff, int* offset) {
+    int ret = *((int*)&buff[*offset]);
+    *offset += 4;
+    return ret;
+}
+
+int buff_get_string(char* str, char* buff, int* offset) {
+    int len = *((int*)&buff[*offset]);
+    *offset += 4;
+
+    memcpy(str, &buff[*offset], len);
+    *offset += len;
+    return len;
+}
+
+void buff_put_int(int input, char* buff, int* offset) {
+    *((int*)&buff[*offset]) = input;
+    *offset += 4;
+}
+
+void buff_put_string(char* str, char* buff, int* offset) {
+    int len = strlen(str) + 1;
+
+    *((int*)&buff[*offset]) = len;
+    *offset += 4;
+
+    memcpy(&buff[*offset], str, len);
+    *offset += len;
+}
+
+void buff_put_struct(void* input, int size, char* buff, int* offset) {
+    memcpy(&buff[*offset], input, size);
+    *offset += size;
+}
+
+void buff_get_struct(char* output, int size, char* buff, int* offset) {
+    memcpy(output, &buff[*offset], size);
+    *offset += size;
+}
+
+int buff_get_binary(void* output, char* buff, int* offset) {
+    int len = *((int*)&buff[*offset]);
+    *offset += 4;
+
+    memcpy(output, &buff[*offset], len);
+    *offset += len;
+    return len;
+}
+
+int add_chksum(char *pBuf) {
+    int i;
+    unsigned char chksum;
+    char ch;
+    unsigned short Size;
+
+    Size = strlen(pBuf);
+
+    if (Size == 0) {
+        return 0;
+    }
+
+    // will add six characters: '*', CHK1, CHK2, <CR>, <LF>, <ZERO>
+    if (Size > (PMTK_MAX_PKT_LENGTH - 6)) {
+        Size = PMTK_MAX_PKT_LENGTH - 6;
+    }
+
+    chksum = 0;
+    for (i = 1; i < Size; i++) {
+        if (pBuf[i] != '*') {
+            chksum ^= pBuf[i];
+        } else {
+            Size = i;
+            break;
+        }
+     }
+
+    // Add symbol '*'
+    pBuf[Size] = '*';
+
+    // Add CHK1
+    ch = (chksum & 0xF0) >> 4;
+    if (ch >= 10) {
+        ch = 'A' + ch - 10;
+    } else {
+        ch = '0' + ch;
+    }
+    pBuf[Size + 1] = ch;
+
+    // Add CHK2
+    ch = chksum & 0x0F;
+    if (ch >= 10) {
+        ch = 'A' + ch - 10;
+    } else {
+        ch = '0' + ch;
+    }
+    pBuf[Size + 2] = ch;
+
+    pBuf[Size + 3] = '\r';
+    pBuf[Size + 4] = '\n';
+    pBuf[Size + 5] = '\0';
+
+    return 1;
+}
+
+int mnl_init_gps_data_path(const char* data_path, const int length){
+    int index = 0;
+    char dir[MNL_GPS_DATA_PATH_MAX_LENGTH] = {0};
+
+    for(index=2;(index<length)&&data_path[index];index++)
+    {
+        if(data_path[index] == '/'){
+            memset(dir, 0, MNL_GPS_DATA_PATH_MAX_LENGTH);
+            strncpy(dir, data_path, index+1);
+            if (mkdir(dir, 00775) < 0)
+            {
+                if (errno == EEXIST)
+                {
+                    LOGD("directory %s existed.\n", dir);
+                }else{
+                    LOGE("mkdir (%s) failed: %s\n", dir, strerror(errno));
+                    goto fail;
+                }
+            }else{
+                LOGD("mkdir (%s) succeed\n", dir);
+            }
+        }
+    }
+    return 0;
+fail:
+    return -1;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mpe.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mpe.c
new file mode 100644
index 0000000..fedd486
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mpe.c
@@ -0,0 +1,350 @@
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <pthread.h>
+#include <errno.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/epoll.h>
+
+#include "mtk_lbs_utility.h"
+#include "mnld.h"
+#include "mtk_gps.h"
+#include "mpe.h"
+#include "gps_dbg_log.h"
+#include "mpe_common.h"
+#include "data_coder.h"
+#include "gps_controller.h"
+#include "mtk_auto_log.h"
+#include "nmea_parser.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MPE"
+#endif
+
+MPECallBack gMpeCallBackFunc = NULL;
+static int g_fd_mpe = -1;
+static int g_fd_mpe2mnl = -1;
+extern unsigned char gMpeThreadExist;
+
+int mnl2adr_gps_open(void) {
+    LOGD("mnl2adr_gps_open");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_OPEN);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_gps_close(void) {
+    LOGD("mnl2adr_gps_close");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_mnl_reboot(void) {
+    LOGD("mnl2adr_mnl_reboot");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_MNL_REBOOT);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_open_gps_done(void) {
+    LOGD("mnl2adr_open_gps_done");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_OPEN_DONE);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+int mnl2adr_close_gps_done(void) {
+    LOGD("mnl2adr_close_gps_done");
+    char buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(buff, &offset, MNL_ADR_TYPE_MNL2ADR_GPS_CLOSE_DONE);
+    put_int(buff, &offset, 0);//No payload, length is 0
+
+    return safe_sendto(MNLD_MNL2ADR_SOCKET, buff, offset);
+}
+
+char nmea_sbuff[MNL_MPE_NMEA_MAX_SIZE] = {0};
+
+int mnl2adr_send_nmea_data(const char * nmea_buffer, const UINT32 length) {
+    //LOGD("len:%d, %s", length, nmea_buffer);
+    int offset = 0;
+    if(length < (MNL_MPE_NMEA_MAX_SIZE - 2)) {
+        memset(nmea_sbuff, 0, MNL_MPE_NMEA_MAX_SIZE);
+        put_int(nmea_sbuff, &offset, MNL_ADR_TYPE_MNL2ADR_NMEA_DATA);
+        put_int(nmea_sbuff, &offset, length);
+        put_binary(nmea_sbuff, &offset, nmea_buffer, length);
+
+        return safe_sendto(MNLD_MNL2ADR_SOCKET, nmea_sbuff, offset);
+    } else {
+        LOGE("over length(%d):%d", MNL_MPE_NMEA_MAX_SIZE, length);
+        return -1;
+    }
+}
+
+int mnl2mpe_set_log_path(char* path, int status_flag, int mode_flag) {
+    char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+    int offset = 0;
+
+    put_int(mnl2mpe_buff, &offset, CMD_SEND_FROM_MNLD);
+    put_int(mnl2mpe_buff, &offset, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN + 2*sizeof(INT32));
+    put_int(mnl2mpe_buff, &offset, status_flag);
+    put_int(mnl2mpe_buff, &offset, mode_flag);
+    put_binary(mnl2mpe_buff, &offset, (const char*)path, GPS_DEBUG_LOG_FILE_NAME_MAX_LEN);
+
+    if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+        LOGD("MPE not enable\n");
+        return MTK_GPS_ERROR;
+    }
+    if(safe_sendto(MNLD_MPE_SOCKET, mnl2mpe_buff, MNL_MPE_MAX_BUFF_SIZE) == -1) {
+        LOGE("safe_sendto fail:[%s]%d", strerror(errno), errno);
+        return MTK_GPS_ERROR;
+    }
+    return 0;
+}
+
+int mpe2mnl_hdlr(char *buff) {
+    int type, length;
+    int offset = 0;
+
+    type = get_int(buff, &offset, MNL_MPE_MAX_BUFF_SIZE);
+    length = get_int(buff, &offset, MNL_MPE_MAX_BUFF_SIZE);
+
+    LOGD("type=%d length=%d\n", type, length);
+
+    switch (type) {
+        case CMD_MPED_REBOOT_DONE: {
+            mtklogger_mped_reboot_message_update();
+            break;
+        }
+        case CMD_START_MPE_RES:
+        case CMD_STOP_MPE_RES:
+        case CMD_SEND_SENSOR_RAW_RES:
+        case CMD_SEND_SENSOR_CALIBRATION_RES:
+        case CMD_SEND_SENSOR_FUSION_RES:
+        case CMD_SEND_GPS_AIDING_RES:
+        case CMD_SEND_ADR_STATUS_RES:
+        case CMD_SEND_GPS_TIME_REQ: {
+            if (mnld_is_gps_started_done()) {
+                mtk_gps_mnl_get_sensor_info((UINT8 *)buff, length + sizeof(MPE_MSG));
+            }
+            break;
+        }
+
+        case MNL_ADR_TYPE_ADR2MNL_NMEA_DATA: {
+            char nmea[MNL_MPE_NMEA_MAX_SIZE] = {0};
+            get_binary(buff, &offset, nmea, MNL_MPE_NMEA_MAX_SIZE, MNL_MPE_NMEA_MAX_SIZE);
+
+            mtk_mnl_nmea_parser_process(nmea, length);
+            break;
+        }
+        case MNL_ADR_TYPE_ADR2MNL_PMTK_CMD: {
+            char pmtk[MNL_MPE_NMEA_MAX_SIZE];
+            get_binary(buff, &offset, pmtk, MNL_MPE_NMEA_MAX_SIZE, sizeof(pmtk));
+            gps_controller_rcv_pmtk(pmtk);
+            break;
+        }
+        default: {
+           LOGE("unknown cmd=%d\n", type);
+           break;
+       }
+    }
+    return 0;
+}
+
+int mtk_gps_mnl_trigger_mpe(void) {
+    int ret = MTK_GPS_ERROR;
+    #ifdef MTK_ADR_SUPPORT
+    UINT16 mpe_len;
+    char mnl2mpe_buff[MNL_MPE_MAX_BUFF_SIZE] = {0};
+
+    mpe_len = mtk_gps_set_mpe_info((UINT8 *)mnl2mpe_buff);
+    LOGD("mpemsg len=%d\n", mpe_len);
+
+    if (mpe_len > 0) {
+        if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+            LOGE("MPE not enable\n");
+            return MTK_GPS_ERROR;
+        }
+        safe_sendto(MNLD_MPE_SOCKET, mnl2mpe_buff, MNL_MPE_MAX_BUFF_SIZE);
+        ret = MTK_GPS_SUCCESS;
+    }
+    #endif
+    return ret;
+}
+
+/*static void mpe_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("mpe_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("mpe_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}*/
+
+int mnl_mpe_thread_init() {
+    int ret;
+    LOGD("mpe init");
+
+    gMpeCallBackFunc = mtk_gps_mnl_trigger_mpe;
+    ret = mtk_gps_mnl_mpe_callback_reg((MPECallBack *)gMpeCallBackFunc);
+    LOGD("register mpe cb %d,gMpeCallBackFunc= %p,mtk_gps_mnl_trigger_mpe=%p\n",
+        ret, gMpeCallBackFunc, mtk_gps_mnl_trigger_mpe);
+    return 0;
+}
+
+static void* mpe_main_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    mnl2mpe_hdlr_init();
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("epoll_create failure reason=[%s]%d\n",
+            strerror(errno), errno);
+        return 0;
+    }
+    if (g_fd_mpe > 0) {
+        if (epoll_add_fd(epfd, g_fd_mpe) == -1) {
+            LOGE("epoll_add_fd() failed for g_fd_epo failed");
+            return 0;
+        }
+    } else {
+        LOGW("g_fd_mpe invalid");
+    }
+
+    if (g_fd_mpe2mnl > 0) {
+        if (epoll_add_fd(epfd, g_fd_mpe2mnl) == -1) {
+            LOGE("epoll_add_fd() failed for g_fd_epo failed");
+            return 0;
+        }
+    } else {
+        LOGW("g_fd_mpe2mnl invalid");
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_mpe) {
+                if (events[i].events & EPOLLIN) {
+                    mnl2mpe_hdlr(g_fd_mpe);
+                }
+            } else if (events[i].data.fd == g_fd_mpe2mnl) {
+                if (events[i].events & EPOLLIN) {
+                    char mpe2mnl_buff[MNL_MPE_NMEA_MAX_SIZE] = {0};
+                    int read_len = 0;
+                    read_len = safe_recvfrom(g_fd_mpe2mnl, mpe2mnl_buff, sizeof(mpe2mnl_buff));
+                    if (read_len <= 0) {
+                        LOGE("safe_recvfrom() failed read_len=%d", read_len);
+                    } else {
+                        mpe2mnl_hdlr(mpe2mnl_buff);
+                    }
+                }
+            } else {
+                LOGE("unknown fd=%d", events[i].data.fd);
+            }
+        }
+    }
+
+    LOGE("exit");
+    pthread_exit(NULL);
+    return 0;
+}
+
+int mpe_function_init(int self_recv) {
+    pthread_t main_thread_handle;
+
+    mpe_sys_read_mpe_conf_flag();
+    if (!(mpe_sys_get_mpe_conf_flag() & MPE_CONF_MPE_ENABLE)) {
+        LOGD("MPE not enable\n");
+        return MTK_GPS_SUCCESS;
+    }
+
+    if (self_recv) {
+        g_fd_mpe = socket_bind_udp(MNLD_MPE_SOCKET);
+    } else {
+        g_fd_mpe = -1;
+    }
+    g_fd_mpe2mnl = socket_bind_udp(MNLD_ADR2MNL_SOCKET);
+
+    if(pthread_create(&main_thread_handle, NULL, mpe_main_thread, NULL)) {
+        LOGE("MPE main thread init failed");
+    }
+
+    return MTK_GPS_SUCCESS;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mt3333_controller.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mt3333_controller.c
new file mode 100644
index 0000000..8eae7a4
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mt3333_controller.c
@@ -0,0 +1,1633 @@
+#ifdef CONFIG_GPS_MT3303
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <pthread.h>
+#include <termios.h>
+#include <time.h>
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "mt3333_controller.h"
+#include "mnld.h"
+#include "qepo.h"
+#include "epo.h"
+#include "mnl_common.h"
+#include "mtk_gps_sys_fp.h"
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "flashtool.h"
+#include "gps_controller.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mt3333_controller"
+#endif
+
+static int g_fd_mt3333_controller;
+int g_fd_mt3333_data;
+static struct tm g_mt3333_time_st;
+static int nmea_1st_after_powerongps=1;
+int factory_meta_exist=0;
+int is_ygps_delete_data = 0;
+
+extern int gps_epo_type; 
+extern int gps_epo_download_days;
+extern MTK_GPS_SYS_FUNCTION_PTR_T porting_layer_callback;
+extern MNL_CONFIG_T mnld_cfg;
+extern MNL_CONFIG_T mnl_config;
+extern int first_entry;
+
+/**
+ * Utc2GpsTime converts UTC time to GPS time
+ *
+ * @param u2Yr, u2Mo, u2Day, u2Hr, u2Min, dfSec: UTC time
+ * @param pi2Wn GPS week
+ * @param pdfTow GPS time
+
+ *
+ * @return None
+ */
+void __mt3333_controller_Utc2GpsTime(unsigned int u2Yr, unsigned int u2Mo, unsigned int u2Day,
+                 unsigned int u2Hr, unsigned int u2Min, unsigned int dfSec,
+                 unsigned short* pi2Wn, unsigned int* pdfTow)
+{
+  int iYearsElapsed;     // Years since 1980.
+  int iDaysElapsed;      // Days elapsed since Jan 5/Jan 6, 1980.
+  int iLeapDays;         // Leap days since Jan 5/Jan 6, 1980.
+  int i;
+  // Number of days into the year at the start of each month (ignoring leap
+  // years).
+  unsigned short  doy[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
+
+  iYearsElapsed = u2Yr - 1980;
+
+
+  i = 0;
+  iLeapDays = 0;
+  while(i <= iYearsElapsed)
+  {
+    if((i % 100) == 20)
+    {
+      if((i % 400) == 20)
+      {
+        iLeapDays++;
+      }
+    }
+    else if((i % 4) == 0)
+    {
+      iLeapDays++;
+    }
+    i++;
+  }
+
+/*  iLeapDays = iYearsElapsed / 4 + 1; */
+  if((iYearsElapsed % 100) == 20)
+  {
+    if(((iYearsElapsed % 400) == 20) && (u2Mo <= 2))
+    {
+      iLeapDays--;
+    }
+  }
+  else if(((iYearsElapsed % 4) == 0) && (u2Mo <= 2))
+  {
+    iLeapDays--;
+  }
+  iDaysElapsed = iYearsElapsed * 365 + doy[u2Mo - 1] + u2Day + iLeapDays - 6;
+
+  // Convert time to GPS weeks and seconds
+  *pi2Wn = iDaysElapsed / 7;
+  *pdfTow = (iDaysElapsed % 7) * 86400
+            + u2Hr * 3600 + u2Min * 60 + dfSec;
+}
+
+int mt3333_controller_Utc2GpsTime(unsigned short* pi2Wn, unsigned int* pdfTow, unsigned int* sys_time){
+    
+    struct tm *time_st = NULL;
+#if 0
+    long long time_s = 0;
+
+    time_s = time/1000;
+    time_st = localtime(&time_s);
+    g_mt3333_time_st = *time_st;
+#else
+    time_t         now;
+    extern time_t epo_get_now_time();
+    //now = time(NULL);
+    now = epo_get_now_time();
+    gmtime_r(&now, &g_mt3333_time_st);
+    time_st = &g_mt3333_time_st;
+#endif
+    
+    LOGD("%d-%d-%d %d:%d:%d\n", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    __mt3333_controller_Utc2GpsTime(time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec,
+        pi2Wn,pdfTow);
+    *sys_time = now;
+    return 0;
+}
+
+
+#if 1
+
+typedef struct __baudrate_mpping{
+    unsigned int        ul_baud_rate;
+    speed_t            linux_baud_rate;
+}BAUD_RATE_SETTING;
+
+static BAUD_RATE_SETTING speeds_mapping[] = {
+    {0        ,B0        },
+    {50        ,B50        },
+    {75        ,B75        },
+    {110    ,B110        },
+    {134    ,B134,        },
+    {150    ,B150        },
+    {200    ,B200        },
+    {300    ,B300        },
+    {600    ,B600        },
+    {1200    ,B1200        },
+    {1800    ,B1800        },
+    {2400    ,B2400        },
+    {4800    ,B4800        },
+    {9600    ,B9600        },
+    {19200    ,B19200        },
+    {38400    ,B38400        },
+    {57600    ,B57600        },
+    {115200    ,B115200    },
+    {230400    ,B230400    },
+    {460800    ,B460800    },
+    {500000    ,B500000    },
+    {576000    ,B576000    },
+    {921600    ,B921600    },
+    {1000000    ,B1000000    }, 
+    {1152000    ,B1152000    }, 
+    {1500000    ,B1500000    }, 
+    {2000000    ,B2000000    }, 
+    {2500000    ,B2500000    }, 
+    {3000000    ,B3000000    }, 
+    {3500000    ,B3500000    }, 
+    {4000000    ,B4000000    },
+};
+
+static speed_t mt3333_controller_get_speed(unsigned int baudrate) 
+{
+    unsigned int idx;
+    for (idx = 0; idx < sizeof(speeds_mapping)/sizeof(speeds_mapping[0]); idx++){
+        if (baudrate == (unsigned int)speeds_mapping[idx].ul_baud_rate){
+            return speeds_mapping[idx].linux_baud_rate;
+        }
+    }
+    return CBAUDEX;        
+}
+#if 0
+int mt3333_controller_set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits)
+{
+    struct termios uart_cfg_opt;
+    speed_t speed;
+    char  using_custom_speed = 0;
+    
+    if(-1==fd)
+        return -1;
+
+    /* Get current uart configure option */
+    if(-1 == tcgetattr(fd, &uart_cfg_opt))
+        return -1;
+
+    tcflush(fd, TCIOFLUSH);
+
+    /* Baud rate setting section */
+    speed = mt3333_controller_get_speed(new_baudrate);
+    if(CBAUDEX != speed){
+        /*set standard buadrate setting*/
+        cfsetospeed(&uart_cfg_opt, speed);
+        cfsetispeed(&uart_cfg_opt, speed);
+        LOGE("Standard baud=%d",new_baudrate);
+    }else{
+        LOGE("Custom baud=%d",new_baudrate);
+        using_custom_speed = 1;
+    }
+    /* Apply baudrate settings */
+    if(-1==tcsetattr(fd, TCSANOW, &uart_cfg_opt))
+        return -1;
+    
+    /* Set time out */
+    uart_cfg_opt.c_cc[VTIME] = 1;
+    uart_cfg_opt.c_cc[VMIN] = 0;
+
+    /*if((ioctl(fd,TIOCGSERIAL,&ss)) < 0)
+        return -1;
+
+    if(using_custom_speed){
+        ss.flags |= ASYNC_SPD_CUST;  
+            ss.custom_divisor = 1<<31|new_baudrate;
+        }else
+            ss.flags &= ~ASYNC_SPD_CUST;    
+
+    if((ioctl(fd, TIOCSSERIAL, &ss)) < 0)
+        return -1;//*/
+
+    /* Data length setting section */
+    uart_cfg_opt.c_cflag &= ~CSIZE;
+    switch(length)
+    {
+    default:
+    case 8:
+        uart_cfg_opt.c_cflag |= CS8;
+        break;
+    case 5:
+        uart_cfg_opt.c_cflag |= CS5;
+        break;
+    case 6:
+        uart_cfg_opt.c_cflag |= CS6;
+        break;
+    case 7:
+        uart_cfg_opt.c_cflag |= CS7;
+        break;
+    }
+
+    /* Parity setting section */
+    uart_cfg_opt.c_cflag &= ~(PARENB|PARODD);
+    switch(parity_c)
+    {
+    default:
+    case 'N':
+    case 'n':
+        uart_cfg_opt.c_iflag &= ~INPCK;
+        break;
+    case 'O':
+    case 'o':
+        uart_cfg_opt.c_cflag |= (PARENB|PARODD);
+        uart_cfg_opt.c_iflag |= INPCK;
+        break;
+    case 'E':
+    case 'e':
+        uart_cfg_opt.c_cflag |= PARENB;
+        uart_cfg_opt.c_iflag |= INPCK;
+        break;
+    }
+
+    /* Stop bits setting section */
+    if(2==stopbits)
+        uart_cfg_opt.c_cflag |= CSTOPB;
+    else
+        uart_cfg_opt.c_cflag &= ~CSTOPB;
+
+    /* Using raw data mode */
+    uart_cfg_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+    uart_cfg_opt.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
+    uart_cfg_opt.c_oflag &=~(INLCR|IGNCR|ICRNL);
+    uart_cfg_opt.c_oflag &=~(ONLCR|OCRNL);
+
+    /* Apply new settings */
+    if(-1==tcsetattr(fd, TCSANOW, &uart_cfg_opt))
+        return -1;
+
+    tcflush(fd,TCIOFLUSH);
+
+    /* All setting applied successful */
+    LOGE("setting apply done\r\n");
+    return 0;
+}
+#else
+int mt3333_controller_set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits)
+{
+
+    struct termios termOptions;
+    // fcntl(fd, F_SETFL, 0);
+
+    // Get the current options:
+    tcgetattr(fd, &termOptions);
+
+    // Set 8bit data, No parity, stop 1 bit (8N1):
+    termOptions.c_cflag &= ~PARENB;
+    termOptions.c_cflag &= ~CSTOPB;
+    termOptions.c_cflag &= ~CSIZE;
+    termOptions.c_cflag |= CS8 | CLOCAL | CREAD;
+
+    
+    // termOptions.c_lflag
+
+    // Raw mode
+    termOptions.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF | IXANY);
+    termOptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /*raw input*/
+    termOptions.c_oflag &= ~OPOST;  /*raw output*/
+
+    tcflush(fd, TCIFLUSH);  // clear input buffer
+    termOptions.c_cc[VTIME] = 10;  /* inter-character timer unused, wait 1s, if no data, return */
+    termOptions.c_cc[VMIN] = 0;  /* blocking read until 0 character arrives */
+
+     // Set baudrate to 38400 bps
+    cfsetispeed(&termOptions, mt3333_controller_get_speed(new_baudrate));  /*set baudrate to 115200, which is 3332 default bd*/
+    cfsetospeed(&termOptions, mt3333_controller_get_speed(new_baudrate));
+
+    tcsetattr(fd, TCSANOW, &termOptions);
+    LOGE("Custom baud=%d length=%d parity_c=%c stopbits=%d\n",new_baudrate, length, parity_c, stopbits);
+    return 0;
+}
+
+#endif
+
+
+#endif
+#if 1
+int mt3333_thread_pmtk_input_fd[5]={C_INVALID_SOCKET,C_INVALID_SOCKET,C_INVALID_SOCKET,C_INVALID_SOCKET,C_INVALID_SOCKET};
+
+void * mt3333_thread_pmtk_input_func(void * arg)
+{
+    int exit = 0;
+    ssize_t bytes = 0;
+    char buf[MNLD_INTERNAL_BUFF_SIZE]={0};
+    //char cmd[MNLD_INTERNAL_BUFF_SIZE]={0};
+    int fd = (int)arg;
+    
+    LOGD("thread pmtk create: %.8X,fd = %d", (unsigned int)pthread_self(),fd);
+
+    while(!exit)
+    {
+        bytes = read(fd, buf, MNLD_INTERNAL_BUFF_SIZE);
+
+        if (bytes > 0) {
+            LOGD("len=%d,%s", bytes, buf);
+
+            if(bytes != write(g_fd_mt3333_data , buf, bytes)){
+                LOGD("3333 not receive data");
+                break;
+            }
+
+            if (strstr(buf, "PMTK101")
+                || strstr(buf, "PMTK102")
+                || strstr(buf, "PMTK103")
+                || strstr(buf, "PMTK104"))
+            {
+                first_entry = 0;
+                LOGD("PMTK START reset first_entry");
+            }
+
+        } else {
+            if (errno == EINTR) {
+                LOGD("thread pmtk input exit");
+                break;
+            } else if (bytes == 0) { /*client close*/    
+                LOGD("client %d close", fd);
+                close(fd);
+                for(int i=0;i<5; i++){
+                    if(mt3333_thread_pmtk_input_fd[i] == fd){
+                        mt3333_thread_pmtk_input_fd[i] = C_INVALID_SOCKET;
+                        break;
+                    }
+                }
+                break;
+            } else {
+                LOGD("pmtk sleep 200ms. bytes=%d", (int)bytes);
+                usleep(200000);  // sleep 200 ms
+            }
+        }
+    }
+
+    pthread_exit(NULL);
+    return NULL;
+}
+
+void* mt3333_thread_data_debug( void*  arg ) 
+{
+    int server_fd = C_INVALID_SOCKET, conn_fd = C_INVALID_SOCKET, on;
+    struct sockaddr_in server_addr;
+    struct sockaddr_in client_addr;
+    socklen_t size;
+    //char buf[128];
+
+    UNUSED(arg);
+    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+    {
+        LOGE("socket error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    /* Enable address reuse */
+    on = 1;
+    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) 
+    {
+        close(server_fd);
+        LOGE("setsockopt error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    server_addr.sin_family = AF_INET;   /*host byte order*/
+    server_addr.sin_port = htons(7000); /*short, network byte order*/
+    server_addr.sin_addr.s_addr = INADDR_ANY; /*automatically fill with my IP*/
+    memset(server_addr.sin_zero, 0x00, sizeof(server_addr.sin_zero));
+
+    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) 
+    {
+        close(server_fd);
+        LOGE("bind error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    if (listen(server_fd, 5) == -1) 
+    {
+        close(server_fd);
+        LOGE("listen error = %d (%s)", errno, strerror(errno));
+        pthread_exit(NULL);
+        return NULL;
+    }
+
+    LOGD("listening debug port: %d", 7000);
+
+    while (1) 
+    {
+        size = sizeof(client_addr);
+        conn_fd = accept(server_fd, (struct sockaddr*)&client_addr, &size);
+        if (conn_fd <= 0) 
+        {
+            LOGE("accept error: %d (%s)", errno, strerror(errno));
+            continue;
+        } 
+        else 
+        {
+            LOGD("accept connection [%d] %s:%d", conn_fd, 
+                inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));     
+            /*loop until being interrupted or client close*/ 
+            pthread_t pthread_mt3333_controller_accept;
+            for(int i=0;i<5; i++){
+                if(mt3333_thread_pmtk_input_fd[i] == C_INVALID_SOCKET){
+                    mt3333_thread_pmtk_input_fd[i] = conn_fd;
+                    break;
+                }
+            }
+            pthread_create(&pthread_mt3333_controller_accept, NULL, mt3333_thread_pmtk_input_func, (void*)conn_fd);
+        }
+    }
+    pthread_exit(NULL);
+    return NULL;
+}
+
+#endif
+
+unsigned char gps_nmea_cal_checksum(unsigned char *ptr, unsigned char len){
+    unsigned char i=0;
+    unsigned char checksum=0;
+
+    checksum=ptr[1];
+    for(i=2; i<len; i++){
+        checksum ^= ptr[i];
+    }
+    return checksum;
+}
+
+#if 1
+
+#define MT3333_CONTROLLER_EPO_RECORD_SIZE (72)
+#define MT3333_CONTROLLER_EPO_SV_NUMBER (32+24)
+#define MT3333_CONTROLLER_EPO_SEG_BUF_SIZE ((MT3333_CONTROLLER_EPO_RECORD_SIZE * MT3333_CONTROLLER_EPO_SV_NUMBER) >> 2)
+
+int mt3333_controller_u4EPOWORD[MT3333_CONTROLLER_EPO_SEG_BUF_SIZE];
+
+
+
+int mtk_gps_epo_UtcToGpsHour (struct tm* time_st)
+{
+    int iYearsElapsed; // Years since 1980
+    int iDaysElapsed; // Days elapsed since Jan 6, 1980
+    int iLeapDays; // Leap days since Jan 6, 1980
+    int i;
+    int iYr =time_st->tm_year + 1900;
+    int iMo =time_st->tm_mon + 1;
+    int iDay =time_st->tm_mday;
+    int iHr = time_st->tm_hour;
+    // Number of days into the year at the start of each month (ignoring leap years)
+    const int doy[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
+
+    
+    
+    iYearsElapsed = iYr - 1980;
+    i = 0;
+    iLeapDays = 0;
+    while (i <= iYearsElapsed)
+    {
+        if ((i % 100) == 20)
+        {
+            if ((i % 400) == 20)
+            {
+                iLeapDays++;
+            }
+        }
+        else if ((i % 4) == 0)
+        {
+            iLeapDays++;
+        }
+        i++;
+    }
+    if ((iYearsElapsed % 100) == 20)
+    {
+        if (((iYearsElapsed % 400) == 20) && (iMo <= 2))
+        {
+            iLeapDays--;
+        }
+    }
+    else if (((iYearsElapsed % 4) == 0) && (iMo <= 2))
+    {
+        iLeapDays--;
+    }
+    iDaysElapsed = iYearsElapsed * 365 + doy[iMo - 1] + iDay + iLeapDays - 6;
+    
+    
+    return (iDaysElapsed * 24 + iHr);
+}
+
+int gps_data_convert(int dat){
+    char *ptr = (char *)(&dat);
+    
+    return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + (ptr[3]<<0);
+}
+
+void gps_timer_epo_send_assistance_data(void)
+{
+    int i=0, SatID;
+    int *pBuf;
+    char nmea_cmd[300], temp[50];
+    int err=0;
+    int count=0;
+
+    if(g_fd_mt3333_data < 0){
+        return;
+    }
+    
+    
+
+    if (gps_epo_type == 0)// G+G
+    {
+        // read binary EPO data and sent it to MT3333
+        for (i =0; i < (MT3333_CONTROLLER_EPO_SV_NUMBER); i++)
+        {
+            pBuf = mt3333_controller_u4EPOWORD + (i * 18);
+            // assume host system is little-endian
+            SatID = (pBuf[0] & 0xFF000000) >> 24;
+            if (SatID == 0){
+                continue;
+            }
+            
+            // assume host system is little-endian
+            sprintf(nmea_cmd,
+            "$PMTK721,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X,%X",
+            SatID,
+#if 0            
+            gps_data_convert(pBuf[0]), gps_data_convert(pBuf[1]), gps_data_convert(pBuf[2]), gps_data_convert(pBuf[3]), 
+            gps_data_convert(pBuf[4]), gps_data_convert(pBuf[5]), gps_data_convert(pBuf[6]), gps_data_convert(pBuf[7]), 
+            gps_data_convert(pBuf[8]), gps_data_convert(pBuf[9]), gps_data_convert(pBuf[10]),gps_data_convert(pBuf[11]), 
+            gps_data_convert(pBuf[12]), gps_data_convert(pBuf[13]), gps_data_convert(pBuf[14]), gps_data_convert(pBuf[15]), 
+            gps_data_convert(pBuf[16]), gps_data_convert(pBuf[17]));
+#else 
+            (pBuf[0]), (pBuf[1]), (pBuf[2]), (pBuf[3]), 
+            (pBuf[4]), (pBuf[5]), (pBuf[6]), (pBuf[7]), 
+            (pBuf[8]), (pBuf[9]), (pBuf[10]),(pBuf[11]), 
+            (pBuf[12]), (pBuf[13]), (pBuf[14]), (pBuf[15]), 
+            (pBuf[16]), (pBuf[17]));
+
+#endif
+            sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+            strcat(nmea_cmd , temp);
+            count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+            if((strlen(nmea_cmd)+1) != count){
+                err=-1;
+            }
+
+            LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+            //UART DMA buffer is 2K, so GPS can send max 2K bytes once
+            //one satellite EPO sentence contain max 174 bytes, every 12 satellites contain max 2088 bytes,
+            //send 2088 bytes need cost 180ms(baudrate 115200) ,so when send 12 satellites EPO data, wait 180ms
+            if (( (i + 1) % 12 ) == 0){
+                usleep(360*1000);
+            }
+        }
+    }
+    
+}
+
+
+
+int mt3333_controller_inject_epo(int qepo){
+
+    int fd = 0;
+    //int addLock, res_epo, res_epo_hal;
+    //unsigned int u4GpsSecs_start;    // GPS seconds
+    //unsigned int u4GpsSecs_expire;
+    //char *epo_file = EPO_FILE;
+    char *epo_file_hal = qepo?QEPO_UPDATE_HAL:EPO_UPDATE_HAL;
+    //char epofile[32] = {0};
+    //time_t uSecond_start;      // UTC seconds
+    //time_t uSecond_expire;
+    int ret = 0;
+    pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;
+    int epofile_begin_utc_hour=0;
+
+#if 1
+        time_t           now;
+        extern time_t epo_get_now_time();
+        //now = time(NULL);
+        now = epo_get_now_time();
+        gmtime_r(&now, &g_mt3333_time_st);
+#endif
+    int current_gps_hour = mtk_gps_epo_UtcToGpsHour(&g_mt3333_time_st);
+    
+    
+    ret = pthread_mutex_lock(&mutx);
+    if (access(epo_file_hal, 0) == -1) {
+        LOGE("EPOHAL.DAT is not exist\n");
+        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    }
+
+    fd = open(epo_file_hal, O_RDONLY);
+    if (fd < 0) {
+        LOGE("Open EPO fail, return\n");
+        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+    }
+
+    // Add file lock
+    if (mtk_gps_sys_read_lock(fd, 0, SEEK_SET, 0) < 0) {
+        LOGE("Add read lock failed, return\n");
+        close(fd);
+        ret = pthread_mutex_unlock(&mutx);
+        return -1;
+   }
+
+    if(qepo == 0){
+        // EPO start time
+        if (sizeof(epofile_begin_utc_hour) != read(fd, &epofile_begin_utc_hour, sizeof(epofile_begin_utc_hour))) {
+            LOGE("Get EPO file start time error, return\n");
+            close(fd);
+            ret = pthread_mutex_unlock(&mutx);
+            return -1;
+        }else{
+            epofile_begin_utc_hour = epofile_begin_utc_hour & 0x00FFFFFF;
+        }
+
+        
+
+        LOGD("current_gps_hour - epofile_begin_utc_hour =%d\n" , current_gps_hour - epofile_begin_utc_hour);
+        if (current_gps_hour - epofile_begin_utc_hour > gps_epo_download_days*24){
+            close(fd);
+            ret = pthread_mutex_unlock(&mutx);
+            LOGE("EPOHAL.DAT is expired, return\n");
+            return -1;
+        }
+
+        if (lseek(fd, ((current_gps_hour - epofile_begin_utc_hour) / 6)*(MT3333_CONTROLLER_EPO_RECORD_SIZE)*(MT3333_CONTROLLER_EPO_SV_NUMBER), SEEK_SET) == -1){
+            close(fd);
+            ret = pthread_mutex_unlock(&mutx);
+            LOGE("lseek error: %s\n", strerror(errno));
+            return -1;
+        }
+    }
+    
+        
+    
+    if ((MT3333_CONTROLLER_EPO_SEG_BUF_SIZE*sizeof(int)) != read(fd, mt3333_controller_u4EPOWORD, MT3333_CONTROLLER_EPO_SEG_BUF_SIZE*sizeof(int))) {
+        close(fd);
+        ret = pthread_mutex_unlock(&mutx);
+        LOGE("lseek error: %s\n", strerror(errno));
+        return -1;
+    }
+
+    close(fd);
+    ret = pthread_mutex_unlock(&mutx);
+
+    gps_timer_epo_send_assistance_data();
+    return 0;
+}
+
+#endif
+
+
+int mt3333_controller_delete_aiding_data(int flags)
+{
+    
+    int err=0;
+    int count=0;
+    //int count1=10*5;
+
+    const char hot_cmd[]="$PMTK101";
+    const char warm_cmd[]="$PMTK102";
+    const char cold_cmd[]="$PMTK103";
+    const char full_cmd[]="$PMTK104";
+    //const char agps_cmd[]="$PMTK106";
+
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    LOGD("%s:0x%X\n", __FUNCTION__, flags);
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+    if(is_ygps_delete_data == 0){
+        return -1;
+    }
+    
+
+    if ((flags&(GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION|GPS_DELETE_RTI)) == (GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION|GPS_DELETE_RTI)) {
+        LOGD("Send MNL_CMD_RESTART_FULL in HAL\n");
+        sprintf(nmea_cmd ,"%s",full_cmd);
+    } else if ((flags&(GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION)) == (GPS_DELETE_EPHEMERIS|GPS_DELETE_POSITION)) {
+        LOGD("Send MNL_CMD_RESTART_COLD in HAL\n");
+        sprintf(nmea_cmd ,"%s",cold_cmd);
+    } else if ((flags&(GPS_DELETE_EPHEMERIS)) == (GPS_DELETE_EPHEMERIS)) {
+        LOGD("Send MNL_CMD_RESTART_WARM in HAL\n");
+        sprintf(nmea_cmd ,"%s",warm_cmd);
+    } else if ((flags&GPS_DELETE_RTI) == GPS_DELETE_RTI) {
+        LOGD("Send MNL_CMD_RESTART_HOT in HAL\n");
+        sprintf(nmea_cmd ,"%s",hot_cmd);
+    } else{
+        LOGD("Send MNL_CMD_RESTART_HOT in HAL\n");
+        sprintf(nmea_cmd ,"%s",hot_cmd);
+    }
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s\n" ,err, nmea_cmd);
+    
+    return 0;
+
+}
+
+int mt3333_controller_inject_location(double latitude, double longitude, float accuracy)
+{
+
+    const char time_aiding_cmd[]="$PMTK741";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    LOGD("inject location lati= %f, longi = %f, accuracy =%f\n", latitude, longitude, accuracy);
+    sprintf(temp ,",%.6f,%.6f,0", latitude , longitude);
+    strcat(nmea_cmd , temp);
+    
+    
+#if 0
+        time_st = &g_mt3333_time_st;
+#else
+        time_t           now;
+        extern time_t epo_get_now_time();
+        //now = time(NULL);
+        now = epo_get_now_time();
+        gmtime_r(&now, &g_mt3333_time_st);
+        time_st = &g_mt3333_time_st;
+#endif
+
+    
+    LOGD("%d-%d-%d %d:%d:%d\n", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    sprintf(temp ,",%4d,%02d,%02d,%02d,%02d,%02d", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+    
+    return 0;
+}
+
+int mt3333_controller_inject_time(int64_t time, int64_t timeReference, int uncertainty)
+{
+    
+    
+    const char time_aiding_cmd[]="$PMTK740";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    struct tm *time_st = NULL;
+#if 0
+    long long time_s = 0;
+#else
+    time_t time_s = 0;
+    UNUSED(uncertainty);
+#endif
+    time_t         now;
+    extern time_t epo_get_now_time();
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    if(time==0 && timeReference == 0){
+        LOGD("local time\n");
+        //now = time(NULL);
+        now = epo_get_now_time();
+        gmtime_r(&now, &g_mt3333_time_st);
+        time_st = &g_mt3333_time_st;
+    }else{// network time is wrong ,diffrect about 20s
+        return 0;
+        now = epo_get_now_time();
+        LOGD("network time %lld, ref=%lld,local=%ld\n",time,timeReference,now);
+        time_s = time/1000;
+        //time_st = localtime(&time_s);
+        //g_mt3333_time_st = *time_st;
+        gmtime_r(&time_s, &g_mt3333_time_st);
+        time_st = &g_mt3333_time_st;
+    }
+
+    
+    LOGD("%d-%d-%d %d:%d:%d\n", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    
+    sprintf(temp ,",%4d,%02d,%02d,%02d,%02d,%02d", 
+        time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, 
+        time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_enable_debuglog(int enable)
+{
+    
+    
+    const char time_aiding_cmd[]="$PMTK299";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d", enable);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_enable_easymode(int enable)
+{
+    
+    
+    const char time_aiding_cmd[]="$PMTK869,1";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d", enable);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+int mt3333_controller_set_nmea_onoff()
+{
+    int gll =0;
+    int rmc =1;
+    int vtg =1;
+    int gga =1;
+    int gsa =1;
+    int gsv =1;
+    int accuracy =1;
+    const char time_aiding_cmd[]="$PMTK314";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d,%d,%d,%d,%d,%d", gll,rmc,vtg,gga,gsa,gsv);
+    strcat(nmea_cmd , temp);
+    sprintf(temp ,",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
+    strcat(nmea_cmd , temp);
+    sprintf(temp ,",%d", accuracy);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+
+int mt3333_controller_set_gnss_working_satellite_system(MTK_GNSS_CONFIGURATION gnssmode)
+{
+    int gps_enable=0;
+    int glonass_enable=0;
+    int galileo_enable=0;
+    int galileo_full_enable=0;
+    int beidou_enable=0;
+    
+    const char time_aiding_cmd[]="$PMTK353";
+    
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+
+    switch(gnssmode){
+    case MTK_CONFIG_GPS_GLONASS:
+    case MTK_CONFIG_GPS_GLONASS_BEIDOU:
+        gps_enable=1;
+        glonass_enable=1;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    case MTK_CONFIG_GPS_BEIDOU:
+        gps_enable=1;
+        glonass_enable=0;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=1;
+        break;    
+    case MTK_CONFIG_GPS_ONLY:
+        gps_enable=1;
+        glonass_enable=0;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;    
+    case MTK_CONFIG_BEIDOU_ONLY:
+        gps_enable=0;
+        glonass_enable=0;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=1;
+        break;    
+    case MTK_CONFIG_GLONASS_ONLY:
+        gps_enable=0;
+        glonass_enable=1;
+        galileo_enable=0;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;    
+    case MTK_CONFIG_GPS_GLONASS_BEIDOU_GALILEO:
+        gps_enable=1;
+        glonass_enable=1;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;    
+    case MTK_CONFIG_GPS_GLONASS_GALILEO:
+        gps_enable=1;
+        glonass_enable=1;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    case MTK_CONFIG_GALILEO_ONLY:
+        gps_enable=0;
+        glonass_enable=0;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    case MTK_CONFIG_GPS_GALILEO:
+        gps_enable=1;
+        glonass_enable=0;
+        galileo_enable=1;
+        galileo_full_enable=0;
+        beidou_enable=0;
+        break;
+    }
+    
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    
+    
+    
+    sprintf(temp ,",%d,%d,%d,%d,%d", gps_enable,glonass_enable,galileo_enable,galileo_full_enable,beidou_enable);
+    strcat(nmea_cmd , temp);
+    
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_set_gnss_position_fix_interval(int fix_interval)
+{
+    const char time_aiding_cmd[]="$PMTK220";
+
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+    //struct tm *time_st = NULL;
+    //long long time_s = 0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    sprintf(temp ,",%d", fix_interval);
+    strcat(nmea_cmd , temp);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+int mt3333_controller_set_pps_config(int pps_mode, int pps_duty)
+{
+    const char time_aiding_cmd[]="$PMTK285";
+
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+
+    int err=0;
+    int count=0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+
+    sprintf(temp ,",%d,%d", pps_mode,pps_duty);
+    strcat(nmea_cmd , temp);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+
+#ifdef MTK_ADR_SUPPORT
+int mt3333_controller_set_gnss_pmtk876_nmea_onoff(int enable)
+{
+    const char time_aiding_cmd[]="$PMTK876";
+    char nmea_cmd[256]={0};
+    char temp[50]={0};
+    int err=0;
+    int count=0;
+
+    if(g_fd_mt3333_data < 0){
+        return -1;
+    }
+
+    sprintf(nmea_cmd ,"%s",time_aiding_cmd);
+    sprintf(temp ,",%d", enable);
+    strcat(nmea_cmd , temp);
+
+    sprintf(temp ,"*%02X\x0d\x0a", gps_nmea_cal_checksum((unsigned char *)nmea_cmd, strlen(nmea_cmd)));
+    strcat(nmea_cmd , temp);
+    count = write(g_fd_mt3333_data , nmea_cmd, strlen(nmea_cmd)+1);
+    if((strlen(nmea_cmd)+1) != count){
+        err=-1;
+    }
+    LOGD("err=%d,cmd=%s" ,err, nmea_cmd);
+
+    return 0;
+}
+#endif
+
+static int mt3333_controller_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main_mt3333_controller_event cmd;
+    int read_len;
+    char assist_data_req=0; // show gps icon
+    int fix_interval = 1000;    /* fix interval in milliseconds */
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("safe_recvfrom() failed read_len=%d, err:%s", read_len, strerror(errno));
+        return -1;
+    }
+
+    while(offset < read_len){
+        
+        cmd = get_int(buff, &offset, sizeof(buff));
+        LOGD("cmd =%d",cmd);
+        switch (cmd) {
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSREBOOT:
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSENABLE:
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSSTART:
+            nmea_1st_after_powerongps = 1;
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSSTOP:
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSDISABLE:
+        case MAIN_MT3333_CONTROLLER_EVENT_GPSDELETEAIDING:
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUES1STNMEA:
+            assist_data_req=0; // show gps icon
+            porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_START_REQ, 0, &assist_data_req);
+            //usleep(800*1000);
+            //mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF);
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTNTP:
+            //assist_data_req=1;
+            //porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_BITMAP_UPDATE, 0, &assist_data_req);
+            mt3333_controller_inject_time(0,0,0);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTNLP:
+            assist_data_req=2;
+            porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_BITMAP_UPDATE, 0, &assist_data_req);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTEPO:
+            if(epo_downloader_is_file_invalid()){
+                // download QEPO , but now we can't get wk + tow, so need to add.
+                porting_layer_callback.sys_agps_disaptcher_callback(MTK_AGPS_CB_QEPO_DOWNLOAD_REQ, 0, NULL);
+            }else{
+                mt3333_controller_inject_epo(0);
+            }
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_REQUESTQEPO:
+            mt3333_controller_inject_epo(1);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEBUGLOG:
+            mt3333_controller_enable_debuglog(1);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEBUGLOG:
+            mt3333_controller_enable_debuglog(0);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND:
+            // tell mnld nmea monitor that data is comming normally.
+            porting_layer_callback.sys_gps_mnl_callback(MTK_GPS_MSG_FIX_READY);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_FACTORYMETA:
+            factory_meta_exist = 1;
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEASYMODE:
+            mt3333_controller_enable_easymode(1);
+            break;    
+        case MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEASYMODE:
+            mt3333_controller_enable_easymode(0);
+            break;        
+        case MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF:
+            mt3333_controller_set_nmea_onoff();
+            break;        
+        case MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM:
+            mt3333_controller_set_gnss_working_satellite_system(mnl_config.GNSSOPMode);
+            break;            
+        case MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL:
+            #ifdef MTK_ADR_SUPPORT
+            fix_interval = 1000;                //  1Hz update rate
+            #else
+            if(mnl_config.fix_interval == 200 || mnl_config.fix_interval == 500 ||
+                mnl_config.fix_interval == 1000 || (mnl_config.fix_interval >= 100 &&
+                mnl_config.GNSSOPMode == MTK_CONFIG_GPS_ONLY)) {
+                fix_interval = mnl_config.fix_interval;
+            }else{
+                fix_interval = 1000;
+            }
+            LOGD("fix_interval = %d \n", fix_interval);
+            #endif
+            mt3333_controller_set_gnss_position_fix_interval(fix_interval);
+            break;
+        case MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG:
+            mt3333_controller_set_pps_config(mnl_config.pps_mode, mnl_config.pps_duty);
+            break;
+        #ifdef MTK_ADR_SUPPORT
+        case MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF:
+            mt3333_controller_set_gnss_pmtk876_nmea_onoff(1);
+            break;
+        #endif
+        }
+    }
+
+    return 0;
+}
+
+static int mt3333_data_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    //int offset = 0;
+    //char assist_data_req=0;
+    int read_len;
+
+    do{
+        memset(buff, 0, sizeof(buff));
+        read_len = read(fd, buff, sizeof(buff));
+        LOGD("read len=%d, err:%s", read_len, strerror(errno));
+        if (read_len <= 0) {
+            break;
+        }else{
+            if((mnld_is_gps_started()) || (factory_meta_exist == 1)){
+            }else{
+                continue;
+            }
+
+            // bypass data to app.
+            porting_layer_callback.sys_nmea_output_to_mnld(buff, read_len);
+            // debug log when issue occur.
+            porting_layer_callback.sys_nmea_output_to_app(buff, read_len);
+
+            //save log to debug log file.
+            porting_layer_callback.sys_alps_gps_dbg2file_mnld(buff, read_len);
+
+            for(int i=0;i<5; i++){
+                if(mt3333_thread_pmtk_input_fd[i] != C_INVALID_SOCKET){
+                    write(mt3333_thread_pmtk_input_fd[i] , buff, read_len);
+                }
+            }
+        }
+    }while(1);
+    
+
+    return 0;
+}
+
+#if 0
+static void mt3333_controller_thread_timeout() {
+    LOGE("mt3333_controller_thread_timeout() crash here for debugging");
+    CRASH_TO_DEBUG();
+}
+#endif
+
+void* mt3333_thread_control(void *arg) {
+    #define MAX_EPOLL_EVENT 1
+    //timer_t hdlr_timer = init_timer(mt3333_controller_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_mt3333_controller) == -1) {
+        LOGE("epoll_add_fd() failed for g_fd_mt3333_controller failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_mt3333_controller) {
+                if (events[i].events & EPOLLIN) {
+                    mt3333_controller_event_hdlr(g_fd_mt3333_controller);
+                }
+            } else {
+                LOGE("unknown fd=%d", events[i].data.fd);
+            }
+        }
+        
+    }
+    pthread_exit(NULL);
+    LOGE("exit");
+    return 0;
+}
+int mt3333_controller_check_if_gpsfunctionok(void) {
+    char buff[32]={0};
+    int read_len = 0;
+    int temp=0;
+    int result=1;
+
+    mnl_set_pwrctl(1);
+
+    int cnt_1s=0;
+    int retry_cnt=0;
+    do{
+        temp = read(g_fd_mt3333_data, buff, sizeof(buff)-1-read_len);
+        if(temp<=0){
+            temp=0;
+        }
+        read_len += temp;
+        usleep(100 * 1000);
+        if((++cnt_1s) > 30){// wait 3s
+            
+            LOGE("read summary len=%d", read_len);
+            cnt_1s = 0;
+            read_len =0;
+            retry_cnt++;
+            mnl_set_pwrctl(4);// reset 3333 power
+        }
+        if(retry_cnt > 1){
+            LOGE("retry max count=5, maybe chip is broken");
+            mnl_set_pwrctl(0);
+            #if ANDROID_MNLD_PROP_SUPPORT
+            if (property_set("3333.gps", "fail") != 0) {
+                LOGE("set 3333.gps %s\n", strerror(errno));
+            }
+            #endif
+            return result;
+        }
+    }while(read_len<31);
+    
+    LOGE("read len=%d,content=%s", read_len,buff);
+    for(int i=0; i<sizeof(buff); i++){
+        if(buff[i] >= 0x80){
+            result=0;
+            break;
+        }
+    }
+    mnl_set_pwrctl(0);
+    LOGE("result= %d",result); 
+    if(1 == result){
+        #if ANDROID_MNLD_PROP_SUPPORT
+        if (property_set("3333.gps", "ok") != 0) {
+            LOGE("set 3333.gps %s\n", strerror(errno));
+        }
+        #endif
+    }else{
+        #if ANDROID_MNLD_PROP_SUPPORT
+        if (property_set("3333.gps", "fail") != 0) {
+            LOGE("set 3333.gps %s\n", strerror(errno));
+        }
+        #endif
+    }
+    
+    return result;
+}
+
+
+int mt3333_controller_check_uart_baudrate(void) {
+    char buff[32]={0};
+    int read_len = 0;
+    int temp=0;
+    int result=1;
+    
+    mnl_set_pwrctl(1);
+
+    int cnt_1s=0;
+    int retry_cnt=0;
+    do{
+        temp = read(g_fd_mt3333_data, buff, sizeof(buff)-1-read_len);
+        if(temp<=0){
+            temp=0;
+        }
+        read_len += temp;
+        usleep(100 * 1000);
+        if((++cnt_1s) > 30){// wait 3s
+            
+            LOGE("read summary len=%d", read_len);
+            cnt_1s = 0;
+            read_len =0;
+            retry_cnt++;
+            mnl_set_pwrctl(4);// reset 3333 power
+        }
+        if(retry_cnt > 1){
+            LOGE("retry max count=5, maybe chip is broken");
+            mnl_set_pwrctl(0);
+            return result;
+        }
+    }while(read_len<31);
+    
+    LOGE("read len=%d,content=%s", read_len,buff);
+    for(int i=0; i<sizeof(buff); i++){
+        if(buff[i] >= 0x80){
+            result=0;
+            break;
+        }
+    }
+    mnl_set_pwrctl(0);
+    LOGE("result= %d",result); 
+    return result;
+}
+
+
+void* mt3333_thread_data(void *arg) {
+    #define MAX_EPOLL_EVENT 1
+    //timer_t hdlr_timer = init_timer(mt3333_controller_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_mt3333_data) == -1) {
+        LOGE("epoll_add_fd() failed for g_fd_mt3333_data failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_mt3333_data) {
+                if (events[i].events & EPOLLIN) {
+                    mt3333_data_event_hdlr(g_fd_mt3333_data);
+                }
+            } else {
+                LOGE("unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        
+    }
+    pthread_exit(NULL);
+    LOGE("exit");
+    return 0;
+}
+
+
+
+int mt3333_controller_init() {
+    pthread_t pthread_mt3333_controller;
+    pthread_t pthread_mt3333_data;
+    pthread_t pthread_mt3333_data_debug;
+    pthread_t pthread_flashtool;
+
+    g_fd_mt3333_controller = socket_bind_udp(MNLD_MT3333_CONTROLLER_SOCKET);
+    if (g_fd_mt3333_controller < 0) {
+        LOGE("socket_bind_udp(MNLD_MT3333_CONTROLLER_SOCKET) failed");
+        return -1;
+    }
+
+    g_fd_mt3333_data= open(MT3333_CONTROLLER_TTY_NAME, O_RDWR|O_NOCTTY|O_NONBLOCK);
+    if (g_fd_mt3333_data < 0) {
+        LOGE("no gps hardware detected: %s:%d, %s", MT3333_CONTROLLER_TTY_NAME, g_fd_mt3333_data, strerror(errno));
+        return -1;
+    }
+
+    if(flashtool_file_isvalid()){
+        pthread_create(&pthread_flashtool, NULL, flashtool_download_thread, NULL);
+    }else{
+#if 1
+        LOGE("uart baudrate:%d", mnld_cfg.init_speed);
+        if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(g_fd_mt3333_data ,mnld_cfg.init_speed, 8, 'N', 1)){
+            LOGE("configure uart baudrate failed");
+            return -1;
+        }
+        if(1 != mt3333_controller_check_if_gpsfunctionok()){
+        #if 0    
+            if(0 != mt3333_controller_set_baudrate_length_parity_stopbits(
+                g_fd_mt3333_data ,
+                mnld_cfg.init_speed == 115200?921600:115200, 
+                8, 'N', 1)){
+                LOGE("configure uart baudrate failed");
+                return -1;
+            }
+        #endif    
+        }
+#endif
+        
+        pthread_create(&pthread_mt3333_controller, NULL, mt3333_thread_control, NULL);
+
+        pthread_create(&pthread_mt3333_data, NULL, mt3333_thread_data, NULL);
+
+        pthread_create(&pthread_mt3333_data_debug, NULL, mt3333_thread_data_debug, NULL);
+    }
+    
+    return 0;
+}
+
+
+int mt3333_controller_socket_send_cmd(main_mt3333_controller_event cmd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, cmd);
+    //put_int(buff, &offset, delete_aiding_data_flags);
+    return safe_sendto(MNLD_MT3333_CONTROLLER_SOCKET, buff, offset);
+}
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/mtknav.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mtknav.c
new file mode 100644
index 0000000..856bad6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/mtknav.c
@@ -0,0 +1,433 @@
+#include <errno.h>   /* Error number definitions */
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mtk_gps_agps.h"
+#include "agps_agent.h"
+#include "data_coder.h"
+#include "mnl_common.h"
+#include "mnld.h"
+#include "mtk_lbs_utility.h"
+#include "epo.h"
+#include "mtknav.h"
+#include "curl.h"
+#include "easy.h"
+#include "mtk_gps.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtknav"
+#endif
+
+#ifdef GPS_EPO_FILE_LEN
+#undef GPS_EPO_FILE_LEN
+#define GPS_EPO_FILE_LEN  20
+#endif
+
+static char mtknav_file_name[GPS_EPO_FILE_LEN] = {0};
+static char mtknav_md5_file_name[GPS_EPO_FILE_LEN] = {0};
+
+bool mtknav_update_flag = false;
+int mtknav_res = EPO_DOWNLOAD_RESULT_FAIL;
+
+static int mtknav_file_update_impl();
+typedef enum {
+    MAIN2MTKNAV_EVENT_START            = 0,
+} main2mtknav_event;
+
+typedef struct mtknav_dl_state {
+    bool MD5_DL_Today;
+    bool DAT_DL_Today;
+    int  last_DL_Date;
+    unsigned int retry_time;
+}MTKNAV_STATE_T;
+
+static int g_fd_mtknav;
+static int mtknav_downloading = 0;
+static MTKNAV_STATE_T dl_state = {
+    .MD5_DL_Today = false,
+    .DAT_DL_Today = false,
+    .last_DL_Date = -1,
+    .retry_time = 0,
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// static functions
+
+static int counter = 1;
+
+static void check_mtknav_file_exist(void) {
+    if ( (access(MTKNAV_MD5_FILE, F_OK) == -1) ||
+         (access(MTKNAV_DAT_FILE, F_OK) == -1) ) {
+        LOGD("mtknav file does not exist, need download\n");
+        dl_state.MD5_DL_Today = false;
+        dl_state.DAT_DL_Today = false;
+        dl_state.retry_time = 0;
+    }
+}
+
+static CURLcode curl_easy_download_mtknav_DAT(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_mtknav_DAT");
+    getEpoUrl(mtknav_file_name, url);
+    res = curl_easy_download(url, MTKNAV_DAT_FILE_HAL);
+
+    LOGD("mtknav DAT file curl_easy_download res = %d\n", res);
+    if (res == 0) {
+        counter = 1;
+        res_val = chmod(MTKNAV_DAT_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        counter++;
+    }
+    return res;
+}
+
+static CURLcode curl_easy_download_mtknav_MD5(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_mtknav_MD5");
+    getEpoUrl(mtknav_md5_file_name, url);
+    res = curl_easy_download(url, MTKNAV_MD5_FILE_HAL);
+
+    LOGD("mtknav MD5 file curl_easy_download res = %d\n", res);
+    if (res == 0) {
+        counter = 1;
+        res_val = chmod(MTKNAV_MD5_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        LOGD("chmod MD5 res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        counter++;
+    }
+    return res;
+}
+
+static int mtknav_MD5_file_check(void) {
+    int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    FILE *fp_old = NULL;
+    FILE *fp_new = NULL;
+    int new_file_size = 0;
+    char old_md5[40];  // length = 40 because current our md5 file size is 37bytes, but only first 32 bytes are useful.
+    char new_md5[40];
+
+    memset(old_md5, 0x00, sizeof(old_md5));
+    memset(new_md5, 0x00, sizeof(new_md5));
+
+    if (is_file_exist(MTKNAV_MD5_FILE_HAL) == 0) {
+        LOGE("new mtknav MD5 file doesn't exist, download failed!");
+        return EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    }
+
+    if (is_file_exist(MTKNAV_MD5_FILE) == 0) {
+        LOGW("old mtknav MD5 file doesn't exist");
+        new_file_size = get_file_size(MTKNAV_MD5_FILE_HAL);
+        if (new_file_size < 32) {
+            ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+            if (delete_file(MTKNAV_MD5_FILE_HAL) == -1) {
+                LOGW("delete %s file error",MTKNAV_MD5_FILE_HAL);
+            }
+        } else {
+            ret = EPO_MD5_FILE_UPDATED;
+            if (rename(MTKNAV_MD5_FILE_HAL, MTKNAV_MD5_FILE) == -1) {  //update MTKNAV.MD5 on local
+                LOGW("MD5 rename error");
+            }
+        }
+    } else {
+        new_file_size = get_file_size(MTKNAV_MD5_FILE_HAL);
+        if (new_file_size < 32) {
+            ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+            if (delete_file(MTKNAV_MD5_FILE_HAL) == -1) {
+                LOGW("delete %s file error",MTKNAV_MD5_FILE_HAL);
+            }
+        } else {
+            fp_old = fopen(MTKNAV_MD5_FILE, "r");
+            if (fp_old != NULL) {
+                if (fread(old_md5, 32, 1, fp_old) != 32) {  //only first 32 bytes are useful.
+                    LOGW("read old MD5 file error");
+                }
+                fclose(fp_old);
+            }
+            fp_new = fopen(MTKNAV_MD5_FILE_HAL, "r");
+            if (fp_new != NULL) {
+                if (fread(new_md5, 32, 1, fp_new) != 32) {
+                    LOGW("read new MD5 file error");
+                }
+                fclose(fp_new);
+            }
+            if (strncmp(old_md5,new_md5,32) != 0) {
+                if (rename(MTKNAV_MD5_FILE_HAL, MTKNAV_MD5_FILE) == -1) { //update MTKNAV.MD5 on local only when file content update
+                    LOGW("MD5 rename error");
+                }
+                ret = EPO_MD5_FILE_UPDATED;
+            } else {
+                ret = EPO_MD5_FILE_NO_UPDATE;
+                if (delete_file(MTKNAV_MD5_FILE_HAL) == -1) {
+                    LOGW("delete %s file error",MTKNAV_MD5_FILE_HAL);
+                }
+            }
+        }
+    }
+    return ret;
+}
+
+static int is_mtknav_file_valid(void) {
+    int fd = 0;
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    fd = open(MTKNAV_DAT_FILE_HAL, O_RDONLY);
+    if (fd < 0) {
+        LOGE("Open mtknav fail(%s), return\n",strerror(errno));
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+    } else {
+        ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+        close(fd);
+    }
+    return ret;
+}
+
+static int mtknav_DAT_download_process(void) {
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+    LOGD("mtknav_DAT_download_process begin");
+
+    MNLD_STRNCPY(mtknav_file_name, "MTKNAV.DAT", sizeof(mtknav_file_name));
+    if (curl_easy_download_mtknav_DAT() == CURLE_OK) {
+        LOGD("download mtknav DAT file success,CURLE_OK");
+        if (is_mtknav_file_valid() == EPO_DOWNLOAD_RESULT_SUCCESS) {
+            LOGD("Check mtknav DAT file ok");
+            ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+        } else {
+            dl_state.retry_time++;
+            ret = EPO_DOWNLOAD_RESULT_FAIL;
+            LOGW("check mtknav DAT file error, retry:%d",dl_state.retry_time);
+        }
+    } else {
+        LOGW("download mtknav MD5 file failed");
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+    }
+    return ret;
+}
+
+static int mtknav_MD5_download_process(void) {
+    LOGD("mtknav_MD5_download_process begin");
+    int ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    MNLD_STRNCPY(mtknav_md5_file_name, "MTKNAV.MD5", sizeof(mtknav_md5_file_name));
+    if (curl_easy_download_mtknav_MD5() == CURLE_OK) {
+        LOGD("mtknav MD5 download success, start to check");
+        ret = mtknav_MD5_file_check();
+    } else {
+        LOGW("download mtknav MD5 file failed");
+        ret = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    }
+    return ret;
+}
+
+static int mtknav_file_update_impl() {
+    int ret_MD5 = EPO_MD5_DOWNLOAD_RESULT_FAIL;
+    int ret_DAT = EPO_DOWNLOAD_RESULT_FAIL;
+
+    ret_MD5 = mtknav_MD5_download_process();
+    if (ret_MD5 != EPO_MD5_DOWNLOAD_RESULT_FAIL) {
+        LOGD("MD5 download success, no need download any more today");
+        dl_state.MD5_DL_Today = true;
+    }
+
+    if (ret_MD5 == EPO_MD5_FILE_NO_UPDATE) {
+        dl_state.DAT_DL_Today = true;  // new MD5 match old MD5, no need download DAT any more
+        return EPO_DOWNLOAD_RESULT_NO_UPDATE;
+    }
+
+    if (ret_MD5 == EPO_MD5_FILE_UPDATED) {
+        ret_DAT = mtknav_DAT_download_process();
+    }
+
+    if (ret_DAT == EPO_DOWNLOAD_RESULT_SUCCESS) {
+        LOGD("DAT download success, no need download any more today");
+        dl_state.DAT_DL_Today = true;
+    }
+    return ret_DAT;
+}
+
+void mtknav_update_mtknav_file(int mtknav_valid) {
+    int xdownload_status = MTK_MTKNAV_RSP_DOWNLOAD_FAIL;
+
+    if (mtknav_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+        //if (mtk_agps_agent_mtknav_file_update() == MTK_GPS_ERROR) {
+        if (1) {
+            xdownload_status = MTK_MTKNAV_RSP_UPDATE_FAIL;
+        } else {
+            LOGD("Update mtknav file successfully");
+            xdownload_status = MTK_MTKNAV_RSP_UPDATE_SUCCESS;
+            unlink(MTKNAV_DAT_FILE_HAL);
+        }
+    } else if (mtknav_valid == EPO_DOWNLOAD_RESULT_NO_UPDATE) {
+        xdownload_status = MTK_MTKNAV_RSP_NO_UPDATE;
+    } else if (mtknav_valid == EPO_DOWNLOAD_RESULT_RETRY_TOO_MUCH) {
+        xdownload_status = MTK_MTKNAV_RSP_DOWNLOAD_FAIL;
+    } else {
+        xdownload_status = MTK_MTKNAV_RSP_DOWNLOAD_FAIL;
+    }
+
+    LOGD("xdownload_status = 0x%x\n", xdownload_status);
+    if (MTK_GPS_ERROR ==  (mtk_agps_set_param (MTK_PARAM_MTKNAV_DOWNLOAD_RESPONSE,
+        &xdownload_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT))) {
+        LOGE("GPS MTKNAV update fail\n");
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// MAIN -> MTKNAV Download (handlers)
+static int mnld_mtknav_download() {
+    int ret;
+    struct tm  tm;
+    time_t now = time(NULL);
+    gmtime_r(&now, &tm);
+
+    check_mtknav_file_exist();
+
+    LOGD("dl_state_date:%d, system_date:%d, MD5_flag:%d, DAT_flag:%d, retry:%d",
+        dl_state.last_DL_Date,tm.tm_mday, dl_state.MD5_DL_Today, dl_state.DAT_DL_Today,dl_state.retry_time);
+
+    if (dl_state.last_DL_Date != tm.tm_mday) {
+        dl_state.MD5_DL_Today = false;
+        dl_state.DAT_DL_Today = false;
+        dl_state.retry_time = 0;
+        dl_state.last_DL_Date = tm.tm_mday;
+        LOGD("First mtknav request today, day is %d", dl_state.last_DL_Date);
+    }
+
+    if ((dl_state.DAT_DL_Today == false) && (dl_state.retry_time <= MTKNAV_DL_RETRY_TIME)) {
+        mtknav_downloading = 1;
+        ret = mtknav_file_update_impl();
+        mtknav_downloading = 0;
+    } else if (dl_state.DAT_DL_Today == true) {
+        LOGW("mtknav has been downloaded today");
+        ret = EPO_DOWNLOAD_RESULT_NO_UPDATE;
+    } else {
+        LOGW("mtknav has been retry too much, retry time=%d",dl_state.retry_time);
+        ret = EPO_DOWNLOAD_RESULT_RETRY_TOO_MUCH;
+    }
+    mtknav_res = ret;
+    if(mnld_mtknav_download_done(ret) == -1){
+        LOGW("mtknav has not download done");
+    }
+    return ret;
+}
+
+static int mtknav_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main2mtknav_event cmd;
+    int read_len;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("mtknav_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    cmd = get_int(buff, &offset, sizeof(buff));
+    switch (cmd) {
+    case MAIN2MTKNAV_EVENT_START: {
+        LOGW("mnld_mtknav_download() before");
+        mnld_mtknav_download();
+        LOGW("mnld_mtknav_download() after");
+        break;
+    }
+    default: {
+        LOGE("mtknav_event_hdlr() unknown cmd=%d", cmd);
+        return -1;
+    }
+    }
+    return 0;
+}
+
+static void* mtknav_downloader_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    //timer_t hdlr_timer = init_timer(qepo_downloader_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("mtknav_downloader_thread() epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_mtknav) == -1) {
+        LOGE("mtknav_downloader_thread() epoll_add_fd() failed for g_fd_mtknav failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("mtknav_downloader_thread wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("mtknav_downloader_thread() epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        //start_timer(hdlr_timer, MNLD_QEPO_HANDLER_TIMEOUT);
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_mtknav) {
+                if (events[i].events & EPOLLIN) {
+                    mtknav_event_hdlr(g_fd_mtknav);
+                }
+            } else {
+                LOGE("mtknav_downloader_thread() unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        //stop_timer(hdlr_timer);
+    }
+
+    LOGE("mtknav_downloader_thread() exit");
+    return 0;
+}
+
+int mtknav_downloader_start() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    if (mtknav_downloading == 1) {
+        LOGW("mtknav downloading... abort requst msg!");
+        return 0;
+    }
+    put_int(buff, &offset, MAIN2MTKNAV_EVENT_START);
+    return safe_sendto(MNLD_MTKNAV_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int mtknav_downloader_init() {
+    pthread_t pthread_mtknav;
+
+    g_fd_mtknav = socket_bind_udp(MNLD_MTKNAV_DOWNLOAD_SOCKET);
+    if (g_fd_mtknav < 0) {
+        LOGE("socket_bind_udp(%s) failed",MNLD_MTKNAV_DOWNLOAD_SOCKET);
+        return -1;
+    }
+
+    pthread_create(&pthread_mtknav, NULL, mtknav_downloader_thread, NULL);
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/nmea_parser.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/nmea_parser.c
new file mode 100644
index 0000000..db19f2a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/nmea_parser.c
@@ -0,0 +1,975 @@
+// SPDX-License-Identifier: MediaTekProprietary
+/* 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) 2016. 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.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#define _NMEA_PARSER_C_
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <errno.h>
+#include <stdio.h>   /* Standard input/output definitions */
+#include <string.h>  /* String function definitions */
+#include <stdlib.h>
+#include <sys/time.h>
+#include <math.h>
+#include "mnld.h"
+#include "mtk_gps.h"
+#include "mnl2hal_interface.h"
+#include "nmea_parser.h"
+#include "mtk_lbs_utility.h"
+#include "mnl_at_interface.h"
+#include "mtk_auto_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+
+extern int g_agc_level;
+
+#define CARRIER_FREQ_GPS_L1    (1575.42*1000000)
+#define CARRIER_FREQ_GPS_L5    (1176.45*1000000)
+#define CARRIER_FREQ_GLO_L1    (1602*1000000)
+#define CARRIER_FREQ_GAL_E1    (1575.42*1000000)
+#define CARRIER_FREQ_GAL_E5A   (1176.45*1000000)
+#define CARRIER_FREQ_BD_B1     (1561.098*1000000)
+#define CARRIER_FREQ_BD_B2     (1207.14*1000000)
+#define CARRIER_FREQ_BD_B3     (1268.52*1000000)
+
+#define NEMA_DEBUG 0
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "nmea_parser"
+#endif
+
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+static int gps_nmea_end_tag = 0;
+
+static NmeaCash nmea_cash[450];
+
+extern int prn[32];
+extern int snr[32];
+extern int MNL_AT_TEST_FLAG;
+extern int MNL_AT_SIGNAL_MODE;
+
+#ifdef CONFIG_GPS_MT3303
+extern MNL_CONFIG_T mnl_config;
+extern int is_ygps_delete_data ;
+extern unsigned int assist_data_bit_map;
+static int has_accuracy = 0;
+int first_entry = 0;
+#endif
+
+/******************************************************************************
+ * Functions
+******************************************************************************/
+static void nmea_reader_update_utc_diff(NmeaReader* const r) {
+    time_t         now = time(NULL);
+    struct tm      tm_local;
+    struct tm      tm_utc;
+    unsigned long  time_local, time_utc;
+
+    gmtime_r(&now, &tm_utc);
+    localtime_r(&now, &tm_local);
+    tm_local.tm_isdst = -1;
+    tm_utc.tm_isdst = -1;
+    time_local = mktime(&tm_local);
+    time_utc = mktime(&tm_utc);
+
+    r->utc_diff = time_utc - time_local;
+}
+
+void nmea_reader_init(NmeaReader* const r) {
+    memset( r, 0, sizeof(*r) );
+
+    r->pos      = 0;
+    r->overflow = 0;
+    r->utc_year = -1;
+    r->utc_mon  = -1;
+    r->utc_day  = -1;
+    r->utc_diff = 0;
+    r->sv_count = 0;
+    r->fix_mode = 0;    /*no fix*/
+    r->cb_status_changed = 0;
+    memset((void*)&r->sv_status, 0x00, sizeof(r->sv_status));
+    memset((void*)r->in, 0x00, sizeof(r->in));
+
+    nmea_reader_update_utc_diff(r);
+}
+
+static int nmea_tokenizer_init(NmeaTokenizer*  t, const char*  p, const char*  end) {
+    int    count = 0;
+
+    // the initial '$' is optional
+    if (p < end && p[0] == '$')
+        p += 1;
+
+    // remove trailing newline
+    if (end > p && end[-1] == '\n') {
+        end -= 1;
+        if (end > p && end[-1] == '\r')
+            end -= 1;
+    }
+
+    // get rid of checksum at the end of the sentecne
+    if (end >= p+3 && end[-3] == '*') {
+        end -= 3;
+    }
+
+    while (p < end) {
+        const char*  q = p;
+
+        q = memchr(p, ',', end-p);
+        if (q == NULL)
+            q = end;
+
+        if (q >= p) {
+            if (count < MAX_NMEA_TOKENS) {
+                t->tokens[count].p   = p;
+                t->tokens[count].end = q;
+                count += 1;
+            }
+        }
+        if (q < end)
+            q += 1;
+
+        p = q;
+    }
+
+    t->count = count;
+    return count;
+}
+
+static Token nmea_tokenizer_get(NmeaTokenizer* t, int  index) {
+    Token  tok;
+    static const char*  dummy = "";
+
+    if (index < 0 || index >= t->count) {
+        tok.p = tok.end = dummy;
+    } else
+        tok = t->tokens[index];
+
+    return tok;
+}
+
+static double str2float(const char*    p, const char*  end) {
+    int   len    = end - p;
+    char  temp[16];
+
+    if (len >= (int)sizeof(temp))
+        return 0.;
+
+    memcpy(temp, p, len);
+    temp[len] = 0;
+    return strtod( temp, NULL );
+}
+
+static int nmea_reader_update_altitude(NmeaReader* const r,
+                   Token altitude,
+                   Token units) {
+    Token   tok = altitude;
+    UNUSED(units);
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_ALT;
+    r->fix.alt = str2float(tok.p, tok.end);
+    return 0;
+}
+
+static int nmea_reader_update_time(NmeaReader* const r, Token  tok) {
+    int        hour, minute;
+    double     seconds;
+    struct tm  tm;
+    time_t     fix_time;
+
+    if (tok.p + 6 > tok.end)
+        return -1;
+
+    memset((void*)&tm, 0x00, sizeof(tm));
+    if (r->utc_year < 0) {
+        // no date yet, get current one
+        time_t  now = time(NULL);
+        gmtime_r(&now, &tm);
+        r->utc_year = tm.tm_year + 1900;
+        r->utc_mon  = tm.tm_mon + 1;
+        r->utc_day  = tm.tm_mday;
+    }
+
+    hour    = str2int(tok.p,   tok.p+2);
+    minute  = str2int(tok.p+2, tok.p+4);
+    seconds = str2float(tok.p+4, tok.end);
+
+    tm.tm_hour = hour;
+    tm.tm_min  = minute;
+    tm.tm_sec  = (int) seconds;
+    tm.tm_year = r->utc_year - 1900;
+    tm.tm_mon  = r->utc_mon - 1;
+    tm.tm_mday = r->utc_day;
+    tm.tm_isdst = -1;
+
+    if (mktime(&tm) == (time_t)-1)
+        LOGE("mktime error: %d %s\n", errno, strerror(errno));
+
+    // Add by ZQH to recalculate the utc_diff when the time zone is reset
+    nmea_reader_update_utc_diff(r);
+    fix_time = mktime(&tm) - r->utc_diff;
+    r->fix.timestamp = (long long)fix_time * 1000;
+    return 0;
+}
+
+static int nmea_reader_update_date(NmeaReader* const r, Token  date, Token  time) {
+    Token  tok = date;
+    int    day, mon, year;
+
+    if (tok.p + 6 != tok.end) {
+        LOGE("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
+        return -1;
+    }
+    day  = str2int(tok.p, tok.p+2);
+    mon  = str2int(tok.p+2, tok.p+4);
+    year = str2int(tok.p+4, tok.p+6) + 2000;
+
+    if ((day|mon|year) < 0) {
+        LOGE("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
+        return -1;
+    }
+
+    r->utc_year  = year;
+    r->utc_mon   = mon;
+    r->utc_day   = day;
+
+    return nmea_reader_update_time( r, time );
+}
+
+static double convert_from_hhmm(Token  tok) {
+    double  val     = str2float(tok.p, tok.end);
+    int     degrees = (int)(floor(val) / 100);
+    double  minutes = val - degrees*100.;
+    double  dcoord  = degrees + minutes / 60.0;
+    return dcoord;
+}
+
+static int nmea_reader_update_latlong(NmeaReader* const r,
+                            Token        latitude,
+                            char         latitudeHemi,
+                            Token        longitude,
+                            char         longitudeHemi) {
+    double   lat, lon;
+    Token    tok;
+
+    tok = latitude;
+    if (tok.p + 6 > tok.end) {
+        LOGE("latitude is too short: '%.*s'", tok.end-tok.p, tok.p);
+        return -1;
+    }
+    lat = convert_from_hhmm(tok);
+    if (latitudeHemi == 'S')
+        lat = -lat;
+
+    tok = longitude;
+    if (tok.p + 6 > tok.end) {
+        LOGE("longitude is too short: '%.*s'", tok.end-tok.p, tok.p);
+        return -1;
+    }
+    lon = convert_from_hhmm(tok);
+    if (longitudeHemi == 'W')
+        lon = -lon;
+
+    r->fix.flags    |= MTK_GPS_LOCATION_HAS_LAT_LONG;
+    r->fix.lat  = lat;
+    r->fix.lng = lon;
+    return 0;
+}
+
+static int nmea_reader_update_bearing(NmeaReader* const r,
+                 Token bearing) {
+    Token    tok = bearing;
+
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_BEARING;
+    r->fix.bearing = str2float(tok.p, tok.end);
+    return 0;
+}
+
+static int nmea_reader_update_speed(NmeaReader* const r,
+                   Token speed) {
+    Token tok = speed;
+
+    if (tok.p >= tok.end)
+        return -1;
+
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_SPEED;
+
+    // Modify by ZQH to convert the speed unit from knot to m/s
+    // r->fix.speed   = str2float(tok.p, tok.end);
+    r->fix.speed = str2float(tok.p, tok.end) / 1.942795467;
+    return 0;
+}
+
+// Add by LCH for accuracy
+static int nmea_reader_update_accuracy(NmeaReader* const r,
+                            Token haccuracy, Token baccuracy, Token saccuracy, Token vaccuracy) {
+    Token   htok = haccuracy;
+    Token   btok = baccuracy;
+    Token   stok = saccuracy;
+    Token   vtok = vaccuracy;
+#ifdef CONFIG_GPS_MT3303
+    if (htok.p >= htok.end)
+#else
+    if (htok.p >= htok.end || btok.p >= btok.end || stok.p >= stok.end || vtok.p >= vtok.end)
+#endif
+        return -1;
+
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_VERTICAL_ACCURACY;
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_SPEED_ACCURACY;
+    r->fix.flags   |= MTK_GPS_LOCATION_HAS_BEARING_ACCURACY;
+
+    r->fix.h_accuracy = str2float(htok.p, htok.end);
+    r->fix.b_accuracy = str2float(btok.p, btok.end);
+    r->fix.s_accuracy = str2float(stok.p, stok.end);
+    r->fix.v_accuracy = str2float(vtok.p, vtok.end);
+
+    LOGD("update accuracy: h=%f, v=%f, s=%f, b= %f", r->fix.h_accuracy, r->fix.v_accuracy,
+        r->fix.s_accuracy, r->fix.b_accuracy);
+    return 0;
+}
+
+static int nmea_reader_update_sv_status(NmeaReader* r, int sv_index,
+                                  int id, Token elevation,
+                                  Token azimuth, Token snr) {
+    // int prn = str2int(id.p, id.end);
+    int prn = id;
+    sv_index = r->sv_count+r->sv_status.num_svs;
+    if (MTK_MNLD_GNSS_MAX_SVS <= sv_index) {
+        LOGE("ERR: sv_index=[%d] is larger than MTK_MNLD_GNSS_MAX_SVS.\n", sv_index);
+        return 0;
+    }
+
+    if ((prn > 0) && (prn <= 32)) {
+        r->sv_status.sv_list[sv_index].svid = prn;
+        r->sv_status.sv_list[sv_index].constellation = GPS_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GPS_L1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else if ((prn >= 65) && (prn <= 96)) {
+        r->sv_status.sv_list[sv_index].svid = prn-64;
+        r->sv_status.sv_list[sv_index].constellation = GLONASS_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GLO_L1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else if ((prn >= 201) && (prn <= 237)) {
+        r->sv_status.sv_list[sv_index].svid = prn-200;
+        r->sv_status.sv_list[sv_index].constellation = BDS_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_BD_B1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else if ((prn >= 401) && (prn <= 436)) {
+        r->sv_status.sv_list[sv_index].svid = prn-400;
+        r->sv_status.sv_list[sv_index].constellation = GALILEO_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GAL_E1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else if ((prn >= 193) && (prn <= 197)) {
+        r->sv_status.sv_list[sv_index].svid = prn;
+        r->sv_status.sv_list[sv_index].constellation = QZSS_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GPS_L1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else if ((prn >= 33) && (prn <= 64)) {
+        r->sv_status.sv_list[sv_index].svid = prn+87;
+        r->sv_status.sv_list[sv_index].constellation = SBAS_SV;
+        r->sv_status.sv_list[sv_index].carrier_frequency = (float)CARRIER_FREQ_GPS_L1;
+        r->sv_status.sv_list[sv_index].flags |= 0x08;
+    } else {
+        LOGW("sv_status: ignore (%d)", prn);
+        return 0;
+    }
+
+    r->sv_status.sv_list[sv_index].c_n0_dbhz = str2float(snr.p, snr.end);
+    r->sv_status.sv_list[sv_index].elevation = str2int(elevation.p, elevation.end);
+    r->sv_status.sv_list[sv_index].azimuth = str2int(azimuth.p, azimuth.end);
+    if (1 == nmea_cash[prn].used_in_fix) {
+        r->sv_status.sv_list[sv_index].flags |= 0x04;
+    } else {
+        r->sv_status.sv_list[sv_index].flags &= ~(0x04);
+    }
+    if (1 == nmea_cash[prn].has_almanac_data) {
+        r->sv_status.sv_list[sv_index].flags |= 0x02;
+    } else {
+        r->sv_status.sv_list[sv_index].flags &= ~(0x02);
+    }
+    if (1 == nmea_cash[prn].has_ephemeris_data) {
+        r->sv_status.sv_list[sv_index].flags |= 0x01;
+    } else {
+        r->sv_status.sv_list[sv_index].flags &= ~(0x01);
+    }
+
+    r->sv_count++;
+    /*
+    #ifdef CONFIG_GPS_ENG_LOAD
+    LOGD("sv_status(%2d): %2d, %d, %2f, %3f, %2f, %d",
+        sv_index, r->sv_status.sv_list[sv_index].svid, r->sv_status.sv_list[sv_index].constellation,
+        r->sv_status.sv_list[sv_index].elevation, r->sv_status.sv_list[sv_index].azimuth,
+        r->sv_status.sv_list[sv_index].c_n0_dbhz, r->sv_status.sv_list[sv_index].flags);
+    #endif
+    */
+    return 0;
+}
+
+static void nmea_reader_parse(NmeaReader* const r) {
+/* we received a complete sentence, now parse it to generate
+* a new GPS fix...
+*/
+    nmea_parser_at_cmd_pre();  // for AT cmd test  check
+
+    NmeaTokenizer  tzer[1];
+    Token          tok;
+    Token          mtok;
+    SV_TYPE sv_type = 1;
+
+    #if NEMA_DEBUG
+    LOGD("Received: '%.*s'", r->pos, r->in);
+    #endif
+    if (r->pos < 9) {
+        LOGE("Too short. discarded. '%.*s'", r->pos, r->in);
+        return;
+    }
+
+    nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
+    #if NEMA_DEBUG
+    {
+        int  n;
+        LOGD("Found %d tokens", tzer->count);
+        for (n = 0; n < tzer->count; n++) {
+            Token  tok = nmea_tokenizer_get(tzer, n);
+            LOGD("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
+        }
+    }
+    #endif
+
+    tok = nmea_tokenizer_get(tzer, 0);
+    if (tok.p + 5 > tok.end) {
+        LOGE("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
+        return;
+    }
+
+    // ignore first two characters.
+    mtok.p = tok.p;  // Mark the first two char for GPS,GLONASS,BDS , GALILEO SV parse.
+    if (!memcmp(mtok.p, "BD", 2)) {
+        sv_type = BDS_SV;
+    } else if (!memcmp(mtok.p, "GP", 2)) {
+        sv_type = GPS_SV;
+    } else if (!memcmp(mtok.p, "GL", 2)) {
+        sv_type = GLONASS_SV;
+    } else if (!memcmp(mtok.p, "GA", 2)) {
+        sv_type = GALILEO_SV;
+    }
+    #ifdef CONFIG_GPS_MT3303
+    else if (!memcmp(mtok.p, "PMTK010", 7)) {
+        Token  result          = nmea_tokenizer_get(tzer, 1);
+        int pmtk010_result = str2int(result.p, result.end);
+        
+        LOGD("[GNSS_Performance]:pmtk010_result: %d, delete state=%d first_entry=%d",
+            pmtk010_result,is_ygps_delete_data, first_entry);
+
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL);
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG);
+
+    #ifdef MTK_ADR_SUPPORT
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF);
+    #endif
+
+        if(pmtk010_result == 1){
+            if(is_ygps_delete_data == 1){
+                is_ygps_delete_data = 2;
+                mt3333_controller_delete_aiding_data(assist_data_bit_map);
+                first_entry = 0;
+                return;
+            }else if(is_ygps_delete_data == 2){
+                is_ygps_delete_data = 0;
+            }else if(is_ygps_delete_data == 10){
+                is_ygps_delete_data = 0;
+            }
+
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUES1STNMEA);
+
+            //mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM);
+            
+        }else if(pmtk010_result == 2){  
+            if(is_ygps_delete_data != 0){
+                return;
+            }   
+
+            if(first_entry == 0){
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_FIXINTERVAL);
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PPS_CONFIG);
+
+                #ifdef MTK_ADR_SUPPORT
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_PMTK876_NMEA_ONOFF);
+                #endif
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_GNSS_SYSTEM);
+                first_entry = 1;
+                LOGD("[GNSS_Performance]:pmtk353_cmd: fix_interval=%d pps_mode=%d pps_duty=%d GNSSOPMode=%d",
+                    mnl_config.fix_interval, mnl_config.pps_mode,mnl_config.pps_duty, mnl_config.GNSSOPMode);
+            } else{
+                first_entry = 0;
+            }
+            LOGD("[GNSS_Performance]:pmtk353_cmd: %d, delete state=%d first_entry=%d", pmtk010_result,
+                is_ygps_delete_data, first_entry);
+
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_NMEA_ONOFF);
+            if(mnl_config.EPO_enabled == 1){
+                //3303 qepo is not  implemented
+                //mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTEPO); 
+            }
+        }
+        return;
+    }
+    else if (!memcmp(mtok.p, "PMTK001", 7)) {
+        gps_nmea_end_tag = 0;
+        Token  cmd          = nmea_tokenizer_get(tzer, 1);
+        Token  cmd_result          = nmea_tokenizer_get(tzer, 2);
+        int pmtk001_cmd = str2int(cmd.p, cmd.end);
+        int pmtk001_cmd_result = str2int(cmd_result.p, cmd_result.end);
+        
+        LOGD("[GNSS_Performance]:pmtk001_cmd: PMTK%03d, cmd result=%d", pmtk001_cmd ,pmtk001_cmd_result);
+
+        
+        if(pmtk001_cmd == 314){
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTNTP);
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTNLP);
+            
+            if(mnl_config.BEE_enabled == 1){
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEASYMODE);
+            }else{
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEASYMODE);
+            }
+            
+            if(mnl_config.dbg2file == 1){
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ENABLEDEBUGLOG);
+            }else{
+                mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_DISABLEDEBUGLOG);
+            }
+        }
+    }
+    if(is_ygps_delete_data != 0){
+        return;
+    }
+#endif
+    #if NEMA_DEBUG
+    LOGD("SV type: %d", sv_type);
+    #endif
+    tok.p += 2;
+    if ( !memcmp(tok.p, "GGA", 3) ) {
+#ifdef CONFIG_GPS_MT3303
+        gps_nmea_end_tag = 0;
+        r->overflow = 0;
+        r->utc_year = -1;
+        r->utc_mon  = -1;
+        r->utc_day  = -1;
+        r->utc_diff = 0;
+        r->sv_count = 0;
+        r->fix_mode = 0;    /*no fix*/
+        r->cb_status_changed = 0;
+        memset((void*)&r->sv_status, 0x00, sizeof(r->sv_status));
+        memset((void*)&r->fix, 0x00, sizeof(r->fix));
+        nmea_reader_update_utc_diff(r);
+#endif
+
+        // GPS fix
+        Token  tok_time          = nmea_tokenizer_get(tzer, 1);
+        Token  tok_latitude      = nmea_tokenizer_get(tzer, 2);
+        Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer, 3);
+        Token  tok_longitude     = nmea_tokenizer_get(tzer, 4);
+        Token  tok_longitudeHemi = nmea_tokenizer_get(tzer, 5);
+        Token  tok_altitude      = nmea_tokenizer_get(tzer, 9);
+        Token  tok_altitudeUnits = nmea_tokenizer_get(tzer, 10);
+
+        nmea_reader_update_time(r, tok_time);
+        nmea_reader_update_latlong(r, tok_latitude,
+            tok_latitudeHemi.p[0],
+            tok_longitude,
+            tok_longitudeHemi.p[0]);
+        nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
+
+    } else if ( !memcmp(tok.p, "GSA", 3) ) {
+        Token tok_fix = nmea_tokenizer_get(tzer, 2);
+        int idx, max = 12;  /*the number of satellites in GPGSA*/
+        r->fix_mode = str2int(tok_fix.p, tok_fix.end);
+
+        if (LOC_FIXED(r)) {  /* 1: No fix; 2: 2D; 3: 3D*/
+            for (idx = 0; idx < max; idx++) {
+                Token tok_satellite = nmea_tokenizer_get(tzer, idx+3);
+                if (tok_satellite.p == tok_satellite.end) {
+                    #if NEMA_DEBUG
+                    LOGD("GSA: found %d active satellites\n", idx);
+                    #endif
+                    break;
+                }
+                int sate_id = str2int(tok_satellite.p, tok_satellite.end);
+                if (sv_type == BDS_SV) {
+                    sate_id += 200;
+                    #if NEMA_DEBUG
+                    LOGD("It is BDS SV: %d", sate_id);
+                    #endif
+                } else if (sv_type == GALILEO_SV) {
+                    sate_id += 400;
+                    #if NEMA_DEBUG
+                    LOGD("It is GALILEO SV: %d", sate_id);
+                    #endif
+                }
+                if (sate_id >= 0 && sate_id < 450) {
+                    nmea_cash[sate_id].prn = sate_id;
+                    nmea_cash[sate_id].used_in_fix = 1;
+                }
+            }
+        }
+    }
+    // VER("GPGSA: mask 0x%x", r->sv_status.used_in_fix_mask);
+    else if (!memcmp(tok.p, "RMC", 3)) {
+        Token  tok_time          = nmea_tokenizer_get(tzer, 1);
+        Token  tok_fixStatus     = nmea_tokenizer_get(tzer, 2);
+        Token  tok_latitude      = nmea_tokenizer_get(tzer, 3);
+        Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer, 4);
+        Token  tok_longitude     = nmea_tokenizer_get(tzer, 5);
+        Token  tok_longitudeHemi = nmea_tokenizer_get(tzer, 6);
+        Token  tok_speed         = nmea_tokenizer_get(tzer, 7);
+        Token  tok_bearing       = nmea_tokenizer_get(tzer, 8);
+        Token  tok_date          = nmea_tokenizer_get(tzer, 9);
+
+        #if NEMA_DEBUG
+        LOGW("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
+        #endif
+        if (tok_fixStatus.p[0] == 'A') {
+            nmea_reader_update_date(r, tok_date, tok_time);
+            nmea_reader_update_latlong(r, tok_latitude,
+                    tok_latitudeHemi.p[0],
+                    tok_longitude,
+                    tok_longitudeHemi.p[0]);
+            nmea_reader_update_bearing(r, tok_bearing);
+            nmea_reader_update_speed(r, tok_speed);
+        }
+    } else if (!memcmp(tok.p+3, "EPH", 3)) {
+        Token tok_num = nmea_tokenizer_get(tzer, 1);    // number of EPH
+        int num = str2int(tok_num.p, tok_num.end);
+        UNUSED(num);
+        int idx, eph = 0;
+        for (idx = 0; idx < GPS_MAX_SVS; idx++) {
+            Token tok_satellite = nmea_tokenizer_get(tzer, idx+2);
+            eph = str2int(tok_satellite.p, tok_satellite.end);
+            if (eph > 0) {
+                nmea_cash[idx+1].has_ephemeris_data = 1;
+                #if NEMA_DEBUG
+                LOGD("eph: %d, sate_id: %d, num: %d\n", eph, idx+1, num);
+                #endif
+            }
+        }
+    } else if (!memcmp(tok.p+3, "ALM", 3)) {
+        Token tok_num = nmea_tokenizer_get(tzer, 1);    // number of ALM
+        int num = str2int(tok_num.p, tok_num.end);
+        UNUSED(num);
+        int idx, alm = 0;
+        for (idx = 0; idx < GPS_MAX_SVS; idx++) {
+            Token tok_satellite = nmea_tokenizer_get(tzer, idx+2);
+            alm = str2int(tok_satellite.p, tok_satellite.end);
+            if (alm > 0) {
+                nmea_cash[idx+1].has_almanac_data = 1;
+                #if NEMA_DEBUG
+                LOGD("alm: %d, sate_id: %d, num: %d\n", alm, idx+1, num);
+                #endif
+            }
+        }
+    } else if (!memcmp(tok.p, "GSV", 3)) {
+        Token tok_num = nmea_tokenizer_get(tzer, 1);  // number of messages
+        Token tok_seq = nmea_tokenizer_get(tzer, 2);  // sequence number
+        Token tok_cnt = nmea_tokenizer_get(tzer, 3);  // Satellites in view
+        int num = str2int(tok_num.p, tok_num.end);
+        int seq = str2int(tok_seq.p, tok_seq.end);
+        int cnt = str2int(tok_cnt.p, tok_cnt.end);
+        int sv_base = (seq - 1)*NMEA_MAX_SV_INFO;
+        int sv_num = cnt - sv_base;
+        int idx, base = 4, base_idx;
+        if (sv_num > NMEA_MAX_SV_INFO)
+            sv_num = NMEA_MAX_SV_INFO;
+        if (seq == 1)    /*if sequence number is 1, a new set of GSV will be parsed*/
+            r->sv_count = 0;
+        for (idx = 0; idx < sv_num; idx++) {
+            base_idx = base*(idx+1);
+            Token tok_id  = nmea_tokenizer_get(tzer, base_idx+0);
+            int sv_id = str2int(tok_id.p, tok_id.end);
+            if (sv_type == BDS_SV) {
+                sv_id += 200;
+                #if NEMA_DEBUG
+                LOGD("It is BDS SV: %d", sv_id);
+                #endif
+            } else if (sv_type == GALILEO_SV) {
+                sv_id += 400;
+                #if NEMA_DEBUG
+                LOGD("It is GALILEO SV: %d", sv_id);
+                #endif
+            }
+            Token tok_ele = nmea_tokenizer_get(tzer, base_idx+1);
+            Token tok_azi = nmea_tokenizer_get(tzer, base_idx+2);
+            Token tok_snr = nmea_tokenizer_get(tzer, base_idx+3);
+            prn[r->sv_count] = str2int(tok_id.p, tok_id.end);
+            snr[r->sv_count] = (int)str2float(tok_snr.p, tok_snr.end);
+
+            nmea_reader_update_sv_status(r, sv_base+idx, sv_id, tok_ele, tok_azi, tok_snr);
+        }
+        if (seq == num) {
+            if (r->sv_count <= cnt) {
+                r->sv_status.num_svs += r->sv_count;
+                if ((1 == MNL_AT_TEST_FLAG) || (1 == MNL_AT_SIGNAL_MODE)) {
+                    LOGD("MNL_AT_TEST_FLAG = %d, MNL_AT_SIGNAL_MODE = %d", MNL_AT_TEST_FLAG, MNL_AT_SIGNAL_MODE);
+                    gps_at_command_test_proc(r);
+                }
+            } else {
+                LOGE("GPGSV incomplete (%d/%d), ignored!", r->sv_count, cnt);
+                r->sv_count = r->sv_status.num_svs = 0;
+            }
+        }
+    }
+    // Add for Accuracy
+    else if (!memcmp(tok.p, "ACCURACY", 8)) {
+#ifdef CONFIG_GPS_MT3303
+        if(!has_accuracy) {
+            has_accuracy = 1;
+        } else {
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND);
+            gps_nmea_end_tag = 1;
+        }
+#endif
+        if ((r->fix_mode == 3) || (r->fix_mode == 2)) {
+            //if(LOC_FIXED(r)) {
+            Token  tok_haccuracy = nmea_tokenizer_get(tzer, 1);
+            Token  tok_baccuracy = nmea_tokenizer_get(tzer, 2);
+            Token  tok_saccuracy = nmea_tokenizer_get(tzer, 3);
+            Token  tok_vaccuracy = nmea_tokenizer_get(tzer, 4);
+
+            nmea_reader_update_accuracy(r, tok_haccuracy, tok_baccuracy, tok_saccuracy, tok_vaccuracy);
+            #if NEMA_DEBUG
+            LOGD("GPS get accuracy from driver:%f\n", r->fix.h_accuracy);
+            #endif
+        }
+    } else if (!memcmp(mtok.p+2, "AG2", 3)) {
+        Token tok_agc = nmea_tokenizer_get(tzer, 2);
+        g_agc_level = str2int(tok_agc.p, tok_agc.end);
+        LOGD("receive PMTKAG2 command, agc: %d\n", g_agc_level);
+    } 
+#ifdef CONFIG_GPS_MT3303
+    else if (!memcmp(mtok.p, "PMTK001", 7) || !memcmp(mtok.p, "PMTK010", 7)) {
+    }else if (!memcmp(tok.p+2, "GRP", 3)) {
+        if(!has_accuracy) {
+            mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_ONCEPERSECOND);
+            gps_nmea_end_tag = 1;
+        }
+    }
+#endif
+    else {
+        tok.p -= 2;
+        LOGW("unknown sentence '%.*s", tok.end-tok.p, tok.p);
+    }
+    if (!LOC_FIXED(r)) {
+        #if NEMA_DEBUG
+        LOGW("Location is not fixed, ignored callback\n");
+        #endif
+    } else if (r->fix.flags != 0 && gps_nmea_end_tag) {
+        #if NEMA_DEBUG
+            char   temp[256];
+            char*  p   = temp;
+            char*  end = p + sizeof(temp);
+            struct tm   utc;
+
+        p += snprintf(p, end-p, "sending fix");
+        if (r->fix.flags & MTK_GPS_LOCATION_HAS_LAT_LONG) {
+            p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.lat, r->fix.lng);
+        }
+        if (r->fix.flags & MTK_GPS_LOCATION_HAS_ALT) {
+            p += snprintf(p, end-p, " altitude=%g", r->fix.alt);
+        }
+        if (r->fix.flags & MTK_GPS_LOCATION_HAS_SPEED) {
+            p += snprintf(p, end-p, " speed=%g", r->fix.speed);
+        }
+        if (r->fix.flags & MTK_GPS_LOCATION_HAS_BEARING) {
+            p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
+        }
+        if (r->fix.flags & MTK_GPS_LOCATION_HAS_HORIZONTAL_ACCURACY) {
+            p += snprintf(p, end-p, " accuracy=%g", r->fix.h_accuracy);
+            LOGD("GPS accuracy=%g\n", r->fix.h_accuracy);
+        }
+        gmtime_r((time_t*) &r->fix.timestamp, &utc);
+        p += snprintf(p, end-p, " time=%s", asctime(&utc));
+        LOGW("%s", temp);
+        #endif
+        mnl2hal_location(r->fix);
+        mnld_gps_update_location(r->fix);
+        r->fix.flags = 0;
+    }
+
+    #if NEMA_DEBUG
+    LOGD("r->sv_status.num_svs = %d, gps_nmea_end_tag = %d", r->sv_status.num_svs, gps_nmea_end_tag);
+    #endif
+    if (gps_nmea_end_tag) {
+        mnl2hal_gps_sv(r->sv_status);
+#ifdef CONFIG_GPS_MT3303
+        if(mnld_is_gps_meas_enabled()){
+            extern gnss_sv_info cts_sv_data;
+            cts_sv_data = r->sv_status;
+        }
+#endif
+
+        r->sv_count = r->sv_status.num_svs = 0;
+        memset((void*)nmea_cash, 0x00, sizeof(nmea_cash));
+    }
+}
+
+static int mtk_mnld_nmea_paser_filter(char* const nmea_stnc, int length)
+{
+    char* buf;
+    int ret = 0;
+
+    if(nmea_stnc == NULL) {
+        LOGE("pointer fail!");
+        return 0;
+    }
+
+    if(length < 6) {
+        LOGE("length fail:%d", length);
+        return 0;
+    }
+
+    buf = nmea_stnc+3; //skip "$GP", "$GL", "$BD", "$GA"
+#ifdef CONFIG_GPS_MT3303
+if ((!memcmp(buf, "GGA", 3)) ||
+     (!memcmp(buf, "GSA", 3)) ||
+     (!memcmp(buf, "RMC", 3)) ||
+     (!memcmp(buf+3, "EPH", 3)) ||
+     (!memcmp(buf+3, "ALM", 3)) ||
+     (!memcmp(buf, "GSV", 3)) ||
+     (!memcmp(buf, "ACCURACY", 8)) ||
+     (!memcmp(buf+2, "001", 3)) ||
+     (!memcmp(buf+2, "010", 3)) ||
+     (!memcmp(buf+2, "AGC", 3)) ||
+     (!memcmp(buf+2, "CLK", 3)) ||
+     (!memcmp(buf+2, "SUPL", 4)) ||
+     (!memcmp(buf+2, "AG2", 3)) ||
+     (!memcmp(buf+2, "GRP", 3))
+#else
+    if ((!memcmp(buf, "GGA", 3)) ||
+        (!memcmp(buf, "GSA", 3)) ||
+        (!memcmp(buf, "RMC", 3)) ||
+        (!memcmp(buf+3, "EPH", 3)) ||
+        (!memcmp(buf+3, "ALM", 3)) ||
+        (!memcmp(buf, "GSV", 3)) ||
+        (!memcmp(buf, "ACCURACY", 8)) ||
+        (!memcmp(buf, "VTG", 3)) ||
+        (!memcmp(buf+2, "TIM", 3)) ||
+        (!memcmp(buf+2, "840", 3)) ||
+        (!memcmp(buf+2, "AGC", 3)) ||
+        (!memcmp(buf+2, "CLK", 3)) ||
+        (!memcmp(buf+2, "SUPL", 4)) ||
+        (!memcmp(buf+2, "AG2", 3))
+#endif
+    ) {
+        ret = 1;
+    } else {
+        ret = 0;
+    }
+
+    return ret;
+}
+
+void nmea_reader_addc(NmeaReader* const r, int  c) {
+    if (r->overflow) {
+        r->overflow = (c != '\n');
+        return;
+    }
+
+    if (r->pos >= NMEA_MAX_SIZE) {
+        r->overflow = 1;
+        r->pos      = 0;
+        return;
+    }
+
+    r->in[r->pos] = (char)c;
+    r->pos += 1;
+
+    if (c == '\n') {
+        if(mtk_mnld_nmea_paser_filter(r->in, r->pos)) {
+            nmea_reader_parse(r);
+        }
+        // LOGD("the structure include nmea_cb address is %p\n", r);
+#ifndef CONFIG_GPS_MT3303
+        mnl2hal_nmea(r->fix.timestamp, r->in, r->pos);
+#else
+        if(is_ygps_delete_data == 0){
+            mnl2hal_nmea(r->fix.timestamp, r->in, r->pos);
+        }
+#endif
+        // LOGD("length: %d, nmea sentence: %s\n", r->pos, r->in);
+        r->pos = 0;
+        memset(r->in, 0x00, NMEA_MAX_SIZE+1);
+    }
+}
+
+void mtk_mnl_nmea_parser_process(const char * buffer, UINT32 length) {
+    UINT32  nn;
+#ifndef CONFIG_GPS_MT3303
+    NmeaReader  reader[1];
+#else
+    static NmeaReader  reader[1]={0};
+#endif
+
+#ifndef CONFIG_GPS_MT3303
+    nmea_reader_init(reader);
+    gps_nmea_end_tag = 0;
+#endif
+
+    for (nn = 0; nn < length; nn++) {
+#ifndef CONFIG_GPS_MT3303
+        if (nn == (length-1)) {
+            gps_nmea_end_tag = 1;
+        }
+#endif
+        nmea_reader_addc(reader, buffer[nn]);
+    }
+}
+
+int get_gps_nmea_parser_end_status() {
+    int ret = 0;
+
+    ret = gps_nmea_end_tag;
+    return ret;
+}
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/op01_log.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/op01_log.c
new file mode 100644
index 0000000..4884303
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/op01_log.c
@@ -0,0 +1,195 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "mtk_lbs_utility.h"
+#include "data_coder.h"
+#include "op01_log.h"
+#include "mnld.h"
+#include "gps_controller.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "op01"
+#endif
+
+typedef enum {
+    MAIN2OP01_EVENT_LOG_WRITE       = 0,
+} main2op01_event;
+
+static int g_fd_op01;
+
+static int send_op01_log_msg(const char *fmt, ...) {
+    char buf[1024] = {0};
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+    va_end(ap);
+
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    put_int(buff, &offset, MAIN2OP01_EVENT_LOG_WRITE);
+    put_string(buff, &offset, buf);
+    return safe_sendto(MNLD_OP01_LOG_WRITER_SOCKET, buff, offset);
+}
+
+static void get_time_stamp(char* time_str1, char* time_str2) {
+    struct tm *tm_pt;
+    time_t time_st;
+    struct timeval tv;
+
+    time(&time_st);
+    gettimeofday(&tv, NULL);
+    tm_pt = gmtime(&time_st);
+    tm_pt = localtime(&tv.tv_sec);
+    memset(time_str1, 0, sizeof(char)*30);
+    memset(time_str2, 0, sizeof(char)*30);
+    if (tm_pt) {
+        sprintf(time_str1, "%d%02d%02d%02d%02d%02d.%1ld",
+            tm_pt->tm_year+1900, tm_pt->tm_mon+1, tm_pt->tm_mday,
+            tm_pt->tm_hour, tm_pt->tm_min, tm_pt->tm_sec, tv.tv_usec/100000);
+        sprintf(time_str2, "%d%02d%02d%02d%02d%02d.%03ld",
+            tm_pt->tm_year+1900, tm_pt->tm_mon+1, tm_pt->tm_mday,
+            tm_pt->tm_hour, tm_pt->tm_min, tm_pt->tm_sec, tv.tv_usec/1000);
+    }
+    LOGE("time_str1=%s,time_str2=%s\n", time_str1, time_str2);
+}
+
+int op01_log_write_internal(const char* log) {
+    // TODO add a configuration to enable/disable the op01 log
+    if (get_file_size(MNLD_OP01_LOG_PATH) > 65535) {
+        LOGD("delete_op01_file=[%s]", MNLD_OP01_LOG_PATH);
+        delete_file(MNLD_OP01_LOG_PATH);
+    }
+    write_msg2file(MNLD_OP01_LOG_PATH, "%s", log);
+    return 0;
+}
+
+static int op01_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main2op01_event cmd;
+    int read_len;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("op01_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    cmd = get_int(buff, &offset, sizeof(buff));
+    switch (cmd) {
+    case MAIN2OP01_EVENT_LOG_WRITE: {
+        char* log = get_string(buff, &offset, sizeof(buff));
+        LOGD("op01_log_write_internal()  log=[%s]", log);
+        op01_log_write_internal(log);
+        break;
+    }
+    default: {
+        LOGE("epo_event_hdlr() unknown cmd=%d", cmd);
+        return -1;
+    }
+    }
+    return 0;
+}
+
+static void op01_log_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("op01_log_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("op01_log_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}
+
+static void* op01_log_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    timer_t hdlr_timer = init_timer(op01_log_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("op01_log_thread() epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_op01) == -1) {
+        LOGE("op01_log_thread() epoll_add_fd() failed for g_fd_op01 failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("op01_log_thread wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("op01_log_thread() epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        start_timer(hdlr_timer, MNLD_OP01_HANDLER_TIMEOUT);
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_op01) {
+                if (events[i].events & EPOLLIN) {
+                    op01_event_hdlr(g_fd_op01);
+                }
+            } else {
+                LOGE("op01_log_thread() unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        stop_timer(hdlr_timer);
+    }
+    LOGE("op01_log_thread() exit");
+    return 0;
+}
+
+int op01_log_gps_start() {
+    char time_str1[30] = {0};
+    char time_str2[30] = {0};
+    get_time_stamp(time_str1, time_str2);
+    return send_op01_log_msg("[%s]0x00000000: %s #gps start\r\n", time_str2, time_str2);
+}
+
+int op01_log_gps_stop() {
+    char time_str1[30] = {0};
+    char time_str2[30] = {0};
+    get_time_stamp(time_str1, time_str2);
+    return send_op01_log_msg("[%s]0x00000001: %s #gps stop\r\n", time_str2, time_str2);
+}
+
+int op01_log_gps_location(double lat, double lng, int ttff) {
+    char time_str1[30] = {0};
+    char time_str2[30] = {0};
+    get_time_stamp(time_str1, time_str2);
+    return send_op01_log_msg("[%s]0x00000002: %s, %f, %f, %d #position(time_stamp, lat, lon, ttff)\r\n",
+        time_str2, time_str2, lat, lng, ttff);
+}
+
+int op01_log_init() {
+    pthread_t pthread_op01;
+
+    g_fd_op01 = socket_bind_udp(MNLD_OP01_LOG_WRITER_SOCKET);
+    if (g_fd_op01 < 0) {
+        LOGE("socket_bind_udp(MNLD_OP01_LOG_WRITER_SOCKET) failed");
+        return -1;
+    }
+
+    pthread_create(&pthread_op01, NULL, op01_log_thread, NULL);
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_entity/src/qepo.c b/src/connectivity/gps/mtk_mnld/mnld_entity/src/qepo.c
new file mode 100644
index 0000000..86e0237
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_entity/src/qepo.c
@@ -0,0 +1,1337 @@
+#include <errno.h>   /* Error number definitions */
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mtk_gps_agps.h"
+#include "agps_agent.h"
+#include "data_coder.h"
+#include "mnl_common.h"
+#include "mnld.h"
+#include "mtk_lbs_utility.h"
+#include "epo.h"
+#include "qepo.h"
+#include "curl.h"
+#include "easy.h"
+#include "gps_controller.h"
+#include "mtk_auto_log.h"
+#ifdef CONFIG_GPS_MT3303
+#include "mt3333_controller.h"
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "qepo"
+#endif
+
+#define QUARTER_FILE_HAL MTK_GPS_DATA_PATH"QEPOHAL.DAT"
+#define QEPO_BD_INVALID_SLEEP (100*1000)  //Delay 100ms before fail response, when the BD QEPO data on server is invalid
+#define QEPO_GA_INVALID_SLEEP (100*1000)  //Delay 100ms before fail response, when the GA QEPO data on server is invalid
+
+static char quarter_epo_file_name[GPS_EPO_FILE_LEN] = {0};
+static char quarter_epo_bd_file_name[GPS_EPO_FILE_LEN] = {0};
+static char quarter_epo_bd_md_file_name[GPS_EPO_FILE_LEN] = {0};
+static char quarter_epo_ga_file_name[GPS_EPO_FILE_LEN] = {0};
+
+static int qepo_file_update_impl();
+typedef enum {
+    MAIN2QEPO_EVENT_START            = 0,
+    MAIN2QEPO_BD_EVENT_START         = 1,
+    MAIN2QEPO_GA_EVENT_START         = 2,
+} main2qepo_event;
+
+typedef struct qepo_gps_time {
+    int wn;
+    int tow;
+    int sys_time;
+}QEPO_GPS_TIME_T;
+
+static QEPO_GPS_TIME_T gps_time;
+static int g_fd_qepo;
+static int qepo_download_finished = 1;
+static int qepo_bd_download_finished = 1;
+static int qepo_ga_download_finished = 1;
+extern int gps_epo_type;
+static time_t g_qbd_latest_dl_time_utc_s = 0;  //Record the latest time of downloading BD QEPO file from server
+static time_t g_qbd_first_invalid_dl_time_utc_s = 0;  //Record the latest time of downloading BD QEPO file from server, and the file is valid
+static int g_qepo_bd_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QBD.DAT file on server is valid or not, valid when init
+static int g_qepo_bd_file_size_correct = MTK_GPS_TRUE;  //The file size is correct or not, correct in init
+static int g_qepo_bd_file_time_correct = MTK_GPS_TRUE;  //The BD QEPO file time is correct or not, correct in init
+int g_qepo_bd_invalid_dl_cnt = 0;
+static time_t g_qga_latest_dl_time_utc_s = 0;  //Record the latest time of downloading BD QEPO file from server
+static time_t g_qga_first_invalid_dl_time_utc_s = 0;  //Record the latest time of downloading BD QEPO file from server, and the file is valid
+static int g_qepo_ga_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QBD.DAT file on server is valid or not, valid when init
+static int g_qepo_ga_file_size_correct = MTK_GPS_TRUE;  //The file size is correct or not, correct in init
+static int g_qepo_ga_file_time_correct = MTK_GPS_TRUE;  //The BD QEPO file time is correct or not, correct in init
+int g_qepo_ga_invalid_dl_cnt = 0;
+bool qepo_update_flag = false;
+int qepo_dl_res = EPO_DOWNLOAD_RESULT_FAIL;
+bool qepo_BD_update_flag = false;
+int qepo_bd_dl_res = EPO_DOWNLOAD_RESULT_FAIL;
+bool qepo_GA_update_flag = false;
+int qepo_ga_dl_res = EPO_DOWNLOAD_RESULT_FAIL;
+#ifdef CONFIG_GPS_MT3303
+extern MNL_CONFIG_T mnl_config;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////
+// static functions
+
+static int pre_day = 0;
+static int server_not_updated = 0;
+static int Qepo_res = 0;
+static int Qepo_bd_res = 0;
+static int Qepo_ga_res = 0;
+static int counter = 1;
+
+#ifndef CONFIG_GPS_MT3303
+static CURLcode curl_easy_download_quarter_epo(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_epo");
+    getEpoUrl(quarter_epo_file_name, url);
+
+    res = curl_easy_download(url, QUARTER_FILE_HAL);
+    LOGD("qepo file curl_easy_download res = %d\n", res);
+    Qepo_res = res;
+    if (res == 0) {
+        counter = 1;
+        res_val = chmod(QUARTER_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        if (res_val < 0) {
+            LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+        }
+    } else {
+        counter++;
+    }
+    return res;
+}
+#else
+static CURLcode curl_easy_download_quarter_epo(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_epo");
+    __getEpoUrl(quarter_epo_file_name, url);
+    res = curl_easy_download(url, QUARTER_FILE_HAL);
+    LOGD("qepo file curl_easy_download res = %d\n", res);
+    Qepo_res = res;
+    if (res == 0) {
+        counter = 1;
+        res_val = chmod(QUARTER_FILE_HAL, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        // LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        counter++;
+    }
+    return res;
+}
+
+#endif
+
+static CURLcode curl_easy_download_quarter_epo_bd(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_bdepo");
+    getEpoUrl(quarter_epo_bd_file_name, url);
+
+    res = curl_easy_download(url, QEPO_BD_UPDATE_FILE);
+
+    LOGD("qbdepo file curl_easy_download res = %d\n", res);
+    Qepo_bd_res = res;
+    if (res == 0) {
+        counter = 1;
+        res_val = chmod(QEPO_BD_UPDATE_FILE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        counter++;
+    }
+    return res;
+}
+
+static CURLcode curl_easy_download_quarter_epo_ga(void) {
+    int res_val;
+    CURLcode res;
+    char url[256]={0};
+
+    LOGD("curl_easy_download_quarter_gaepo");
+    getEpoUrl(quarter_epo_ga_file_name, url);
+
+    res = curl_easy_download(url, QEPO_GA_UPDATE_FILE);
+
+    LOGD("qgaepo file curl_easy_download res = %d\n", res);
+    Qepo_ga_res = res;
+    if (res == 0) {
+        counter = 1;
+        res_val = chmod(QEPO_GA_UPDATE_FILE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH);
+        LOGD("chmod res_val = %d, %s\n", res_val, strerror(errno));
+    } else {
+        counter++;
+    }
+    return res;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_qepo_bd_period_start
+ * DESCRIPTION
+ *  Get the start time of Beidou QEPO file
+ * PARAMETERS
+ *  [IN] fd: The file description of Beidou QEPO file
+ *  [OUT] u4GpsSecs: The start time of Beidou QEPO file in second of GSP time
+ *  [OUT] uSecond: The start time of Beidou QEPO file in second of UTC time
+ * RETURNS
+ *  success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {         // no file lock
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    if (-1 == lseek(fd, MTK_QEPO_BD_HEADER_SIZE, SEEK_SET)) { //Skip the header of BD QEPO file
+        LOGE("lseek error\n");
+        return -1;
+    }
+
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        LOGE("read error\n");
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    // TRC();
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);   // to get UTC second
+    return 0;
+}
+
+int mtk_gps_sys_qepo_ga_period_start(int fd, unsigned int* u4GpsSecs, time_t* uSecond) {         // no file lock
+    char szBuf[MTK_EPO_ONE_SV_SIZE];
+    int pi2WeekNo;
+    unsigned int pu4Tow;
+
+    if (-1 == lseek(fd, MTK_QEPO_GA_HEADER_SIZE, SEEK_SET)) { //Skip the header of GA QEPO file
+        LOGE("lseek error\n");
+        return -1;
+    }
+
+    if (read(fd, szBuf, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        LOGE("read error\n");
+        return -1;
+    }
+
+    *u4GpsSecs = (((*(unsigned int*)(&szBuf[0])) & 0x00FFFFFF) *3600);
+    pi2WeekNo = (*u4GpsSecs) / 604800;
+    pu4Tow = (*u4GpsSecs) % 604800;
+
+    // TRC();
+    GpsToUtcTime(pi2WeekNo, pu4Tow, uSecond);   // to get UTC second
+    return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_qepo_bd_has_epo
+ * DESCRIPTION
+ *  Get the HAS_EPO flag of Beidou QEPO file
+ * PARAMETERS
+ *  [IN] header: The first word value of header in Beidou QEPO file
+ *  [OUT] has_epo: The value of HAS_EPO flag
+ * RETURNS
+ *  success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_has_epo(UINT32 header, int* has_epo) {
+    if (NULL == has_epo) { //Read from the beginning of BD QEPO file
+        LOGE("has_epo pointer check error\n");
+        return -1;
+    }
+
+    if((header&QEPO_BD_HAS_EPO_BIT_MASK) == QEPO_BD_HAS_EPO_BIT_MASK)
+    {
+        *has_epo = MTK_GPS_TRUE;
+        LOGD("BD QEPO has epo(0x%x)!!!\n", header);
+    }else{
+        *has_epo = MTK_GPS_FALSE;
+        LOGE("BD QEPO file error(0x%x), doesn't have epo!!!\n",header);
+    }
+
+    return 0;
+}
+
+int mtk_gps_sys_qepo_ga_has_epo(UINT32 header, int* has_epo) {
+    if (NULL == has_epo) { //Read from the beginning of GA QEPO file
+        LOGE("has_epo pointer check error\n");
+        return -1;
+    }
+
+    if((header&QEPO_GA_HAS_EPO_BIT_MASK) == QEPO_GA_HAS_EPO_BIT_MASK)
+    {
+        *has_epo = MTK_GPS_TRUE;
+        LOGD("GA QEPO has epo(0x%x)!!!\n", header);
+    }else{
+        *has_epo = MTK_GPS_FALSE;
+        LOGE("GA QEPO file error(0x%x), doesn't have epo!!!\n",header);
+    }
+
+    return 0;
+}
+
+/* count the number of 1 in a 32-bit word */
+static UINT32
+gps_mnl_epo_bit_cnt (UINT32 u4BitMask)
+{
+    UINT32 i, u4Cnt = 0;
+
+    for (i = 0; i < 32; i++)
+    {
+        if (1 == ((u4BitMask >> i) & 1))
+        {
+            u4Cnt++;
+        }
+    }
+
+    return  u4Cnt;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_qepo_bd_get_sv_cnt
+ * DESCRIPTION
+ *  Get the SV cnt of Beidou QEPO file
+ * PARAMETERS
+ *  [IN] header: The second word value of header in Beidou QEPO file
+ *  [OUT] sv_cnt: The value of SV count
+ * RETURNS
+ *  success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_get_sv_cnt(UINT32 header, int* sv_cnt) {
+    if (NULL == sv_cnt) { //Read from the beginning of BD QEPO file
+        LOGE("sv_cnt pointer check error\n");
+        return -1;
+    }
+
+    *sv_cnt = gps_mnl_epo_bit_cnt(header);
+    LOGD("sv cnt(0x%x):%d",header,*sv_cnt);
+
+    return 0;
+}
+
+int mtk_gps_sys_qepo_ga_get_sv_cnt(UINT32 header, int* sv_cnt) {
+    if (NULL == sv_cnt) { //Read from the beginning of GA QEPO file
+        LOGE("sv_cnt pointer check error\n");
+        return -1;
+    }
+
+    *sv_cnt = gps_mnl_epo_bit_cnt(header);
+    LOGD("sv cnt(0x%x):%d",header,*sv_cnt);
+
+    return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mtk_gps_sys_qepo_bd_get_header
+ * DESCRIPTION
+ *  Get the header of Beidou QEPO file(72byte)
+ * PARAMETERS
+ *  [IN] fd: The file description of Beidou QEPO file
+ *  [OUT] bd_header: The pointer of HAS_EPO flag
+ * RETURNS
+ *  success(0); failure(-1)
+ *****************************************************************************/
+int mtk_gps_sys_qepo_bd_get_header(int fd, UINT32 bd_header[MTK_EPO_ONE_SV_SIZE/4]) {         // no file lock
+    if(NULL == bd_header )
+    {
+        LOGE("bd_header pointer check error\n");
+        return -1;
+    }
+
+    if (-1 == lseek(fd, 0, SEEK_SET)) { //Read from the beginning of BD QEPO file
+        LOGE("lseek error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    memset(bd_header,0,MTK_EPO_ONE_SV_SIZE);
+    if (read(fd, bd_header, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        LOGE("read error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+int mtk_gps_sys_qepo_ga_get_header(int fd, UINT32 ga_header[MTK_EPO_ONE_SV_SIZE/4]) {         // no file lock
+    if(NULL == ga_header )
+    {
+        LOGE("ga_header pointer check error\n");
+        return -1;
+    }
+
+    if (-1 == lseek(fd, 0, SEEK_SET)) { //Read from the beginning of BD QEPO file
+        LOGE("lseek error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    memset(ga_header,0,MTK_EPO_ONE_SV_SIZE);
+    if (read(fd, ga_header, MTK_EPO_ONE_SV_SIZE) != MTK_EPO_ONE_SV_SIZE) {
+        LOGE("read error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/*****************************************************************************/
+static int is_quarter_epo_valid(void) {
+    unsigned int u4GpsSecs_start;  // GPS seconds
+    time_t uSecond_start;   // UTC seconds
+    time_t mnl_time;
+    time_t *mnl_gps_time = NULL;
+    int fd = 0;
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    fd = open(QUARTER_FILE_HAL, O_RDONLY);
+    if (fd < 0) {
+        LOGE("Open QEPO fail, return\n");
+        return ret;
+    } else {
+        if (mtk_gps_sys_epo_period_start(fd, &u4GpsSecs_start, &uSecond_start)) {
+            LOGE("Read QEPO file failed\n");
+            close(fd);
+            return ret;
+        } else {
+            mnl_gps_time = &mnl_time;
+            //LOGD("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+            GpsToUtcTime(gps_time.wn, gps_time.tow, mnl_gps_time);
+            //LOGD("The Start time of QEPO file is %lld\n", (long long)uSecond_start);
+            LOGD("The start time of QEPO file is %s", ctime(&uSecond_start));
+            LOGD("GPS time: %s", ctime(mnl_gps_time));
+
+            if ((mnl_time >= uSecond_start) && (mnl_time < ((6*60*60) + uSecond_start))) {
+                ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+            } else {
+                ret = EPO_DOWNLOAD_RESULT_FAIL;
+                if (uSecond_start >= ((18*60*60) + mnl_time)) {
+                    // download time 23:55, server has updated
+                    pre_day = 1;
+                } else {
+                    pre_day = 0;
+                }
+                if (mnl_time >= ((24*60*60) + uSecond_start)) {
+                   // download time 00:04,server has not updated
+                   server_not_updated = 1;
+                } else {
+                    server_not_updated = 0;
+                }
+            }
+        }
+        close(fd);
+    }
+    return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  gps_mnl_set_qbd_latest_dl_time
+ * DESCRIPTION
+ *  Set the latest Beidou QEPO download time in second of UTC time
+ * PARAMETERS
+ *  [IN] dl_time: The UTC time to be set
+ * RETURNS
+ *  All ways 0
+ *****************************************************************************/
+static int gps_mnl_set_qbd_latest_dl_time(time_t dl_time)
+{
+    g_qbd_latest_dl_time_utc_s = dl_time;
+
+    return 0;
+}
+
+static int gps_mnl_set_qga_latest_dl_time(time_t dl_time)
+{
+    g_qga_latest_dl_time_utc_s = dl_time;
+
+    return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  gps_mnl_get_qbd_latest_dl_time
+ * DESCRIPTION
+ *  Get the latest Beidou QEPO download time in second of UTC time
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  The value of g_qbd_latest_dl_time_utc_s
+ *****************************************************************************/
+time_t gps_mnl_get_qbd_latest_dl_time(void)
+{
+    return g_qbd_latest_dl_time_utc_s;
+}
+
+time_t gps_mnl_get_qga_latest_dl_time(void)
+{
+    return g_qga_latest_dl_time_utc_s;
+}
+
+ /*****************************************************************************
+  * FUNCTION
+  *  gps_mnl_set_qbd_first_invalid_dl_time
+  * DESCRIPTION
+  *  Set the latest Beidou QEPO invalid download time in second of UTC time
+  *  invalid download: The file has been downloaded to local, but is invalid(size or start time is incorrect)
+  * PARAMETERS
+  *  [IN] dl_time: The UTC time to be set
+  * RETURNS
+  *  All ways 0
+  *****************************************************************************/
+ int gps_mnl_set_qbd_first_invalid_dl_time(time_t dl_time)
+ {
+    g_qbd_first_invalid_dl_time_utc_s = dl_time;
+    return 0;
+ }
+
+ int gps_mnl_set_qga_first_invalid_dl_time(time_t dl_time)
+ {
+    g_qga_first_invalid_dl_time_utc_s = dl_time;
+    return 0;
+ }
+
+ /*****************************************************************************
+  * FUNCTION
+  *  gps_mnl_get_qbd_first_invalid_dl_time
+  * DESCRIPTION
+  *  Get the latest Beidou QEPO invalid download time in second of UTC time
+  *  invalid download: The file has been downloaded to local, but is invalid(size or start time is incorrect)
+  * PARAMETERS
+  *  None
+  * RETURNS
+  *  The value of g_qbd_first_invalid_dl_time_utc_s
+  *****************************************************************************/
+ time_t gps_mnl_get_qbd_first_invalid_dl_time(void)
+ {
+     return g_qbd_first_invalid_dl_time_utc_s;
+ }
+
+ time_t gps_mnl_get_qga_first_invalid_dl_time(void)
+ {
+     return g_qga_first_invalid_dl_time_utc_s;
+ }
+
+ /*****************************************************************************
+  * FUNCTION
+  *  gps_mnl_qbd_has_epo
+  * DESCRIPTION
+  *  Get the value of g_qepo_bd_has_epo
+  * PARAMETERS
+  *  None
+  * RETURNS
+  *  The value of g_qepo_bd_has_epo
+  *****************************************************************************/
+int gps_mnl_qbd_has_epo(void)
+{
+    return g_qepo_bd_has_epo;
+}
+
+int gps_mnl_qga_has_epo(void)
+{
+    return g_qepo_ga_has_epo;
+}
+
+ /*****************************************************************************
+  * FUNCTION
+  *  gps_mnl_epo_get_file_size
+  * DESCRIPTION
+  *  Get the file size
+  * PARAMETERS
+  *  [IN] fd: The file description
+  * RETURNS
+  *  File size
+  *****************************************************************************/
+int gps_mnl_epo_get_file_size(int fd)
+{
+    int u4FileSize;
+
+    if (fd == 0)
+    {
+        return -1;
+    }
+
+    u4FileSize = lseek(fd, 0, SEEK_END);
+
+    if (-1 == u4FileSize) { //lseek fail
+        LOGE("lseek end error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    if (-1 == lseek(fd, 0, SEEK_SET)) { //Back to the start of file
+        LOGE("lseek set error(%s)\n",strerror(errno));
+        return -1;
+    }
+
+    return u4FileSize;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  gps_mnl_bd_qepo_init
+ * DESCRIPTION
+ *  Reset the init condition of BD QEPO
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  None
+ *****************************************************************************/
+void gps_mnl_bd_qepo_init(void)
+{
+        g_qepo_bd_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QBD.DAT file on server is valid or not, valid when init
+        g_qepo_bd_file_size_correct = MTK_GPS_TRUE;  //The file size is correct or not, correct in init
+        g_qepo_bd_file_time_correct = MTK_GPS_TRUE;  //The BD QEPO file time is correct or not, correct in init
+}
+
+void gps_mnl_ga_qepo_init(void)
+{
+        g_qepo_ga_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QGA.DAT file on server is valid or not, valid when init
+        g_qepo_ga_file_size_correct = MTK_GPS_TRUE;  //The file size is correct or not, correct in init
+        g_qepo_ga_file_time_correct = MTK_GPS_TRUE;  //The GA QEPO file time is correct or not, correct in init
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  is_quarter_epo_bd_on_server_valid
+ * DESCRIPTION
+ *  Judge the Beidou QEPO file on server is valid or not
+ *  if invalid, will retry downloading.
+ *  Valid: HAS_EPO flag is true && the time is correct
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  MTK_GPS_TRUE; MTK_GPS_FALSE
+ *****************************************************************************/
+static int is_quarter_epo_bd_on_server_valid(void) {
+    if(g_qepo_bd_file_time_correct == MTK_GPS_TRUE &&
+      g_qepo_bd_has_epo == MTK_GPS_TRUE){
+      return MTK_GPS_TRUE;
+    }else{
+      return MTK_GPS_FALSE;
+    }
+}
+
+static int is_quarter_epo_ga_on_server_valid(void) {
+    if(g_qepo_ga_file_time_correct == MTK_GPS_TRUE &&
+      g_qepo_ga_has_epo == MTK_GPS_TRUE){
+      return MTK_GPS_TRUE;
+    }else{
+      return MTK_GPS_FALSE;
+    }
+}
+
+ /*****************************************************************************
+  * FUNCTION
+  *  is_quarter_epo_bd_valid
+  * DESCRIPTION
+  *  Judge the Beidou QEPO file of current download is valid or not
+  *  if invalid, will retry downloading.
+  *  Valid: file open successfully && get HAS_EPO flag successfully && get start time successfully
+  *           && request time is in the valid durration of current Beidou QEPO file (start time+6H).
+  * PARAMETERS
+  *  None
+  * RETURNS
+  *  EPO_DOWNLOAD_RESULT_FAIL; EPO_DOWNLOAD_RESULT_SUCCESS
+  *****************************************************************************/
+static int is_quarter_epo_bd_valid(void) {
+    unsigned int u4GpsSecs_start;  // GPS seconds
+    time_t current_qbd_start_time_utc_s;   // UTC seconds
+    time_t current_rqst_time_utc_s;
+    time_t current_dl_time_utc_s;
+    UINT32 bd_header_data[MTK_EPO_ONE_SV_SIZE/4] = {0};
+    int file_size = 0;
+    int sv_cnt = 0;
+
+    int fd = 0;
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    fd = open(QEPO_BD_UPDATE_FILE, O_RDONLY);
+    if (fd < 0) {
+        /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+        g_qepo_bd_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QBD.DAT file on server is valid or not
+        g_qepo_bd_file_size_correct = MTK_GPS_FALSE;
+        g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+
+        LOGE("Open QEPO_BD fail(%s), return\n",strerror(errno));
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+        goto func_exit;
+    } else {
+        LOGD("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+        GpsToUtcTime(gps_time.wn, gps_time.tow, &current_rqst_time_utc_s);
+        LOGD("Request GPS time: %s", ctime(&current_rqst_time_utc_s));
+
+        gps_mnl_set_qbd_latest_dl_time(current_rqst_time_utc_s);
+
+        if(mtk_gps_sys_qepo_bd_get_header(fd, bd_header_data)){
+             /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+            g_qepo_bd_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QBD.DAT file on server is valid or not
+            g_qepo_bd_file_size_correct = MTK_GPS_FALSE;
+            g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+
+            LOGE("qepo bd get header fail, return\n");
+            ret = EPO_DOWNLOAD_RESULT_FAIL;
+            goto func_exit;
+        }
+
+        //Check HAS_EPO flag
+        mtk_gps_sys_qepo_bd_has_epo(bd_header_data[0], &g_qepo_bd_has_epo);
+        mtk_gps_sys_qepo_bd_get_sv_cnt(bd_header_data[1], &sv_cnt);
+
+        //Check file size
+        file_size = gps_mnl_epo_get_file_size(fd);
+        LOGD("qepo bd file size:%d\n",file_size);
+        if((file_size==0) || ((file_size%MTK_EPO_ONE_SV_SIZE != 0)||
+            (sv_cnt != (file_size/MTK_EPO_ONE_SV_SIZE-1)))){  //The BD QEPO file size and sv cnt not match, something goes wrong
+            LOGE("qepo bd file size check error\n");
+            g_qepo_bd_file_size_correct = MTK_GPS_FALSE;
+        }else{
+            g_qepo_bd_file_size_correct = MTK_GPS_TRUE;
+        }
+
+        //Check time
+        if (mtk_gps_sys_epo_bd_period_start(fd, &u4GpsSecs_start, &current_qbd_start_time_utc_s)) {
+            /*Something goes wrong, set time correct flag to true for next downloading*/
+            g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+
+            LOGE("Read QEPO file failed\n");
+            ret = EPO_DOWNLOAD_RESULT_FAIL;
+            goto func_exit;
+        } else {
+            LOGD("The Start time of QEPO file is %lld\n", (long long)current_qbd_start_time_utc_s);
+            LOGD("The start time of QEPO file is %s\n", ctime(&current_qbd_start_time_utc_s));
+            current_dl_time_utc_s = current_rqst_time_utc_s+(time((time_t *)NULL)-gps_time.sys_time);
+            LOGD("Time after download: %s\n", ctime(&current_dl_time_utc_s));
+            if ((current_dl_time_utc_s >= current_qbd_start_time_utc_s) && (current_dl_time_utc_s < ((6*60*60) + current_qbd_start_time_utc_s))) {
+                g_qepo_bd_file_time_correct = MTK_GPS_TRUE;
+            }else{
+                LOGE("qepo bd file time check error\n");
+                g_qepo_bd_file_time_correct = MTK_GPS_FALSE;
+            }
+        }
+    }
+
+    if(g_qepo_bd_has_epo == MTK_GPS_TRUE
+        && g_qepo_bd_file_size_correct == MTK_GPS_TRUE
+        && g_qepo_bd_file_time_correct == MTK_GPS_TRUE)
+    {
+        ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+    }else{
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+    }
+
+func_exit:
+    if(fd >= 0){
+        close(fd);
+    }
+
+    return ret;
+}
+
+static int is_quarter_epo_ga_valid(void) {
+    unsigned int u4GpsSecs_start;  // GPS seconds
+    time_t current_qga_start_time_utc_s;   // UTC seconds
+    time_t current_rqst_time_utc_s;
+    time_t current_dl_time_utc_s;
+    UINT32 ga_header_data[MTK_EPO_ONE_SV_SIZE/4] = {0};
+    int file_size = 0;
+    int sv_cnt = 0;
+
+    int fd = 0;
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    fd = open(QEPO_GA_UPDATE_FILE, O_RDONLY);
+    if (fd < 0) {
+        /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+        g_qepo_ga_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QGA.DAT file on server is valid or not
+        g_qepo_ga_file_size_correct = MTK_GPS_FALSE;
+        g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+
+        LOGE("Open QEPO_GA fail(%s), return\n",strerror(errno));
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+        goto func_exit;
+    } else {
+        LOGD("gps_time.wn, tow %d, %d\n", gps_time.wn, gps_time.tow);
+        GpsToUtcTime(gps_time.wn, gps_time.tow, &current_rqst_time_utc_s);
+        LOGD("Request GPS time: %s", ctime(&current_rqst_time_utc_s));
+
+        gps_mnl_set_qga_latest_dl_time(current_rqst_time_utc_s);
+
+        if(mtk_gps_sys_qepo_ga_get_header(fd, ga_header_data)){
+             /*Something goes wrong, set HAS_EPO & time correct flag to true for next downloading*/
+            g_qepo_ga_has_epo = MTK_GPS_TRUE;  //This flag to indentify the QGA.DAT file on server is valid or not
+            g_qepo_ga_file_size_correct = MTK_GPS_FALSE;
+            g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+
+            LOGE("qepo ga get header fail, return\n");
+            ret = EPO_DOWNLOAD_RESULT_FAIL;
+            goto func_exit;
+        }
+
+        //Check HAS_EPO flag
+        mtk_gps_sys_qepo_ga_has_epo(ga_header_data[0], &g_qepo_ga_has_epo);
+        mtk_gps_sys_qepo_ga_get_sv_cnt(ga_header_data[1], &sv_cnt);
+
+        //Check file size
+        file_size = gps_mnl_epo_get_file_size(fd);
+        LOGD("qepo ga file size:%d\n",file_size);
+        if((file_size==0) || ((file_size%MTK_EPO_ONE_SV_SIZE != 0)||
+            (sv_cnt != (file_size/MTK_EPO_ONE_SV_SIZE-1)))){  //The GA QEPO file size and sv cnt not match, something goes wrong
+            LOGE("qepo ga file size check error\n");
+            g_qepo_ga_file_size_correct = MTK_GPS_FALSE;
+        }else{
+            g_qepo_ga_file_size_correct = MTK_GPS_TRUE;
+        }
+
+        //Check time
+        if (mtk_gps_sys_epo_ga_period_start(fd, &u4GpsSecs_start, &current_qga_start_time_utc_s)) {
+            /*Something goes wrong, set time correct flag to true for next downloading*/
+            g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+
+            LOGE("Read QEPO file failed\n");
+            ret = EPO_DOWNLOAD_RESULT_FAIL;
+            goto func_exit;
+        } else {
+            LOGD("The Start time of QEPO file is %lld\n", (long long)current_qga_start_time_utc_s);
+            LOGD("The start time of QEPO file is %s\n", ctime(&current_qga_start_time_utc_s));
+            current_dl_time_utc_s = current_rqst_time_utc_s+(time((time_t *)NULL)-gps_time.sys_time);
+            LOGD("Time after download: %s\n", ctime(&current_dl_time_utc_s));
+            if ((current_dl_time_utc_s >= current_qga_start_time_utc_s) && (current_dl_time_utc_s < ((6*60*60) + current_qga_start_time_utc_s))) {
+                g_qepo_ga_file_time_correct = MTK_GPS_TRUE;
+            }else{
+                LOGE("qepo ga file time check error\n");
+                g_qepo_ga_file_time_correct = MTK_GPS_FALSE;
+            }
+        }
+    }
+
+    if(g_qepo_ga_has_epo == MTK_GPS_TRUE
+        && g_qepo_ga_file_size_correct == MTK_GPS_TRUE
+        && g_qepo_ga_file_time_correct == MTK_GPS_TRUE)
+    {
+        ret = EPO_DOWNLOAD_RESULT_SUCCESS;
+    }else{
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+    }
+
+func_exit:
+    if(fd >= 0){
+        close(fd);
+    }
+
+    return ret;
+}
+
+/*static void
+gps_download_quarter_epo_file_name(int count) {
+    if (gps_epo_type == 1) {
+        if (count == 1) {
+            strncpy(quarter_epo_file_name, "QG_R_1.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 2) {
+            strncpy(quarter_epo_file_name, "QG_R_2.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 3) {
+            strncpy(quarter_epo_file_name, "QG_R_3.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 4) {
+            strncpy(quarter_epo_file_name, "QG_R_4.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 5) {
+            strncpy(quarter_epo_file_name, "QG_R_5.DAT", GPS_EPO_FILE_LEN);
+        }
+        LOGD("quarter_epo_file_name=%s\n", quarter_epo_file_name);
+    } else if (gps_epo_type == 0) {
+        if (count == 1) {
+            strncpy(quarter_epo_file_name, "QG_R_1.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 2)  {
+            strncpy(quarter_epo_file_name, "QG_R_2.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 3) {
+            strncpy(quarter_epo_file_name, "QG_R_3.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 4) {
+            strncpy(quarter_epo_file_name, "QG_R_4.DAT", GPS_EPO_FILE_LEN);
+        } else if (count == 5) {
+            strncpy(quarter_epo_file_name, "QG_R_5.DAT", GPS_EPO_FILE_LEN);
+        }
+        LOGD("quarter_epo_file_name=%s\n", quarter_epo_file_name);
+    }
+}*/
+
+void gps_mnl_set_gps_time(int wn, int tow, int sys_time) {
+    gps_time.wn = wn;
+    gps_time.tow = tow;
+    gps_time.sys_time = sys_time;
+}
+static void quarter_epo_download_process(void) {
+    // LOGD("quarter_epo_download_process begin");
+/*    int index = 1;
+    INT32 SecofDay = gps_time.tow % 86400;
+
+    if ((SecofDay > 300) && (SecofDay <= 21900)) {
+        index = 1;
+    } else if ((SecofDay > 21900) && (SecofDay <= 43500)) {
+        index = 2;
+    } else if ((SecofDay > 43500) && (SecofDay <= 65100)) {
+        index = 3;
+    } else if ((SecofDay > 65100) && (SecofDay <= 85500)) {
+        index = 4;
+    } else if ((SecofDay <= 300) || (SecofDay > 85500)) {
+        if (server_not_updated) {
+            index = 4;
+        } else {
+            index = 5;
+        }
+    }
+
+    if (pre_day) {
+        index = 5;
+    }
+    LOGD("SecofDay = %d , index = %d\n", SecofDay, index);
+    gps_download_quarter_epo_file_name(index);*/
+    strncpy(quarter_epo_file_name, "QG_R.DAT", sizeof(quarter_epo_file_name));
+    curl_easy_download_quarter_epo();
+}
+
+static void quarter_epo_bd_download_process(void) {
+    strncpy(quarter_epo_bd_file_name, "QBD2.DAT",sizeof(quarter_epo_bd_file_name));
+    strncpy(quarter_epo_bd_md_file_name, "QBD2.MD5",sizeof(quarter_epo_bd_md_file_name));
+    curl_easy_download_quarter_epo_bd();
+}
+
+static void quarter_epo_ga_download_process(void) {
+    strncpy(quarter_epo_ga_file_name, "QGA.DAT",sizeof(quarter_epo_ga_file_name));
+    curl_easy_download_quarter_epo_ga();
+}
+
+static int qepo_file_update_impl() {
+    int try_time = QEPO_GR_DL_RETRY_TIME;  // for network issue download failed retry.
+    int qepo_valid = EPO_DOWNLOAD_RESULT_FAIL;
+
+    //LOGD("qepo_download_finished = 0\n");
+    quarter_epo_download_process();
+    while (((qepo_valid = is_quarter_epo_valid()) == EPO_DOWNLOAD_RESULT_FAIL)
+           && (try_time > 0) && is_network_connected()) {
+        try_time--;
+
+        LOGD("qepo download failed try again, try_time = %d\n", try_time);
+        quarter_epo_download_process();
+    }
+    LOGD("try time is %d, qepo_valid is %d\n", try_time, qepo_valid);
+    if (try_time < QEPO_GR_DL_RETRY_TIME) {
+        try_time = QEPO_GR_DL_RETRY_TIME;
+    }
+    if (server_not_updated) {
+        Qepo_res = CURLE_RECV_ERROR;  // server has not updated
+    }
+    return qepo_valid;  // success
+}
+
+static int qepo_bd_file_update_impl() {
+    int qepo_bd_valid = EPO_DOWNLOAD_RESULT_FAIL;
+
+ /*Download directly.
+  *If the notwork is unavailable, will download fail, is_quarter_epo_bd_valid() will return FAIL.
+  *If the network is available and download successfully, is_quarter_epo_bd_valid will return TRUE*/
+    LOGD("qepo download start, network conncet:%d...\n",is_network_connected());
+    quarter_epo_bd_download_process();
+
+    qepo_bd_valid = is_quarter_epo_bd_valid();
+    LOGD("qepo_bd_valid is %d, has epo:%d, file time correct:%d, file size correct:%d\n",  qepo_bd_valid,g_qepo_bd_has_epo,g_qepo_bd_file_time_correct,g_qepo_bd_file_size_correct);
+    if((is_quarter_epo_bd_on_server_valid() == MTK_GPS_FALSE) ||
+        (g_qepo_bd_file_size_correct == MTK_GPS_FALSE))
+    {
+        if(g_qepo_bd_invalid_dl_cnt == 0)
+        {
+            gps_mnl_set_qbd_first_invalid_dl_time(gps_mnl_get_qbd_latest_dl_time());//record the firest invalid download times
+        }
+        g_qepo_bd_invalid_dl_cnt++;
+    }
+
+    return qepo_bd_valid;
+}
+
+static int qepo_ga_file_update_impl() {
+    int qepo_ga_valid = EPO_DOWNLOAD_RESULT_FAIL;
+
+ /*Download directly.
+  *If the notwork is unavailable, will download fail, is_quarter_epo_ga_valid() will return FAIL.
+  *If the network is available and download successfully, is_quarter_epo_ga_valid will return TRUE*/
+    LOGD("qepo download start, network conncet:%d...\n",is_network_connected());
+    quarter_epo_ga_download_process();
+
+    qepo_ga_valid = is_quarter_epo_ga_valid();
+    LOGD("qepo_ga_valid is %d, has epo:%d, file time correct:%d, file size correct:%d\n",  qepo_ga_valid,g_qepo_ga_has_epo,g_qepo_ga_file_time_correct,g_qepo_ga_file_size_correct);
+    if((is_quarter_epo_ga_on_server_valid() == MTK_GPS_FALSE) ||
+        (g_qepo_ga_file_size_correct == MTK_GPS_FALSE))
+    {
+        if(g_qepo_ga_invalid_dl_cnt == 0)
+        {
+            gps_mnl_set_qga_first_invalid_dl_time(gps_mnl_get_qga_latest_dl_time());//record the firest invalid download times
+        }
+        g_qepo_ga_invalid_dl_cnt++;
+    }
+
+    return qepo_ga_valid;
+}
+#ifndef CONFIG_GPS_MT3303
+void qepo_update_quarter_epo_file(int qepo_valid) {
+    int qdownload_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+
+    if (qepo_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+        if (mtk_agps_agent_qepo_file_update() == MTK_GPS_ERROR) {
+            qdownload_status = MTK_QEPO_RSP_UPDATE_FAIL;
+        } else {
+            qdownload_status = MTK_QEPO_RSP_UPDATE_SUCCESS;
+            unlink(QEPO_UPDATE_HAL);
+        }
+    } else {
+        qdownload_status = Qepo_res;
+        if (qdownload_status > 0) {
+            qdownload_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+        }
+    }
+
+    qdownload_status |= ((AGT_QEPO_GP_BIT|AGT_QEPO_GL_BIT)<< MTK_QEPO_RSP_BIT_NUM);
+    LOGD("qdownload_status = 0x%x\n", qdownload_status);
+    if (MTK_GPS_ERROR ==  (mtk_agps_set_param (MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+            &qdownload_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT))) {
+            LOGE("GPS QEPO update fail\n");
+        }
+}
+#else
+void qepo_update_quarter_epo_file(int qepo_valid) {
+    if (qepo_valid == EPO_DOWNLOAD_RESULT_SUCCESS && (mnl_config.EPO_enabled == 1)) {
+        mt3333_controller_socket_send_cmd(MAIN_MT3333_CONTROLLER_EVENT_REQUESTQEPO);
+    }
+}
+
+#endif
+
+void qepo_update_quarter_epo_bd_file(int qepo_bd_valid) {
+    int qdownload_bd_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+
+    if (qepo_bd_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+        if (MTK_GPS_ERROR == mtk_agps_agent_qepo_bd_file_update()) {
+            qdownload_bd_status = MTK_QEPO_RSP_UPDATE_FAIL;
+            LOGE("qdownload_bd_status = %d, download fail\n", qdownload_bd_status);
+    } else {
+            qdownload_bd_status = MTK_QEPO_RSP_UPDATE_SUCCESS;
+            unlink(QEPO_BD_UPDATE_FILE);
+        }
+    } else {
+        if((is_quarter_epo_bd_on_server_valid() == MTK_GPS_TRUE) && (g_qepo_bd_file_size_correct == MTK_GPS_FALSE))
+        {
+             if (MTK_GPS_ERROR == mtk_agps_agent_qepo_bd_file_update()) {
+                qdownload_bd_status = MTK_QEPO_RSP_UPDATE_FAIL;
+                LOGE("qdownload_bd_status = %d, download fail\n", qdownload_bd_status);
+            } else {
+                 qdownload_bd_status = MTK_QEPO_RSP_SIZE_FAIL;
+                unlink(QEPO_BD_UPDATE_FILE);
+        }
+    }
+        else
+        {
+            qdownload_bd_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+        }
+        }
+
+    qdownload_bd_status = qdownload_bd_status |(AGT_QEPO_BD_BIT<< MTK_QEPO_RSP_BIT_NUM);   // high 4 bit
+    if (MTK_GPS_ERROR == (mtk_agps_set_param (MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+        &qdownload_bd_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT)) ) {
+        LOGE("GPS QEPO_BD update fail\n");
+    }
+}
+
+void qepo_update_quarter_epo_ga_file(int qepo_ga_valid) {
+    int qdownload_ga_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+
+    if (qepo_ga_valid == EPO_DOWNLOAD_RESULT_SUCCESS) {
+        if (MTK_GPS_ERROR == mtk_agps_agent_qepo_ga_file_update()) {
+            qdownload_ga_status = MTK_QEPO_RSP_UPDATE_FAIL;
+            LOGE("qdownload_ga_status = %d, download fail\n", qdownload_ga_status);
+        } else {
+            qdownload_ga_status = MTK_QEPO_RSP_UPDATE_SUCCESS;
+            unlink(QEPO_GA_UPDATE_FILE);
+        }
+    } else {
+        if((is_quarter_epo_ga_on_server_valid() == MTK_GPS_TRUE) && (g_qepo_ga_file_size_correct == MTK_GPS_FALSE))
+        {
+            if (MTK_GPS_ERROR == mtk_agps_agent_qepo_ga_file_update()) {
+                qdownload_ga_status = MTK_QEPO_RSP_UPDATE_FAIL;
+                LOGE("qdownload_ga_status = %d, download fail\n", qdownload_ga_status);
+            } else {
+                qdownload_ga_status = MTK_QEPO_RSP_SIZE_FAIL;
+                unlink(QEPO_GA_UPDATE_FILE);
+            }
+        } else {
+            qdownload_ga_status = MTK_QEPO_RSP_DOWNLOAD_FAIL;
+        }
+    }
+
+    qdownload_ga_status = qdownload_ga_status |(AGT_QEPO_GA_BIT<< MTK_QEPO_RSP_BIT_NUM);   // high 4 bit
+    if (MTK_GPS_ERROR == (mtk_agps_set_param (MTK_PARAM_QEPO_DOWNLOAD_RESPONSE,
+        &qdownload_ga_status, MTK_MOD_DISPATCHER, MTK_MOD_AGENT)) ) {
+        LOGE("GPS QEPO_GA update fail\n");
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// MAIN -> EPO Download (handlers)
+static int mnld_qepo_download() {
+    //LOGD("mnld_qepo_download");
+
+    qepo_download_finished = 0;
+    int ret = qepo_file_update_impl();
+    qepo_download_finished = 1;
+    qepo_dl_res = ret;
+    mnld_qepo_download_done(ret);
+    return ret;
+}
+
+static int mnld_qepo_bd_download() {
+    time_t current_rqst_time_utc_s = 0;
+    time_t qbd_rqst_time_diff = 0;
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    GpsToUtcTime(gps_time.wn, gps_time.tow, &current_rqst_time_utc_s);
+
+    qbd_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qbd_first_invalid_dl_time()/SECONDS_PER_HOUR;
+    LOGD("QBD current request time: %ld, latest invalid dl time:%ld, time_diff:%ld,\n", current_rqst_time_utc_s,gps_mnl_get_qbd_first_invalid_dl_time(),qbd_rqst_time_diff);
+    if(qbd_rqst_time_diff != 0){ //Rest the count value hourly
+        g_qepo_bd_invalid_dl_cnt = 0;
+        LOGD("reset invalid download cnt\n");
+    }
+
+    //qbd_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qbd_latest_dl_time()/SECONDS_PER_HOUR;
+    LOGD("has epo:%d, time correct:%d,size correct:%d,invalid download cnt:%d\n", g_qepo_bd_has_epo,g_qepo_bd_file_time_correct,g_qepo_bd_file_size_correct,g_qepo_bd_invalid_dl_cnt);
+    if(g_qepo_bd_invalid_dl_cnt < QEPO_BD_DL_RETRY_TIME)//The invalid download count of one hour
+    {
+
+        qepo_bd_download_finished = 0;
+        ret = qepo_bd_file_update_impl();
+        qepo_bd_download_finished = 1;
+    }else{
+        usleep(QEPO_BD_INVALID_SLEEP);
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+        LOGW("The qbd data on server is invalid, will download again when the requesting is come in in next hour!\n");
+    }
+
+    qepo_bd_dl_res = ret;
+
+    mnld_qepo_bd_download_done(ret);
+    return ret;
+}
+
+static int mnld_qepo_ga_download() {
+    time_t current_rqst_time_utc_s = 0;
+    time_t qga_rqst_time_diff = 0;
+    int ret = EPO_DOWNLOAD_RESULT_FAIL;
+
+    GpsToUtcTime(gps_time.wn, gps_time.tow, &current_rqst_time_utc_s);
+
+    qga_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qga_first_invalid_dl_time()/SECONDS_PER_HOUR;
+    LOGD("QGA current request time: %ld, latest invalid dl time:%ld, time_diff:%ld,\n", current_rqst_time_utc_s,gps_mnl_get_qga_first_invalid_dl_time(),qga_rqst_time_diff);
+    if(qga_rqst_time_diff != 0){ //Rest the count value hourly
+        g_qepo_ga_invalid_dl_cnt = 0;
+        LOGD("reset invalid download cnt\n");
+    }
+
+    //qbd_rqst_time_diff = current_rqst_time_utc_s/SECONDS_PER_HOUR - gps_mnl_get_qbd_latest_dl_time()/SECONDS_PER_HOUR;
+    LOGD("has epo:%d, time correct:%d,size correct:%d,invalid download cnt:%d\n", g_qepo_ga_has_epo,g_qepo_ga_file_time_correct,g_qepo_ga_file_size_correct,g_qepo_ga_invalid_dl_cnt);
+    if(g_qepo_ga_invalid_dl_cnt < QEPO_GA_DL_RETRY_TIME)//The invalid download count of one hour
+    {
+
+        qepo_ga_download_finished = 0;
+        ret = qepo_ga_file_update_impl();
+        qepo_ga_download_finished = 1;
+    }else{
+        usleep(QEPO_GA_INVALID_SLEEP);
+        ret = EPO_DOWNLOAD_RESULT_FAIL;
+        LOGW("The qga data on server is invalid, will download again when the requesting is come in in next hour!\n");
+    }
+
+    qepo_ga_dl_res = ret;
+
+    mnld_qepo_ga_download_done(ret);
+    return ret;
+}
+
+int is_qepo_download_finished() {
+    return qepo_download_finished;
+}
+
+int is_qepo_bd_download_finished() {
+    return qepo_bd_download_finished;
+}
+
+int is_qepo_ga_download_finished() {
+    return qepo_ga_download_finished;
+}
+
+static int qepo_event_hdlr(int fd) {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    main2qepo_event cmd;
+    int read_len;
+
+    read_len = safe_recvfrom(fd, buff, sizeof(buff));
+    if (read_len <= 0) {
+        LOGE("qepo_event_hdlr() safe_recvfrom() failed read_len=%d", read_len);
+        return -1;
+    }
+
+    cmd = get_int(buff, &offset, sizeof(buff));
+    switch (cmd) {
+    case MAIN2QEPO_EVENT_START: {
+        LOGW("mnld_qepo_download() before");
+        // need to call mnld_qepo_download_done() when QEPO download is done
+        mnld_qepo_download();
+        LOGW("mnld_qepo_download() after");
+        break;
+    }
+    case MAIN2QEPO_BD_EVENT_START: {
+        LOGW("mnld_qepo_bd_download() before");
+        mnld_qepo_bd_download();
+        LOGW("mnld_qepo_bd_download() after");
+        break;
+    }
+    case MAIN2QEPO_GA_EVENT_START: {
+        LOGW("mnld_qepo_ga_download() before");
+        mnld_qepo_ga_download();
+        LOGW("mnld_qepo_ga_download() after");
+        break;
+    }
+
+    default: {
+        LOGE("qepo_event_hdlr() unknown cmd=%d", cmd);
+        return -1;
+    }
+    }
+    return 0;
+}
+
+/*static void qepo_downloader_thread_timeout() {
+    if (mnld_timeout_ne_enabled() == false) {
+        LOGE("qepo_downloader_thread_timeout() dump and exit.");
+        mnld_block_exit();
+    } else {
+        LOGE("qepo_downloader_thread_timeout() crash here for debugging");
+        CRASH_TO_DEBUG();
+    }
+}*/
+
+static void* qepo_downloader_thread(void *arg) {
+    #define MAX_EPOLL_EVENT 50
+    //timer_t hdlr_timer = init_timer(qepo_downloader_thread_timeout);
+    struct epoll_event events[MAX_EPOLL_EVENT];
+    memset(&events, 0, sizeof(events));
+    UNUSED(arg);
+
+    int epfd = epoll_create(MAX_EPOLL_EVENT);
+    if (epfd == -1) {
+        LOGE("qepo_downloader_thread() epoll_create failure reason=[%s]%d",
+            strerror(errno), errno);
+        return 0;
+    }
+
+    if (epoll_add_fd(epfd, g_fd_qepo) == -1) {
+        LOGE("qepo_downloader_thread() epoll_add_fd() failed for g_fd_qepo failed");
+        return 0;
+    }
+
+    while (1) {
+        int i;
+        int n;
+        LOGD("qepo_downloader_thread wait");
+        n = epoll_wait(epfd, events, MAX_EPOLL_EVENT , -1);
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                LOGE("qepo_downloader_thread() epoll_wait failure reason=[%s]%d",
+                    strerror(errno), errno);
+                return 0;
+            }
+        }
+        //start_timer(hdlr_timer, MNLD_QEPO_HANDLER_TIMEOUT);
+        for (i = 0; i < n; i++) {
+            if (events[i].data.fd == g_fd_qepo) {
+                if (events[i].events & EPOLLIN) {
+                    qepo_event_hdlr(g_fd_qepo);
+                }
+            } else {
+                LOGE("qepo_downloader_thread() unknown fd=%d",
+                    events[i].data.fd);
+            }
+        }
+        //stop_timer(hdlr_timer);
+    }
+
+    LOGE("qepo_downloader_thread() exit");
+    return 0;
+}
+
+int qepo_downloader_start() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    if (qepo_download_finished == 0) {
+        LOGW("qepo downloading... abort requst msg!");
+        return 0;
+    }
+    put_int(buff, &offset, MAIN2QEPO_EVENT_START);
+    return safe_sendto(MNLD_QEPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+
+int qepo_bd_downloader_start() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    if (qepo_bd_download_finished == 0) {
+        LOGW("qepo bd downloading... abort requst msg!");
+        return 0;
+    }
+    put_int(buff, &offset, MAIN2QEPO_BD_EVENT_START);
+    return safe_sendto(MNLD_QEPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int qepo_ga_downloader_start() {
+    char buff[MNLD_INTERNAL_BUFF_SIZE] = {0};
+    int offset = 0;
+    if (qepo_ga_download_finished == 0) {
+        LOGW("qepo ga downloading... abort requst msg!");
+        return 0;
+    }
+    put_int(buff, &offset, MAIN2QEPO_GA_EVENT_START);
+    return safe_sendto(MNLD_QEPO_DOWNLOAD_SOCKET, buff, offset);
+}
+
+int qepo_downloader_init() {
+    pthread_t pthread_qepo;
+
+    g_fd_qepo = socket_bind_udp(MNLD_QEPO_DOWNLOAD_SOCKET);
+    if (g_fd_qepo < 0) {
+        LOGE("socket_bind_udp(MNLD_QEPO_DOWNLOAD_SOCKET) failed");
+        return -1;
+    }
+
+    pthread_create(&pthread_qepo, NULL, qepo_downloader_thread, NULL);
+    gps_mnl_bd_qepo_init();
+    return 0;
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/mnld_mt33xx.service b/src/connectivity/gps/mtk_mnld/mnld_mt33xx.service
new file mode 100644
index 0000000..b8657c9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/mnld_mt33xx.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=MNL Daemon
+Requires=mt33xx_drv_insmod.service
+After=mt33xx_drv_insmod.service
+
+[Service]
+ExecStart=/usr/bin/mnld0
+Restart=always
+#StandardOutput=kmsg+console
+
+[Install]
+WantedBy=basic.target
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/data_coder.h b/src/connectivity/gps/mtk_mnld/utility/inc/data_coder.h
new file mode 100644
index 0000000..fc66d2f
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/data_coder.h
@@ -0,0 +1,32 @@
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char        get_byte(char* buff, int* offset, int src_len);
+short       get_short(char* buff, int* offset, int src_len);
+int         get_int(char* buff, int* offset, int src_len);
+long long   get_long(char* buff, int* offset, int src_len);
+float       get_float(char* buff, int* offset, int src_len);
+double      get_double(char* buff, int* offset, int src_len);
+char*       get_string(char* buff, int* offset, int src_len);
+char*       get_string2(char* buff, int* offset, int src_len);
+int         get_binary(char* buff, int* offset, char* output, int src_len, int des_len);
+
+void put_byte(char* buff, int* offset, const char input);
+void put_short(char* buff, int* offset, const short input);
+void put_int(char* buff, int* offset, const int input);
+void put_long(char* buff, int* offset, const long long input);
+void put_float(char* buff, int* offset, const float input);
+void put_double(char* buff, int* offset, const double input);
+void put_string(char* buff, int* offset, const char* input);
+void put_binary(char* buff, int* offset, const char* input, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/mtk_auto_log.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_auto_log.h
new file mode 100644
index 0000000..0387cb0
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/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 "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__)
+
+#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/mtk_mnld/utility/inc/mtk_lbs_utility.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_lbs_utility.h
new file mode 100644
index 0000000..1498859
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_lbs_utility.h
@@ -0,0 +1,159 @@
+#ifndef __MTK_LBS_UTILITY_H__
+#define __MTK_LBS_UTILITY_H__
+
+#include <time.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include "gps_dbg_log.h"
+#include "mtk_auto_log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************
+* Basic Utilities
+**************************************************/
+#define  MTK_GPS_NVRAM  0
+    
+#if defined(__ANDROID_OS__)
+#define  ANDROID_MNLD_PROP_SUPPORT 1
+#elif defined(__LINUX_OS__)
+#define  ANDROID_MNLD_PROP_SUPPORT 0
+
+/** 
+ * connect to peer named "name"
+ * returns fd or -1 on error
+ */
+int socket_local_client(const char *name, int type);
+/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem 
+ *  namespace
+ *
+ *  Returns fd on success, -1 on fail
+ */
+int socket_local_server(const char *name, int type);
+#endif
+
+#define CRASH_TO_DEBUG() \
+{\
+    int* crash = 0;\
+    gps_dbg_log_exit_flush(0);\
+    *crash = 100;\
+}
+
+#define MNLD_STRNCPY(dst,src,size)\
+    do{\
+        strncpy((char *)(dst), (src), (size - 1));\
+        (dst)[size - 1] = '\0';\
+    }while(0)
+
+typedef struct sync_lock {
+    pthread_mutex_t mutx;
+    pthread_cond_t con;
+    int condtion;
+    int index;
+}SYNC_LOCK_T;
+
+void msleep(int interval);
+
+// in millisecond
+time_t get_tick();
+
+// in millisecond
+time_t get_time_in_millisecond();
+
+// -1 means failure
+int block_here();
+
+//exit block_here() and process will exit and restart
+void mnld_block_exit(void);
+
+/*************************************************
+* Timer
+**************************************************/
+typedef void (* timer_callback)();
+
+// -1 means failure
+timer_t init_timer_id(timer_callback cb, int id);
+
+// -1 means failure
+timer_t init_timer(timer_callback cb);
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds);
+
+// -1 means failure
+int stop_timer(timer_t timerid);
+
+// -1 means failure
+int deinit_timer(timer_t timerid);
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd);
+
+// -1 failed
+int epoll_add_fd2(int epfd, int fd, uint32_t events);
+
+// -1 failed
+int epoll_del_fd(int epfd, int fd);
+
+int epoll_mod_fd(int epfd, int fd, uint32_t events);
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_bind_udp(const char* path);
+
+int mnld_flp_to_mnld_fd_init(const char* path);
+
+int mnld_sendto_flp(void* dest, char* buf, int size);
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking);
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len);
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len);
+
+/*************************************************
+* File
+**************************************************/
+// 0 not exist, 1 exist
+int is_file_exist(const char* path);
+
+// -1 means failure
+int get_file_size(const char* path);
+
+// -1 failure
+int delete_file(const char* file_path);
+
+// -1 means failure
+int write_msg2file(char* dest, char* msg, ...);
+
+int asc_str_to_usc2_str(char* output, const char* input);
+
+void raw_data_to_hex_string(char* output, char* input, int input_len);
+
+void init_condition(SYNC_LOCK_T *lock);
+
+void get_condition(SYNC_LOCK_T *lock);
+
+void release_condition(SYNC_LOCK_T *lock);
+
+//void mnld_dump_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_data_coder.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_data_coder.h
new file mode 100644
index 0000000..cc9d52e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_data_coder.h
@@ -0,0 +1,50 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __DATA_CODER_H__
+#define __DATA_CODER_H__
+
+#include "mtk_socket_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool mtk_socket_get_bool(char* buff, int* offset);
+char mtk_socket_get_char(char* buff, int* offset);
+short mtk_socket_get_short(char* buff, int* offset);
+int mtk_socket_get_int(char* buff, int* offset);
+int64_t mtk_socket_get_int64_t(char* buff, int* offset);
+float mtk_socket_get_float(char* buff, int* offset);
+double mtk_socket_get_double(char* buff, int* offset);
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size);
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size);
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size);
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size);
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size);
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size);
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size);
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size);
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2);
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input);
+void mtk_socket_put_char(char* buff, int* offset, char input);
+void mtk_socket_put_short(char* buff, int* offset, short input);
+void mtk_socket_put_int(char* buff, int* offset, int input);
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input);
+void mtk_socket_put_float(char* buff, int* offset, float input);
+void mtk_socket_put_double(char* buff, int* offset, double input);
+void mtk_socket_put_string(char* buff, int* offset, const char* input);
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size);
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size);
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size);
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size);
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size);
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size);
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size);
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_utils.h b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_utils.h
new file mode 100644
index 0000000..03e29c6
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/inc/mtk_socket_utils.h
@@ -0,0 +1,236 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#ifndef __MTK_SOCKET_UTILS_H__
+#define __MTK_SOCKET_UTILS_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include "mtk_auto_log.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    SOCK_NS_ABSTRACT = 0,
+    SOCK_NS_FILESYSTEM = 1,
+} mtk_socket_namespace;
+
+typedef struct {
+    int fd;
+    bool is_local;
+    pthread_mutex_t mutex;
+
+    // Network
+    char* host;
+    int port;
+
+    // Local
+    char* path;
+    mtk_socket_namespace namesapce;
+} mtk_socket_fd;
+
+void _mtk_socket_log(int type, const char *fmt, ...);
+
+#define SOCK_LOGD(fmt, arg ...) ALOGD("%s: " fmt, __FUNCTION__ , ##arg)
+#define SOCK_LOGW(fmt, arg ...) ALOGW("%s: " fmt, __FUNCTION__ , ##arg)
+#define SOCK_LOGE(fmt, arg ...) ALOGE("%s: " fmt, __FUNCTION__ , ##arg)
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port);
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port);
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port);
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace);
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd);
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd);
+void mtk_socket_client_close(mtk_socket_fd* sock_fd);
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len);
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len);
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout);
+
+
+void mtk_socket_buff_dump(const char* buff, int len);
+
+bool mtk_socket_string_is_equal(char* data1, char* data2);
+bool mtk_socket_string_array_is_equal(void* data1, int data1_size, void* data2, int data2_size, int string_size);
+void mtk_socket_string_array_dump(void* input, int size1, int size2);
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size);
+void mtk_socket_bool_array_dump(bool input[], int size);
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size);
+void mtk_socket_char_array_dump(char input[], int size);
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size);
+void mtk_socket_short_array_dump(short input[], int size);
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size);
+void mtk_socket_int_array_dump(int input[], int size);
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size);
+void mtk_socket_int64_t_array_dump(int64_t input[], int size);
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size);
+void mtk_socket_float_array_dump(float input[], int size);
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size);
+void mtk_socket_double_array_dump(double input[], int size);
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line);
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line);
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line);
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line);
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line);
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line);
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line);
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line);
+
+#define ASSERT_EQUAL_INT(d1, d2) \
+{\
+    int _d1 = d1;\
+    int _d2 = d2;\
+    if(_d1 != _d2) {\
+        LOGE("%s():%d ASSERT_EQUAL_INT() failed, d1=[%d], d2=[%d]",\
+        __func__, __LINE__, _d1, _d2);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_BOOL(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_bool(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_CHAR(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_char(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_SHORT(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_short(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_INT(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_int(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_INT64_T(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_int64_t(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_FLOAT(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_float(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_DOUBLE(buff, offset, expected_value) \
+{\
+    if(!mtk_socket_expected_double(buff, offset, expected_value, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRING(buff, offset, expected_value, max_size) \
+{\
+    if(!mtk_socket_expected_string(buff, offset, expected_value, max_size, __func__, __LINE__)) {\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRUCT(buff, offset, expected_value, struct_name) \
+{\
+    struct_name _tmp;\
+    struct_name##_decode(buff, offset, &_tmp);\
+    if(!struct_name##_is_equal(&_tmp, expected_value)) {\
+        LOGE("%s():%d EXPECTED_STRUCT() %s_is_equal() fail", __func__, __LINE__, #struct_name);\
+        LOGE(" ============= read ===============");\
+        struct_name##_dump(&_tmp);\
+        LOGE(" ============= expected ===============");\
+        struct_name##_dump(expected_value);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+    type _tmp[max_size] = {0};\
+    int _tmp_num = mtk_socket_get_##type##_array(buff, offset, _tmp, max_size);\
+    if(!mtk_socket_##type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+        LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+        LOGE(" ============= read ===============");\
+        mtk_socket_##type##_array_dump(_tmp, _tmp_num);\
+        LOGE(" ============= expected ===============");\
+        mtk_socket_##type##_array_dump(expected_value, expected_num);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRING_ARRAY(buff, offset, expected_num, expected_value, max_size1, max_size2) \
+{\
+    char _tmp[max_size1][max_size2];\
+    int _tmp_num = mtk_socket_get_string_array(buff, offset, _tmp, max_size1, max_size2);\
+    if(!mtk_socket_string_array_is_equal(expected_value, expected_num, _tmp, _tmp_num, max_size2)) {\
+        LOGE("%s():%d expected_string_array() fail", __func__, __LINE__);\
+        LOGE(" ============= read ===============");\
+        mtk_socket_string_array_dump(_tmp, _tmp_num, max_size2);\
+        LOGE(" ============= expected ===============");\
+        mtk_socket_string_array_dump(expected_value, expected_num, max_size2);\
+        return false;\
+    }\
+}
+
+#define EXPECTED_STRUCT_ARRAY(buff, offset, expected_num, expected_value, type, max_size) \
+{\
+    type _tmp[max_size];\
+    int _tmp_num = type##_array_decode(buff, offset, _tmp, max_size);\
+    if(!type##_array_is_equal(expected_value, expected_num, _tmp, _tmp_num)) {\
+        LOGE("%s():%d expected_%s_array() fail", __func__, __LINE__, #type);\
+        LOGE(" ============= read ===============");\
+        type##_array_dump(_tmp, _tmp_num);\
+        LOGE(" ============= expected ===============");\
+        type##_array_dump(expected_value, expected_num);\
+        return false;\
+    }\
+}
+
+#define ASSERT_LESS_EQUAL_THAN(d1, d2) \
+{\
+    if(d1 > d2) {\
+        LOGE("%s():%d ASSERT_LESS_EQUAL_THAN() fail, %s=[%d] > [%d]", __func__, __LINE__, #d1, d1, d2);\
+        return false;\
+    }\
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/data_coder.c b/src/connectivity/gps/mtk_mnld/utility/src/data_coder.c
new file mode 100644
index 0000000..ab67b38
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/data_coder.c
@@ -0,0 +1,154 @@
+#include <string.h>
+
+#ifndef MAX
+#define MAX(A,B) ((A)>(B)?(A):(B))
+#endif
+#ifndef MIN
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#endif
+
+//===============================================================
+// get
+char get_byte(char* buff, int* offset, int src_len) {
+    char ret = 0;
+    if (*offset >= 0 && *offset < src_len) {
+        ret = buff[*offset];
+        *offset += 1;
+    }
+    return ret;
+}
+
+short get_short(char* buff, int* offset, int src_len) {
+    short ret = 0;
+    ret |= get_byte(buff, offset, src_len) & 0xff;
+    ret |= (get_byte(buff, offset, src_len) << 8);
+    return ret;
+}
+
+int get_int(char* buff, int* offset, int src_len) {
+    int ret = 0;
+    ret |= get_short(buff, offset, src_len) & 0xffff;
+    ret |= (get_short(buff, offset, src_len) << 16);
+    return ret;
+}
+
+long long get_long(char* buff, int* offset, int src_len) {
+    long long ret = 0;
+    ret |= get_int(buff, offset, src_len) & 0xffffffffL;
+    ret |= ((long long)get_int(buff, offset, src_len) << 32);
+    return ret;
+}
+
+float get_float(char* buff, int* offset, int src_len) {
+    float ret;
+    int tmp = get_int(buff, offset, src_len);
+    ret = *((float*)&tmp);
+    return ret;
+}
+
+double get_double(char* buff, int* offset, int src_len) {
+    double ret;
+    long long tmp = get_long(buff, offset, src_len);
+    ret = *((double*)&tmp);
+    return ret;
+}
+
+char* get_string(char* buff, int* offset, int src_len) {
+    char ret = get_byte(buff, offset, src_len);
+    if (ret == 0) {
+        return NULL;
+    } else {
+        char* p = NULL;
+        int len = get_int(buff, offset, src_len);
+        if (*offset < 0 || *offset >= src_len) {
+            *offset = 0;
+        }
+        if ((len > src_len - *offset) || len < 0) {
+            len = src_len - *offset;
+        }
+        if (len <= 0) {
+            return NULL;
+        }
+        p = &buff[*offset];
+        p[len-1] = 0;
+        *offset += len;
+        return p;
+    }
+}
+
+char* get_string2(char* buff, int* offset, int src_len) {
+    char* output = get_string(buff, offset, src_len);
+    if (output == NULL) {
+        return "";
+    } else {
+        return output;
+    }
+}
+
+int get_binary(char* buff, int* offset, char* output, int src_len, int des_len) {
+    int len = 0;
+    if (*offset >= 0 && *offset <= src_len) {
+        len = get_int(buff, offset, src_len);
+        if (len > MIN((src_len-(*offset)), des_len)) {
+            len = MIN((src_len-(*offset)), des_len);
+        }
+        if (len > 0) {
+            memcpy(output, &buff[*offset], len);
+            *offset += len;
+        }
+    }
+    return len;
+}
+
+//===============================================================
+// put
+void put_byte(char* buff, int* offset, const char input) {
+    *((char*)&buff[*offset]) = input;
+    *offset += 1;
+}
+
+void put_short(char* buff, int* offset, const short input) {
+    put_byte(buff, offset, input & 0xff);
+    put_byte(buff, offset, (input >> 8) & 0xff);
+}
+
+void put_int(char* buff, int* offset, const int input) {
+    put_short(buff, offset, input & 0xffff);
+    put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void put_long(char* buff, int* offset, const long long input) {
+    put_int(buff, offset, input & 0xffffffffL);
+    put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void put_float(char* buff, int* offset, const float input) {
+    int* data = (int*)&input;
+    put_int(buff, offset, *data);
+}
+
+void put_double(char* buff, int* offset, const double input) {
+    long long* data = (long long*)&input;
+    put_long(buff, offset, *data);
+}
+
+void put_string(char* buff, int* offset, const char* input) {
+    if (input == NULL) {
+        put_byte(buff, offset, 0);
+    } else {
+        int len = strlen(input) + 1;
+        put_byte(buff, offset, 1);
+        put_int(buff, offset, len);
+        memcpy(&buff[*offset], input, len);
+        *offset += len;
+    }
+}
+
+void put_binary(char* buff, int* offset, const char* input, const int len) {
+    put_int(buff, offset, len);
+    if (len > 0) {
+        memcpy(&buff[*offset], input, len);
+        *offset += len;
+    }
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_auto_log.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_auto_log.c
new file mode 100644
index 0000000..1c16fa9
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_auto_log.c
@@ -0,0 +1,109 @@
+/*
+* 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.
+*/
+#include <sys/time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <memory.h>
+
+#include "mtk_auto_log.h"
+
+#if defined(__LINUX_OS__)
+// -1 means failure
+int get_time_str(char* buf, int len) {
+    struct timeval  tv;
+    struct timezone tz;
+    struct tm      *tm;
+
+    gettimeofday(&tv, &tz);
+    tm = localtime(&tv.tv_sec);
+
+    memset(buf, 0, len);
+    sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d.%03d",
+        tm->tm_year + 1900, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
+        tm->tm_sec, (int)(tv.tv_usec / 1000));
+
+    return 0;
+}
+#endif
+
+int set_log_level(int *dst_level, int src_level)
+{
+#if defined(__ANDROID_OS__)
+
+    ALOGI("Current debug level=%d", *dst_level);
+
+    if (src_level < L_VERBOSE || src_level >  L_SUPPRESS)
+    {
+        ALOGE("Invalid debug level, level=%d", src_level);
+        ALOGE("  [level] -");
+        ALOGE("  QUIET      = 6");
+        ALOGE("  ASSERT     = 5");
+        ALOGE("  ERROR      = 4");
+        ALOGE("  WARNING    = 3");
+        ALOGE("  INFO       = 2");
+        ALOGE("  DEBUG      = 1");
+        ALOGE("  LOGALL     = 0");
+        return -1;
+    }
+
+    *dst_level = src_level;
+
+    ALOGI("New debug level=%d", *dst_level);
+
+#elif defined(__LINUX_OS__)
+
+    printf("Current debug level=%d\n", *dst_level);
+
+    if (src_level < L_VERBOSE || src_level >  L_SUPPRESS)
+    {
+        printf("Invalid debug level, level=%d", src_level);
+        printf("  [level] -");
+        printf("  QUIET      = 6");
+        printf("  ASSERT     = 5");
+        printf("  ERROR      = 4");
+        printf("  WARNING    = 3");
+        printf("  INFO       = 2");
+        printf("  DEBUG      = 1");
+        printf("  LOGALL     = 0");
+        return -1;
+    }
+
+    *dst_level = src_level;
+
+    printf("New debug level=%d\n", *dst_level);
+
+#endif
+    return 0;
+}
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_lbs_utility.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_lbs_utility.c
new file mode 100644
index 0000000..170b70a
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_lbs_utility.c
@@ -0,0 +1,669 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h>  // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>  // usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h>  // inet_addr
+#include <sys/un.h>  // struct sockaddr_un
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <signal.h>
+#include <semaphore.h>
+
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_lbs_utility"
+#endif
+
+#ifdef __LINUX_OS__
+
+#define LISTEN_BACKLOG 4
+/* Only the bottom bits are really the socket type; there are flags too. */
+#define SOCK_TYPE_MASK 0xf
+/* Documented in header file. */
+int socket_make_sockaddr_un(const char *name, struct sockaddr_un *p_addr, socklen_t *alen)
+{
+    memset (p_addr, 0, sizeof (*p_addr));
+    size_t namelen;
+
+    namelen  = strlen(name);
+
+    // Test with length +1 for the *initial* '\0'.
+    if ((namelen + 1) > sizeof(p_addr->sun_path)) {
+        goto error;
+    }
+
+    /*
+     * Note: The path in this case is *not* supposed to be
+     * '\0'-terminated. ("man 7 unix" for the gory details.)
+     */
+    
+    p_addr->sun_path[0] = 0;
+    memcpy(p_addr->sun_path + 1, name, namelen); 
+
+    p_addr->sun_family = AF_LOCAL;
+    *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
+    return 0;
+error:
+    return -1;
+}
+
+/**
+ * connect to peer named "name" on fd
+ * returns same fd or -1 on error.
+ * fd is not closed on error. that's your job.
+ * 
+ * Used by AndroidSocketImpl
+ */
+int socket_local_client_connect(int fd, const char *name)
+{
+    struct sockaddr_un addr;
+    socklen_t alen;
+    int err;
+
+    err = socket_make_sockaddr_un(name, &addr, &alen);
+
+    if (err < 0) {
+        goto error;
+    }
+
+    if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
+        goto error;
+    }
+
+    return fd;
+
+error:
+    return -1;
+}
+
+/** 
+ * connect to peer named "name"
+ * returns fd or -1 on error
+ */
+int socket_local_client(const char *name, int type)
+{
+    int s;
+
+    s = socket(AF_LOCAL, type, 0);
+    if(s < 0) return -1;
+
+    if ( 0 > socket_local_client_connect(s, name)) {
+        close(s);
+        return -1;
+    }
+
+    return s;
+}
+
+
+
+/**
+ * Binds a pre-created socket(AF_LOCAL) 's' to 'name'
+ * returns 's' on success, -1 on fail
+ *
+ * Does not call listen()
+ */
+int socket_local_server_bind(int s, const char *name)
+{
+    struct sockaddr_un addr;
+    socklen_t alen;
+    int n;
+    int err;
+
+    err = socket_make_sockaddr_un(name, &addr, &alen);
+
+    if (err < 0) {
+        return -1;
+    }
+
+    /* basically: if this is a filesystem path, unlink first */
+    /*ignore ENOENT*/
+    unlink(addr.sun_path);
+
+    n = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
+
+    if(bind(s, (struct sockaddr *) &addr, alen) < 0) {
+        return -1;
+    }
+
+    return s;
+
+}
+
+
+/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem 
+ *  namespace
+ *
+ *  Returns fd on success, -1 on fail
+ */
+
+int socket_local_server(const char *name, int type)
+{
+    int err;
+    int s;
+    
+    s = socket(AF_LOCAL, type, 0);
+    if (s < 0) return -1;
+
+    err = socket_local_server_bind(s, name);
+
+    if (err < 0) {
+        close(s);
+        return -1;
+    }
+
+    if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) {
+        int ret;
+
+        ret = listen(s, LISTEN_BACKLOG);
+
+        if (ret < 0) {
+            close(s);
+            return -1;
+        }
+    }
+
+    return s;
+}
+
+
+#endif //__LINUX_OS__
+
+int asc_str_to_usc2_str(char* output, const char* input) {
+    int len = 2;
+
+    output[0] = 0xfe;
+    output[1] = 0xff;
+
+    while (*input != 0) {
+        output[len++] = 0;
+        output[len++] = *input;
+        input++;
+    }
+
+    output[len] = 0;
+    output[len+1] = 0;
+    return len;
+}
+
+void raw_data_to_hex_string(char* output, char* input, int input_len) {
+    int i = 0;
+    for (i = 0; i < input_len; i++) {
+        int tmp = (input[i] >> 4) & 0xf;
+
+        if (tmp >= 0 && tmp <= 9) {
+            output[i*2] = tmp + '0';
+        } else {
+            output[i*2] = (tmp - 10) + 'A';
+        }
+
+        tmp = input[i] & 0xf;
+        if (tmp >= 0 && tmp <= 9) {
+            output[(i*2)+1] = tmp + '0';
+        } else {
+            output[(i*2)+1] = (tmp - 10) + 'A';
+        }
+    }
+    output[i*2] = 0;
+}
+
+void msleep(int interval) {
+    usleep(interval * 1000);
+}
+
+// in millisecond
+time_t get_tick() {
+    struct timespec ts;
+    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
+        LOGE("clock_gettime failed reason=[%s]", strerror(errno));
+        return -1;
+    }
+    return (ts.tv_sec*1000) + (ts.tv_nsec/1000000);
+}
+
+// in millisecond
+time_t get_time_in_millisecond() {
+    struct timespec ts;
+    if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+        LOGE("get_time_in_millisecond  failed reason=[%s]", strerror(errno));
+        return -1;
+    }
+    return ((long long)ts.tv_sec*1000) + ((long long)ts.tv_nsec/1000000);
+}
+
+
+sem_t g_mnld_exit_sem;
+// -1 means failure
+int block_here() {
+    if (sem_init(&g_mnld_exit_sem, 0, 0) == -1) {
+        LOGE("block_here() sem_init failure reason=%s\n", strerror(errno));
+        return -1;
+    }
+    sem_wait(&g_mnld_exit_sem);
+    if (sem_destroy(&g_mnld_exit_sem) == -1) {
+        LOGE("block_here() sem_destroy reason=%s\n", strerror(errno));
+    }
+    return 0;
+}
+
+void mnld_block_exit(void) {
+    if(sem_post(&g_mnld_exit_sem) == -1) {
+        LOGE("sem_post failed");
+        _exit(0);
+    }
+}
+
+/*************************************************
+* Timer
+**************************************************/
+// -1 means failure
+timer_t init_timer_id(timer_callback cb, int id) {
+    struct sigevent sevp;
+    timer_t timerid;
+
+    memset(&sevp, 0, sizeof(sevp));
+    sevp.sigev_value.sival_int = id;
+    sevp.sigev_notify = SIGEV_THREAD;
+    sevp.sigev_notify_function = cb;
+
+    if (timer_create(CLOCK_MONOTONIC, &sevp, &timerid) == -1) {
+        LOGE("timer_create  failed reason=[%s]", strerror(errno));
+        return (timer_t)-1;
+    }
+    return timerid;
+}
+
+// -1 means failure
+timer_t init_timer(timer_callback cb) {
+    return init_timer_id(cb, 0);
+}
+
+// -1 means failure
+int start_timer(timer_t timerid, int milliseconds) {
+    struct itimerspec expire;
+    expire.it_interval.tv_sec = 0;
+    expire.it_interval.tv_nsec = 0;
+    expire.it_value.tv_sec = milliseconds/1000;
+    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+    return timer_settime(timerid, 0, &expire, NULL);
+}
+
+// -1 means failure
+int stop_timer(timer_t timerid) {
+    return start_timer(timerid, 0);
+}
+
+// -1 means failure
+int deinit_timer(timer_t timerid) {
+    if (timer_delete(timerid) == -1) {
+        // errno
+        return -1;
+    }
+    return 0;
+}
+
+/*************************************************
+* Epoll
+**************************************************/
+// -1 means failure
+int epoll_add_fd(int epfd, int fd) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = EPOLLIN;
+    // don't set the fd to edge trigger
+    // the some event like accept may be lost if two or more clients are connecting to server at the same time
+    // level trigger is preferred to avoid event lost
+    // do not set EPOLLOUT due to it will always trigger when write is available
+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        LOGE("epoll_add_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+            strerror(errno), errno, epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+// -1 failed
+int epoll_add_fd2(int epfd, int fd, uint32_t events) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = events;
+    // don't set the fd to edge trigger
+    // the some event like accept may be lost if two or more clients are connecting to server at the same time
+    // level trigger is preferred to avoid event lost
+    // do not set EPOLLOUT due to it will always trigger when write is available
+    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        LOGE("epoll_add_fd2() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+            strerror(errno), errno, epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+int epoll_del_fd(int epfd, int fd) {
+    struct epoll_event  ev;
+    int                 ret;
+
+    if (epfd == -1)
+        return -1;
+
+    ev.events  = EPOLLIN;
+    ev.data.fd = fd;
+    do {
+        ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
+// -1 failed
+int epoll_mod_fd(int epfd, int fd, uint32_t events) {
+    struct epoll_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.data.fd = fd;
+    ev.events = events;
+    if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
+        LOGE("epoll_mod_fd() epoll_ctl() failed reason=[%s]%d epfd=%d fd=%d",
+            strerror(errno), errno, epfd, fd);
+        return -1;
+    }
+    return 0;
+}
+
+/*************************************************
+* Local UDP Socket
+**************************************************/
+// -1 means failure
+int socket_bind_udp(const char* path) {
+    int fd;
+    struct sockaddr_un addr;
+
+    fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("socket_bind_udp() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    LOGD("fd=%d,path=%s\n", fd, path);
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_path[0] = 0;
+    MNLD_STRNCPY(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);
+    addr.sun_family = AF_UNIX;
+    unlink(path);
+
+    if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+        LOGE("socket_bind_udp() bind() failed path=[%s] reason=[%s]%d",
+            addr.sun_path+1, strerror(errno), errno);
+        close(fd);
+        return -1;
+    }else
+        LOGI("bind ok path=[%s]", addr.sun_path+1);
+    return fd;
+}
+
+int mnld_flp_to_mnld_fd_init(const char* path) {
+    int flp_fd = -1;
+    struct sockaddr_un cmd_local;
+
+    if ((flp_fd = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1) {
+        LOGE("flp2mnl socket create failed\n");
+        return flp_fd;
+    }
+
+    unlink(path);
+    memset(&cmd_local, 0, sizeof(cmd_local));
+    cmd_local.sun_family = AF_LOCAL;
+    MNLD_STRNCPY(cmd_local.sun_path, path,sizeof(cmd_local.sun_path));
+
+    if (bind(flp_fd, (struct sockaddr *)&cmd_local, sizeof(cmd_local)) < 0) {
+        LOGE("flp2mnl socket bind failed\n");
+        close(flp_fd);
+        flp_fd = -1;
+        return flp_fd;
+    }
+
+    int res = chmod(path, 0660);  // (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+    LOGD("chmod res = %d, %s\n", res, strerror(errno));
+    return flp_fd;
+}
+
+// -1 means failure
+int socket_set_blocking(int fd, int blocking) {
+    if (fd < 0) {
+        LOGE("socket_set_blocking() invalid fd=%d", fd);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags == -1) {
+        LOGE("socket_set_blocking() fcntl() failed invalid flags=%d reason=[%s]%d",
+            flags, strerror(errno), errno);
+        return -1;
+    }
+
+    flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
+    return (fcntl(fd, F_SETFL, flags) == 0) ? 0 : -1;
+}
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len) {
+    int ret = 0;
+    struct sockaddr_un addr;
+    int retry = 10;
+    int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("safe_sendto() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){
+        LOGE("fcntl failed reason=[%s]%d",
+                    strerror(errno), errno);
+
+        close(fd);
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_path[0] = 0;
+    MNLD_STRNCPY(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);
+    addr.sun_family = AF_UNIX;
+
+    while ((ret = sendto(fd, buff, len, 0,
+        (const struct sockaddr *)&addr, sizeof(addr))) == -1) {
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("sendto() failed path=[%s] ret=%d reason=[%s]%d",
+            path, ret, strerror(errno), errno);
+        break;
+    }
+
+    close(fd);
+    return ret;
+}
+
+int mnld_sendto_flp(void* dest, char* buf, int size) {
+    // dest: MTK_MNLD2HAL
+    int ret = 0;
+    int len = 0;
+    struct sockaddr_un soc_addr;
+    socklen_t addr_len;
+    int retry = 10;
+
+    int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("safe_sendto() socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+
+    MNLD_STRNCPY(soc_addr.sun_path, dest,sizeof(soc_addr.sun_path));
+    soc_addr.sun_family = AF_UNIX;
+    addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(soc_addr.sun_path) + 1);
+
+    //LOGD("mnld2flp fd: %d\n", fd);
+    while ((len = sendto(fd, buf, size, 0,
+        (const struct sockaddr *)&soc_addr, (socklen_t)addr_len)) == -1) {
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("[mnld2hal] ERR: sendto dest=[%s] len=%d reason =[%s]\n",
+            (char *)dest, size, strerror(errno));
+        ret = -1;
+        break;
+    }
+    close(fd);
+    return ret;
+}
+
+// -1 means failure
+int safe_recvfrom(int fd, char* buff, int len) {
+    int ret = 0;
+    int retry = 10;
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){
+        LOGE("fcntl failed reason=[%s]%d", strerror(errno), errno);
+    }
+
+    while ((ret = recvfrom(fd, buff, len, 0, NULL, NULL)) == -1) {
+        LOGW("safe_recvfrom() ret=%d len=%d", ret, len);
+        if (errno == EINTR) continue;
+        if (errno == EAGAIN) {
+            if (retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+        }
+        LOGE("safe_recvfrom() recvfrom() failed reason=[%s]%d",
+            strerror(errno), errno);
+        break;
+    }
+    return ret;
+}
+
+/*************************************************
+* File
+**************************************************/
+// 0 not exist, 1 exist
+int is_file_exist(const char* path) {
+    FILE* fp = NULL;
+    fp = fopen(path, "r");
+    if (fp == NULL) {
+        return 0;
+    } else {
+        fclose(fp);
+        return 1;
+    }
+    return 0;
+}
+
+// -1 means failure
+int get_file_size(const char* path) {
+    struct stat s;
+    if (stat(path, &s) == -1) {
+        LOGD("get_file_size() stat() fail for [%s] reason=[%s]",
+            path, strerror(errno));
+        return -1;
+    }
+    return s.st_size;
+}
+
+// -1 failure
+int delete_file(const char* file_path) {
+    return remove(file_path);
+}
+
+// -1 means failure
+int write_msg2file(char* dest, char* msg, ...) {
+    FILE* fp;
+    char buf[1024] = {0};
+    va_list ap;
+
+    if (dest == NULL || msg == NULL) {
+        return -1;
+    }
+
+    va_start(ap, msg);
+    vsnprintf(buf, sizeof(buf), msg, ap);
+    va_end(ap);
+
+    fp = fopen(dest, "a");
+    if (fp == NULL) {
+        LOGE("write_msg2file() fopen() fail reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    fprintf(fp, "%s", buf);
+    fclose(fp);
+    return 0;
+}
+
+void init_condition(SYNC_LOCK_T *lock) {
+    int ret = 0;
+
+    ret = pthread_mutex_lock(&(lock->mutx));
+    lock->condtion = 0;
+    ret = pthread_mutex_unlock(&(lock->mutx));
+    LOGD("ret mutex unlock = %d\n", ret);
+
+    return;
+}
+
+void get_condition(SYNC_LOCK_T *lock) {
+    int ret = 0;
+
+    ret = pthread_mutex_lock(&(lock->mutx));
+    //LOGD("ret mutex lock = %d\n", ret);
+
+    while (!lock->condtion) {
+        ret = pthread_cond_wait(&(lock->con), &(lock->mutx));
+        //LOGD("ret cond wait = %d\n" , ret);
+    }
+
+    lock->condtion = 0;
+    ret = pthread_mutex_unlock(&(lock->mutx));
+    LOGD("ret mutex unlock = %d\n", ret);
+
+    return;
+}
+
+void release_condition(SYNC_LOCK_T *lock) {
+    int ret = 0;
+
+    ret = pthread_mutex_lock(&(lock->mutx));
+    //LOGD("ret mutex lock = %d\n", ret);
+
+    lock->condtion = 1;
+    ret = pthread_cond_signal(&(lock->con));
+    //LOGD("ret cond_signal = %d\n", ret);
+
+    ret = pthread_mutex_unlock(&(lock->mutx));
+    LOGD("ret unlock= %d\n", ret);
+
+    return;
+}
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_mnld_dump.cpp b/src/connectivity/gps/mtk_mnld/utility/src/mtk_mnld_dump.cpp
new file mode 100644
index 0000000..05e457b
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_mnld_dump.cpp
@@ -0,0 +1,147 @@
+#if defined(__ANDROID_OS__)
+#include <utils/CallStack.h>
+#include <utils/ProcessCallStack.h>
+#endif
+#include <fcntl.h>   /* File control definitions */
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "mtk_gps_type.h"
+#include "gps_dbg_log.h"
+#include "mtk_lbs_utility.h"
+#include "mtk_auto_log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MNLD_DUMP"
+#endif
+
+#define MNLD_DUMP_FILE_LEN 128
+
+char mnld_dump_file[] = "mnld";
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnld_dump_get_filename
+ * DESCRIPTION
+ *  To generate the full name of dump file
+ * PARAMETERS
+ *  dump_filename         [OUT]   the string to store the full name of dump file
+ *  length                      [IN]    the max length of dump_filename
+ * RETURNS
+ *  None
+ *****************************************************************************/
+void mnld_dump_get_filename(char *dump_filename, size_t length)
+{
+    char path[MNLD_DUMP_FILE_LEN] = {0};
+
+    do {
+#if ANDROID_MNLD_PROP_SUPPORT
+        char path_result[PROPERTY_VALUE_MAX] = {0};
+
+        if (property_get(GPS_LOG_PERSIST_PATH, path_result, NULL)  //Store the dump file under GPS debug log folder
+            && (strcmp(path_result, GPS_LOG_PERSIST_VALUE_NONE) != 0)) {
+            MNLD_STRNCPY(path, path_result, length);
+        } else {
+            LOGW("log path not set!");
+            break;
+        }
+#endif
+        if(dump_filename == NULL)
+        {
+            LOGW("input NULL pointer!!!");
+            break;
+        }
+
+        memset(dump_filename, 0x00, length);
+
+        snprintf(dump_filename, length, "%s%s_%d.dumpc",
+            path, mnld_dump_file, getpid());
+        LOGD("dump file:%s", dump_filename);
+    } while(0);
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnld_dump_process
+ * DESCRIPTION
+ *  Dump all threads of current process.
+ * PARAMETERS
+ *  dump_fd         [IN]   the file descripter to dump in to, -1: dump to mainlog
+ *
+ * RETURNS
+ *  None
+ *****************************************************************************/
+ void mnld_dump_process(int dump_fd) {
+#if defined(__ANDROID_OS__)
+    android::ProcessCallStack pcs;
+    pcs.update();
+    if(dump_fd != -1) {
+        pcs.dump(dump_fd, 0, NULL);  //Dump to file
+    } else {
+        pcs.log(LOG_TAG, ANDROID_LOG_DEBUG, NULL);  //Dump to mainlog
+    }
+#endif
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnld_dump_thread
+ * DESCRIPTION
+ *  To dump specified thread's backtrace.
+ *  [Not used until now, keep here for demo code]
+ * PARAMETERS
+ *  dump_fd         [IN]   the file descripter to dump in to, -1: dump to mainlog
+ *  tid                 [IN]   the thread id(tid) need to be dumped
+ *
+ * RETURNS
+ *  None
+ *****************************************************************************/
+void mnld_dump_thread(int dump_fd, pid_t tid) {  //Dump specific thread backtrace
+#if defined(__ANDROID_OS__)
+    android::CallStack stack;
+    stack.update(0, tid);
+    if(dump_fd != -1) {
+        stack.dump(dump_fd, 0, NULL);  //Dump to file
+    } else {
+        stack.log(LOG_TAG, ANDROID_LOG_DEBUG, NULL);  //Dump to mainlog
+    }
+#endif
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  mnld_dump_exit
+ * DESCRIPTION
+ *  To dump specified thread's backtrace and exit current process.
+ *  If the tid equal to current process id(pid), will dump all threads of current process.
+ * PARAMETERS
+ *  tid         [IN]   the thread id(tid) need to be dumped
+ *
+ * RETURNS
+ *  None
+ *****************************************************************************/
+extern "C" void mnld_dump_exit(void)
+{
+    int dump_fd = 0;
+    char dump_file_full[MNLD_DUMP_FILE_LEN] = {0};
+    char dump_file_full2[MNLD_DUMP_FILE_LEN] = {0};
+
+    mnld_dump_get_filename(dump_file_full, MNLD_DUMP_FILE_LEN);
+    dump_fd = open(dump_file_full, O_RDWR|O_NONBLOCK|O_CREAT, 0660);
+    mnld_dump_process(dump_fd);
+    if(dump_fd != -1) {
+        MNLD_STRNCPY(dump_file_full2, dump_file_full, MNLD_DUMP_FILE_LEN);
+        dump_file_full2[strlen(dump_file_full2)-1] = '\0';
+        if(rename(dump_file_full, dump_file_full2) != 0) {
+            LOGW("rename faile(%s)", strerror(errno));
+        }
+        close(dump_fd);
+    }
+    gps_dbg_log_exit_flush(0);
+    _exit(0);
+}
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_data_coder.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_data_coder.c
new file mode 100644
index 0000000..c641f22
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_data_coder.c
@@ -0,0 +1,256 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include "mtk_socket_data_coder.h"
+
+bool mtk_socket_get_bool(char* buff, int* offset) {
+    bool ret = (mtk_socket_get_char(buff, offset) == 0)? false : true;
+    return ret;
+}
+
+char mtk_socket_get_char(char* buff, int* offset) {
+    char ret = buff[*offset];
+    *offset += 1;
+    return ret;
+}
+
+short mtk_socket_get_short(char* buff, int* offset) {
+    short ret = 0;
+    ret |= mtk_socket_get_char(buff, offset) & 0xff;
+    ret |= (mtk_socket_get_char(buff, offset) << 8);
+    return ret;
+}
+
+int mtk_socket_get_int(char* buff, int* offset) {
+    int ret = 0;
+    ret |= mtk_socket_get_short(buff, offset) & 0xffff;
+    ret |= (mtk_socket_get_short(buff, offset) << 16);
+    return ret;
+}
+
+int64_t mtk_socket_get_int64_t(char* buff, int* offset) {
+    int64_t ret = 0;
+    ret |= mtk_socket_get_int(buff, offset) & 0xffffffffL;
+    ret |= ((int64_t)mtk_socket_get_int(buff, offset) << 32);
+    return ret;
+}
+
+float mtk_socket_get_float(char* buff, int* offset) {
+    float ret;
+    int tmp = mtk_socket_get_int(buff, offset);
+    ret = *((float*)&tmp);
+    return ret;
+}
+
+double mtk_socket_get_double(char* buff, int* offset) {
+    double ret;
+    int64_t tmp = mtk_socket_get_int64_t(buff, offset);
+    ret = *((double*)&tmp);
+    return ret;
+}
+
+int mtk_socket_get_string(char* buff, int* offset, char* output, int max_size) {
+    int size = mtk_socket_get_int(buff, offset);
+    memset(output, 0, max_size);
+    memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+    output[max_size - 1] = 0;
+    *offset += size;
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_bool_array(char* buff, int* offset, bool output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        bool data = mtk_socket_get_bool(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_char_array(char* buff, int* offset, char output[], int max_size) {
+    int size = mtk_socket_get_int(buff, offset);
+    memcpy(output, &buff[*offset], (size > max_size)? max_size : size);
+    *offset += size;
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_short_array(char* buff, int* offset, short output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        short data = mtk_socket_get_short(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int_array(char* buff, int* offset, int output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        int data = mtk_socket_get_int(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_int64_t_array(char* buff, int* offset, int64_t output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        int64_t data = mtk_socket_get_int64_t(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_float_array(char* buff, int* offset, float output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        float data = mtk_socket_get_float(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_double_array(char* buff, int* offset, double output[], int max_size) {
+    int i = 0;
+    int size = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size; i++) {
+        double data = mtk_socket_get_double(buff, offset);
+        if(i < max_size) {
+            output[i] = data;
+        }
+    }
+    return (size > max_size)? max_size : size;
+}
+
+int mtk_socket_get_string_array(char* buff, int* offset, void* output, int max_size1, int max_size2) {
+    int i = 0;
+    int size1 = mtk_socket_get_int(buff, offset);
+    for(i = 0; i < size1; i++) {
+        if(i < max_size1) {
+            mtk_socket_get_string(buff, offset, output, max_size2);
+            output = (char*)output + max_size2;
+        } else {
+            char tmp[max_size2];
+            mtk_socket_get_string(buff, offset, tmp, max_size2);
+        }
+    }
+    return (size1 > max_size1)? max_size1 : size1;
+}
+
+void mtk_socket_put_bool(char* buff, int* offset, bool input) {
+    mtk_socket_put_char(buff, offset, input);
+}
+
+void mtk_socket_put_char(char* buff, int* offset, char input) {
+    *((char*)&buff[*offset]) = input;
+    *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, short input) {
+    mtk_socket_put_char(buff, offset, input & 0xff);
+    mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int input) {
+    mtk_socket_put_short(buff, offset, input & 0xffff);
+    mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+void mtk_socket_put_int64_t(char* buff, int* offset, int64_t input) {
+    mtk_socket_put_int(buff, offset, input & 0xffffffffL);
+    mtk_socket_put_int(buff, offset, ((input >> 32L) & 0xffffffffL));
+}
+
+void mtk_socket_put_float(char* buff, int* offset, float input) {
+    int* data = (int*)&input;
+    mtk_socket_put_int(buff, offset, *data);
+}
+
+void mtk_socket_put_double(char* buff, int* offset, double input) {
+    int64_t* data = (int64_t*)&input;
+    mtk_socket_put_int64_t(buff, offset, *data);
+}
+
+void mtk_socket_put_string(char* buff, int* offset, const char* input) {
+    int len = strlen(input);
+    mtk_socket_put_int(buff, offset, len);
+    memcpy(&buff[*offset], input, len);
+    *offset += len;
+}
+
+void mtk_socket_put_bool_array(char* buff, int* offset, bool input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_bool(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_char_array(char* buff, int* offset, char input[], int size) {
+    mtk_socket_put_int(buff, offset, size);
+    memcpy(&buff[*offset], input, size);
+    *offset += size;
+}
+
+void mtk_socket_put_short_array(char* buff, int* offset, short input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_short(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_int_array(char* buff, int* offset, int input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_int(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_int64_t_array(char* buff, int* offset, int64_t input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_int64_t(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_float_array(char* buff, int* offset, float input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_float(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_double_array(char* buff, int* offset, double input[], int size) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size);
+    for(i = 0; i < size; i++) {
+        mtk_socket_put_double(buff, offset, input[i]);
+    }
+}
+
+void mtk_socket_put_string_array(char* buff, int* offset, void* input, int size1, int size2) {
+    int i = 0;
+    mtk_socket_put_int(buff, offset, size1);
+    for(i = 0; i < size1; i++) {
+        mtk_socket_put_string(buff, offset, (char*)input);
+        input = (char*)input + size2;
+    }
+}
+
diff --git a/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_utils.c b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_utils.c
new file mode 100644
index 0000000..30aee1e
--- /dev/null
+++ b/src/connectivity/gps/mtk_mnld/utility/src/mtk_socket_utils.c
@@ -0,0 +1,611 @@
+// This source code is generated by UdpGeneratorTool, not recommend to modify it directly
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stddef.h> // offsetof
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h> //usleep
+#include <sys/socket.h>
+#include <string.h>
+#include <fcntl.h>
+#include <arpa/inet.h> //inet_addr
+#include <sys/un.h> //struct sockaddr_un
+#include <sys/epoll.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <inttypes.h>
+
+#include "mtk_socket_utils.h"
+#include "mtk_socket_data_coder.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "mtk_socket"
+#endif
+
+//-1 means failure
+int mtk_socket_server_bind_network(int port) {
+    struct sockaddr_in addr;
+    memset(&addr, 0, sizeof(addr));
+    int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        LOGE("socket() failed reason=[%s]%d", strerror(errno), errno);
+        return -1;
+    }
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+        LOGE("bind() failed reason=[%s]%d for port=[%d]", strerror(errno), errno, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_network_ipv6(int port) {
+    struct sockaddr_in6 addr;
+    memset(&addr, 0, sizeof(addr));
+    int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        LOGE("socket() failed reason=[%s]%d", strerror(errno), errno);
+        return -1;
+    }
+    addr.sin6_family = AF_INET6;
+    addr.sin6_port = htons(port);
+    addr.sin6_addr = in6addr_any;
+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+        LOGE("bind() failed reason=[%s]%d for port=[%d]", strerror(errno), errno, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+//-1 means failure
+int mtk_socket_server_bind_local(const char* path, mtk_socket_namespace sock_namespace) {
+    int size;
+    struct sockaddr_un addr;
+    int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("socket() failed reason=[%s]%d", strerror(errno), errno);
+        return -1;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    size = strlen(path) + offsetof(struct sockaddr_un, sun_path) + 1;
+    if(sock_namespace == SOCK_NS_ABSTRACT) {
+        addr.sun_path[0] = 0;
+        memcpy(addr.sun_path + 1, path, strlen(path));
+    } else if(sock_namespace == SOCK_NS_FILESYSTEM) {
+        strcpy(addr.sun_path, path);
+        unlink(addr.sun_path);
+    } else {
+        LOGE("unknown namespace=[%d]", sock_namespace);
+        close(fd);
+        return -1;
+    }
+    if (bind(fd, (struct sockaddr *)&addr, size) == -1) {
+        LOGE("bind() failed reason=[%s]%d for path=[%s]",
+            strerror(errno), errno, path);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+
+void mtk_socket_client_init_network(mtk_socket_fd* sock_fd, const char* host, int port) {
+    int len = strlen(host);
+    memset(sock_fd, 0, sizeof(*sock_fd));
+    sock_fd->fd = -1;
+    sock_fd->is_local = false;
+    pthread_mutex_init(&sock_fd->mutex, NULL);
+    sock_fd->host = malloc(len + 1);
+    strcpy(sock_fd->host, host);
+    sock_fd->port = port;
+}
+
+void mtk_socket_client_init_local(mtk_socket_fd* sock_fd, const char* path, mtk_socket_namespace sock_namespace) {
+    int len = strlen(path);
+    memset(sock_fd, 0, sizeof(*sock_fd));
+    sock_fd->fd = -1;
+    sock_fd->is_local = true;
+    pthread_mutex_init(&sock_fd->mutex, NULL);
+    sock_fd->path = malloc(len + 1);
+    strcpy(sock_fd->path, path);
+    sock_fd->namesapce = sock_namespace;
+}
+
+void mtk_socket_client_cleanup(mtk_socket_fd* sock_fd) {
+    mtk_socket_client_close(sock_fd);
+    if(sock_fd->host) {
+        free(sock_fd->host);
+        sock_fd->host = NULL;
+    }
+    if(sock_fd->path) {
+        free(sock_fd->path);
+        sock_fd->path = NULL;
+    }
+}
+
+static bool mtk_socket_connect_local(mtk_socket_fd* sock_fd) {
+    int size;
+    struct sockaddr_un addr;
+    int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        LOGE("socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return false;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_LOCAL;
+    size = strlen(sock_fd->path) + offsetof(struct sockaddr_un, sun_path) + 1;
+    if(sock_fd->namesapce == SOCK_NS_ABSTRACT) {
+        addr.sun_path[0] = 0;
+        memcpy(addr.sun_path + 1, sock_fd->path, strlen(sock_fd->path));
+    } else if(sock_fd->namesapce == SOCK_NS_FILESYSTEM) {
+        strcpy(addr.sun_path, sock_fd->path);
+    } else {
+        LOGE("unknown namespace=[%d]", sock_fd->namesapce);
+        close(fd);
+        return false;
+    }
+    if (connect(fd, (struct sockaddr *)&addr, size) < 0) {
+        LOGE("connect() failed reason=[%s]%d for path=[%s]",
+            strerror(errno), errno, sock_fd->path);
+        close(fd);
+        return false;
+    }
+    sock_fd->fd = fd;
+    return true;
+}
+
+static int mtk_socket_connect_network_ipv4(struct sockaddr_in* addr) {
+    int port = ntohs(addr->sin_port);
+    char ip_str[64] = {0};
+    inet_ntop(AF_INET, &(addr->sin_addr), ip_str, sizeof(ip_str));
+    int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        LOGE("socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    //LOGD("IPv4=[%s] port=[%d]", ip_str, port);
+    if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+        LOGE("connect() failed reason=[%s]%d for host=[%s] port=[%d]",
+            strerror(errno), errno, ip_str, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+//-1 means failure
+static int mtk_socket_connect_network_ipv6(struct sockaddr_in6* addr) {
+    int port = ntohs(addr->sin6_port);
+    int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd < 0) {
+        LOGE("socket() failed reason=[%s]%d",
+            strerror(errno), errno);
+        return -1;
+    }
+    //unsigned char* ipv6_addr = addr->sin6_addr.s6_addr;
+    //LOGD("mtk_socket_connect_network_ipv6() IPv6=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x] port=[%d]",
+    //    ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3], ipv6_addr[4], ipv6_addr[5], ipv6_addr[6], ipv6_addr[7],
+    //    ipv6_addr[8], ipv6_addr[9], ipv6_addr[10], ipv6_addr[11], ipv6_addr[12], ipv6_addr[13], ipv6_addr[14], ipv6_addr[15],
+    //    port);
+    if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+        LOGE("connect() failed reason=[%s]%d for port=[%d]",
+            strerror(errno), errno, port);
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+
+static bool mtk_socket_connect_network(mtk_socket_fd* sock_fd) {
+    struct addrinfo hints;
+    struct addrinfo *result;
+    struct addrinfo *rp;
+    int ret;
+    char port_str[11] = {0};
+    sprintf(port_str, "%u", sock_fd->port);
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_UNSPEC;    // Allow IPv4 or IPv6, AF_UNSPEC, AF_INET, AF_INET6
+    hints.ai_socktype = SOCK_DGRAM;
+    hints.ai_flags = AI_ADDRCONFIG; // check local system
+    hints.ai_protocol = IPPROTO_UDP;
+    ret = getaddrinfo(sock_fd->host, port_str, &hints, &result);
+    if(ret != 0) {
+        LOGE("getaddrinfo() failure reason=[%s] %d\n",
+            gai_strerror(ret), ret);
+        return false;
+    }
+    for (rp = result; rp != NULL; rp = rp->ai_next) {
+        if(rp->ai_family == AF_INET) {
+            ret = mtk_socket_connect_network_ipv4((struct sockaddr_in*)rp->ai_addr);
+            if(ret >= 0) {
+                sock_fd->fd = ret;
+                break;
+            }
+        }
+        if(rp->ai_family == AF_INET6) {
+            ret = mtk_socket_connect_network_ipv6((struct sockaddr_in6*)rp->ai_addr);
+            if(ret >= 0) {
+                sock_fd->fd = ret;
+                break;
+            }
+        }
+    }
+    freeaddrinfo(result);
+    if(ret >= 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool mtk_socket_client_connect(mtk_socket_fd* sock_fd) {
+    if(sock_fd->is_local) {
+        return mtk_socket_connect_local(sock_fd);
+    } else {
+        return mtk_socket_connect_network(sock_fd);
+    }
+}
+
+void mtk_socket_client_close(mtk_socket_fd* sock_fd) {
+    if(sock_fd->fd >= 0) {
+        close(sock_fd->fd);
+        sock_fd->fd = -1;
+    }
+}
+
+//-1 means failure
+int mtk_socket_read(int fd, char* buff, int len) {
+    int n, retry = 10;
+    if(fd < 0 || buff == NULL || len < 0) {
+        LOGE("invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+        return -1;
+    }
+    if(len == 0) {
+        return 0;
+    }
+    while((n = read(fd, buff, len)) < 0) {
+        if(errno == EINTR) continue;
+        if(errno == EAGAIN) {
+            if(retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+            goto exit;
+        }
+        goto exit;
+    }
+    return n;
+exit:
+    LOGE("read() failed, fd=[%d] len=[%d] errno=[%s]%d",
+        fd, len, strerror(errno), errno);
+    return -1;
+}
+
+//-1 means failure
+int mtk_socket_write(int fd, void* buff, int len) {
+    int n, retry = 10;
+    if(fd < 0 || buff == NULL || len < 0) {
+        LOGE("invalid params fd=[%d] buff=[%p] len=[%d]", fd, buff, len);
+        return -1;
+    }
+    while((n = write(fd, buff, len)) != len) {
+        if(errno == EINTR) continue;
+        if(errno == EAGAIN) {
+            if(retry-- > 0) {
+                usleep(100 * 1000);
+                continue;
+            }
+            goto exit;
+        }
+        goto exit;
+    }
+    return n;
+exit:
+    LOGE("write() failed, fd=[%d] len=[%d] errno=[%s]%d\n",
+        fd, len, strerror(errno), errno);
+    return -1;
+}
+
+// <= 0 means no data received
+int mtk_socket_poll(int fd, int timeout) {
+    struct pollfd poll_fd[1];
+    int ret = 0;
+    memset(poll_fd, 0, sizeof(poll_fd));
+    poll_fd[0].fd      = fd;
+    poll_fd[0].events  = POLLIN;
+    poll_fd[0].revents = 0;
+
+    ret = poll(poll_fd, 1, timeout);
+    if(ret > 0) {
+        if(poll_fd[0].revents & POLLIN ||
+            poll_fd[0].revents & POLLERR) {
+            ret = 1 << 0;
+        }
+    }
+    return ret;
+}
+
+void mtk_socket_buff_dump(const char* buff, int len) {
+    int i = 0;
+    char tmp[512] = {0};
+    LOGD("len=%d", len);
+    for(i = 0; i < len; i++) {
+        if((i % 16 == 0) && (i != 0)) {
+            LOGD("  %s", tmp);
+            memset(tmp, 0, sizeof(tmp));
+        }
+        sprintf(tmp + ((i % 16) * 3), "%02x ", buff[i] & 0xff);
+    }
+    if(i > 0) {
+        LOGD("  %s", tmp);
+    }
+}
+
+bool mtk_socket_string_is_equal(char* data1, char* data2) {
+    return (strcmp(data1, data2) == 0)? true : false;
+}
+
+bool mtk_socket_bool_array_is_equal(bool data1[], int data1_size, bool data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_char_array_is_equal(char data1[], int data1_size, char data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_short_array_is_equal(short data1[], int data1_size, short data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_int_array_is_equal(int data1[], int data1_size, int data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_int64_t_array_is_equal(int64_t data1[], int data1_size, int64_t data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_float_array_is_equal(float data1[], int data1_size, float data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_double_array_is_equal(double data1[], int data1_size, double data2[], int data2_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(data1[i] != data2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool mtk_socket_string_array_is_equal(void* data1, int data1_size, void* data2, int data2_size, int string_size) {
+    int i = 0;
+    if(data1_size != data2_size) {
+        return false;
+    }
+    for(i = 0; i < data1_size; i++) {
+        if(!mtk_socket_string_is_equal(data1, data2)) {
+            return false;
+        }
+        data1 = (char*)data1 + string_size;
+        data2 = (char*)data2 + string_size;
+    }
+    return true;
+}
+
+void mtk_socket_bool_array_dump(bool input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i]);
+    }
+}
+
+void mtk_socket_char_array_dump(char input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i] & 0xff);
+    }
+}
+
+void mtk_socket_short_array_dump(short input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i] & 0xffff);
+    }
+}
+
+void mtk_socket_int_array_dump(int input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%d]", i, input[i]);
+    }
+}
+
+void mtk_socket_int64_t_array_dump(int64_t input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%lld]", i, (long long)input[i]);
+    }
+}
+
+void mtk_socket_float_array_dump(float input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%f]", i, input[i]);
+    }
+}
+
+void mtk_socket_double_array_dump(double input[], int size) {
+    int i = 0;
+    LOGD("size=%d", size);
+    for(i = 0; i < size; i++) {
+        LOGD("  i=[%d] data=[%f]", i, input[i]);
+    }
+}
+
+void mtk_socket_string_array_dump(void* input, int size1, int size2) {
+    int i = 0;
+    LOGD("size1=%d size2=%d", size1, size2);
+    for(i = 0; i < size1; i++) {
+        LOGD("  i=[%d] data=[%s]", i, (char*)input);
+        input = (char*)input + size2;
+    }
+}
+
+bool mtk_socket_expected_bool(char* buff, int* offset, bool expected_value, const char* func, int line) {
+    bool value = mtk_socket_get_bool(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_char(char* buff, int* offset, char expected_value, const char* func, int line) {
+    char value = mtk_socket_get_char(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_short(char* buff, int* offset, short expected_value, const char* func, int line) {
+    short value = mtk_socket_get_short(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_int(char* buff, int* offset, int expected_value, const char* func, int line) {
+    int value = mtk_socket_get_int(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%d], expected=[%d]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_int64_t(char* buff, int* offset, int64_t expected_value, const char* func, int line) {
+    int64_t value = mtk_socket_get_int64_t(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%"PRId64"], expected=[%"PRId64"]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_float(char* buff, int* offset, float expected_value, const char* func, int line) {
+    float value = mtk_socket_get_float(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%f], expected=[%f]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_double(char* buff, int* offset, double expected_value, const char* func, int line) {
+    double value = mtk_socket_get_double(buff, offset);
+    if(value != expected_value) {
+        LOGE("%s():%d failed, read=[%f], expected=[%f]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
+
+bool mtk_socket_expected_string(char* buff, int* offset, const char* expected_value, int max_size, const char* func, int line) {
+    char value[max_size];
+    mtk_socket_get_string(buff, offset, value, sizeof(value));
+    if(strcmp(value, expected_value) != 0) {
+        LOGE("%s():%d failed, read=[%s], expected=[%s]",
+            func, line, value, expected_value);
+        return false;
+    }
+    return true;
+}
diff --git a/src/connectivity/gps/service/1.0/AGnss.cpp b/src/connectivity/gps/service/1.0/AGnss.cpp
new file mode 100644
index 0000000..29c6ddd
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/AGnss.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_AGnssInterface"
+
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
+sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
+bool AGnss::sInterfaceExists = false;
+
+AGpsCallbacks AGnss::sAGnssCb = {
+    .status_cb = statusCb,
+    .create_thread_cb = createThreadCb
+};
+
+AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+AGnss::~AGnss() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+void AGnss::statusCb(AGpsStatus* status) {
+    if (sAGnssCbIface == nullptr) {
+        ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("AGNSS status is invalid");
+        return;
+    }
+
+    /*
+     * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
+     * AGpsStatus is checked for backward compatibility since some devices may
+     * be sending out an older version of AGpsStatus that only supports IPv4.
+     */
+    size_t statusSize = status->size;
+    if (status->size == sizeof(AGpsStatus)) {
+        switch (status->addr.ss_family)
+        {
+            case AF_INET:
+                {
+                    /*
+                     * ss_family indicates IPv4.
+                     */
+                    struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
+                    IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+                        .type = static_cast<IAGnssCallback::AGnssType>(status->type),
+                        .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+                        .ipV4Addr = in->sin_addr.s_addr,
+                    };
+
+                    /*
+                     * Callback to client with agnssStatusIpV4Cb.
+                     */
+                    auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+                    if (!ret.isOk()) {
+                        ALOGE("%s: Unable to invoke callback", __func__);
+                    }
+                    break;
+                }
+            case AF_INET6:
+                {
+                    /*
+                     * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
+                     */
+                    IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
+
+                    aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
+                    aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
+                            status->status);
+
+                    struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
+                            &(status->addr));
+                    memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
+                           aGnssStatusIpV6.ipV6Addr.size());
+                    auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
+                    if (!ret.isOk()) {
+                        ALOGE("%s: Unable to invoke callback", __func__);
+                    }
+                    break;
+                }
+             default:
+                    ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
+        }
+    } else if (statusSize >= sizeof(AGpsStatus_v2)) {
+        AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
+        uint32_t ipV4Addr = statusV2->ipaddr;
+        IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+            .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
+            .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+            /*
+             * For older versions of AGpsStatus, change IP addr to net order. This
+             * was earlier being done in GnssLocationProvider.
+             */
+            .ipV4Addr = htonl(ipV4Addr)
+        };
+        /*
+         * Callback to client with agnssStatusIpV4Cb.
+         */
+        auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+        }
+    } else {
+        ALOGE("%s: Invalid size for AGPS Status", __func__);
+    }
+}
+
+pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+/*
+ * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
+ */
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return Void();
+    }
+
+    sAGnssCbIface = callback;
+
+    mAGnssIface->init(&sAGnssCb);
+    return Void();
+}
+
+Return<bool> AGnss::dataConnClosed()  {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_closed() == 0);
+}
+
+Return<bool> AGnss::dataConnFailed()  {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_failed() == 0);
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+                              const hidl_string& hostname,
+                              int32_t port) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
+                                                     static_cast<uint16_t>(apnIpType)) == 0);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/AGnss.h b/src/connectivity/gps/service/1.0/AGnss.h
new file mode 100644
index 0000000..2a8eed0
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/AGnss.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_AGnss_H_
+#define android_hardware_gnss_V1_0_AGnss_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hardware/gps_internal.h>
+#include <hidl/Status.h>
+#include <netinet/in.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for AGNSS support. Also contains wrapper methods to allow
+ * methods from IAGnssCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct AGnss : public IAGnss {
+    AGnss(const AGpsInterface* agpsIface);
+    ~AGnss();
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+     * These declarations were generated from IAGnss.hal.
+     */
+    Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+    Return<bool> dataConnClosed() override;
+    Return<bool> dataConnFailed() override;
+    Return<bool> setServer(IAGnssCallback::AGnssType type,
+                         const hidl_string& hostname, int32_t port) override;
+    Return<bool> dataConnOpen(const hidl_string& apn,
+                                           IAGnss::ApnIpType apnIpType) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IAGnss base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void statusCb(AGpsStatus* status);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static AGpsCallbacks sAGnssCb;
+
+ private:
+    const AGpsInterface* mAGnssIface = nullptr;
+    static sp<IAGnssCallback> sAGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_AGnss_H_
diff --git a/src/connectivity/gps/service/1.0/AGnssRil.cpp b/src/connectivity/gps/service/1.0/AGnssRil.cpp
new file mode 100644
index 0000000..1458327
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/AGnssRil.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_AGnssRilInterface"
+
+#include "AGnssRil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnssRil::sThreadFuncArgsList;
+sp<IAGnssRilCallback> AGnssRil::sAGnssRilCbIface = nullptr;
+bool AGnssRil::sInterfaceExists = false;
+
+AGpsRilCallbacks AGnssRil::sAGnssRilCb = {
+    .request_setid = AGnssRil::requestSetId,
+    .request_refloc = AGnssRil::requestRefLoc,
+    .create_thread_cb = AGnssRil::createThreadCb
+};
+
+AGnssRil::AGnssRil(const AGpsRilInterface* aGpsRilIface) : mAGnssRilIface(aGpsRilIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+AGnssRil::~AGnssRil() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+void AGnssRil::requestSetId(uint32_t flags) {
+    if (sAGnssRilCbIface == nullptr) {
+        ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = sAGnssRilCbIface->requestSetIdCb(flags);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void AGnssRil::requestRefLoc(uint32_t /*flags*/) {
+    if (sAGnssRilCbIface == nullptr) {
+        ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = sAGnssRilCbIface->requestRefLocCb();
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+pthread_t AGnssRil::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+Return<void> AGnssRil::setCallback(const sp<IAGnssRilCallback>& callback)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return Void();
+    }
+
+    sAGnssRilCbIface = callback;
+
+    mAGnssRilIface->init(&sAGnssRilCb);
+    return Void();
+}
+
+Return<void> AGnssRil::setRefLocation(const IAGnssRil::AGnssRefLocation& aGnssRefLocation)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return Void();
+    }
+
+    AGpsRefLocation aGnssRefloc;
+    aGnssRefloc.type = static_cast<uint16_t>(aGnssRefLocation.type);
+
+    auto& cellID = aGnssRefLocation.cellID;
+    aGnssRefloc.u.cellID = {
+        .type = static_cast<uint16_t>(cellID.type),
+        .mcc = cellID.mcc,
+        .mnc = cellID.mnc,
+        .lac = cellID.lac,
+        .cid = cellID.cid,
+        .tac = cellID.tac,
+        .pcid = cellID.pcid
+    };
+
+    mAGnssRilIface->set_ref_location(&aGnssRefloc, sizeof(aGnssRefloc));
+    return Void();
+}
+
+Return<bool> AGnssRil::setSetId(IAGnssRil::SetIDType type, const hidl_string& setid)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->set_set_id(static_cast<uint16_t>(type), setid.c_str());
+    return true;
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected,
+                                          IAGnssRil::NetworkType type,
+                                          bool roaming) {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->update_network_state(connected,
+                                         static_cast<int>(type),
+                                         roaming,
+                                         nullptr /* extra_info */);
+    return true;
+}
+
+Return<bool> AGnssRil::updateNetworkAvailability(bool available, const hidl_string& apn)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->update_network_availability(available, apn.c_str());
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/AGnssRil.h b/src/connectivity/gps/service/1.0/AGnssRil.h
new file mode 100644
index 0000000..6215a9e
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/AGnssRil.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_AGnssRil_H_
+#define android_hardware_gnss_V1_0_AGnssRil_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+    AGnssRil(const AGpsRilInterface* aGpsRilIface);
+    ~AGnssRil();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+     * These declarations were generated from IAGnssRil.hal.
+     */
+    Return<void> setCallback(const sp<IAGnssRilCallback>& callback) override;
+    Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& agnssReflocation) override;
+    Return<bool> setSetId(IAGnssRil::SetIDType type, const hidl_string& setid) override;
+    Return<bool> updateNetworkState(bool connected,
+                                    IAGnssRil::NetworkType type,
+                                    bool roaming) override;
+    Return<bool> updateNetworkAvailability(bool available, const hidl_string& apn) override;
+    static void requestSetId(uint32_t flags);
+    static void requestRefLoc(uint32_t flags);
+
+    /*
+     * Callback method to be passed into the conventional GNSS HAL by the default
+     * implementation. This method is not part of the IAGnssRil base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static AGpsRilCallbacks sAGnssRilCb;
+
+ private:
+    const AGpsRilInterface* mAGnssRilIface = nullptr;
+    static sp<IAGnssRilCallback> sAGnssRilCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_AGnssRil_H_
diff --git a/src/connectivity/gps/service/1.0/Android.mk b/src/connectivity/gps/service/1.0/Android.mk
new file mode 100644
index 0000000..db53aff
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/Android.mk
@@ -0,0 +1,63 @@
+#ifdef HIDL_V1_0
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-impl-mediatek
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    ThreadCreationWrapper.cpp \
+    AGnss.cpp \
+    AGnssRil.cpp \
+    Gnss.cpp \
+    GnssBatching.cpp \
+    GnssDebug.cpp \
+    GnssGeofencing.cpp \
+    GnssMeasurement.cpp \
+    GnssNavigationMessage.cpp \
+    GnssNi.cpp \
+    GnssXtra.cpp \
+    GnssConfiguration.cpp \
+    GnssUtils.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libhidlbase \
+    libhidltransport \
+    libutils \
+    android.hardware.gnss@1.0 \
+    libhardware \
+
+LOCAL_CFLAGS += -Werror
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE := android.hardware.gnss@1.0-service-mediatek
+LOCAL_INIT_RC := android.hardware.gnss@1.0-service-mediatek.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware \
+    libbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.gnss@1.0 \
+
+LOCAL_REQUIRED_MODULES := \
+    android.hardware.gnss@1.0-impl-mediatek
+
+include $(BUILD_EXECUTABLE)
+
+#endif
diff --git a/src/connectivity/gps/service/1.0/Gnss.cpp b/src/connectivity/gps/service/1.0/Gnss.cpp
new file mode 100644
index 0000000..c91e67a
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/Gnss.cpp
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssInterface"
+
+#include "Gnss.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> Gnss::sThreadFuncArgsList;
+sp<IGnssCallback> Gnss::sGnssCbIface = nullptr;
+bool Gnss::sInterfaceExists = false;
+bool Gnss::sWakelockHeldGnss = false;
+bool Gnss::sWakelockHeldFused = false;
+
+GpsCallbacks_ext Gnss::sGnssCb = {
+    .size = sizeof(GpsCallbacks_ext),
+    .location_cb = locationCb,
+    .status_cb = statusCb,
+    .sv_status_cb = gpsSvStatusCb,
+    .nmea_cb = nmeaCb,
+    .set_capabilities_cb = setCapabilitiesCb,
+    .acquire_wakelock_cb = acquireWakelockCb,
+    .release_wakelock_cb = releaseWakelockCb,
+    .create_thread_cb = createThreadCb,
+    .request_utc_time_cb = requestUtcTimeCb,
+    .set_system_info_cb = setSystemInfoCb,
+    .gnss_sv_status_cb = gnssSvStatusCb,
+
+    .set_name_cb = setNameCb,
+    .request_location_cb = requestLocationCb
+};
+
+uint32_t Gnss::sCapabilitiesCached = 0;
+uint16_t Gnss::sYearOfHwCached = 0;
+sem_t Gnss::sSem;
+
+Gnss::Gnss(gps_device_t_ext* gnssDevice) :
+        mDeathRecipient(new GnssHidlDeathRecipient(this)) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+
+    if (gnssDevice == nullptr) {
+        ALOGE("%s: Invalid device_t handle", __func__);
+        return;
+    }
+
+    mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
+    sem_init(&sSem, 0, 1);
+}
+
+Gnss::~Gnss() {
+    sInterfaceExists = false;
+    sThreadFuncArgsList.clear();
+    sem_destroy(&sSem);
+}
+
+void Gnss::locationCb(GpsLocation_ext* location) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s: Invalid location from GNSS HAL", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    GnssLocation gnssLocation = V1_0::implementation::convertToGnssLocation(location);
+    auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::statusCb(GpsStatus* gnssStatus) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (gnssStatus == nullptr) {
+        ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssStatusValue status =
+            static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
+
+    auto ret = sGnssCbIface->gnssStatusCb(status);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::gnssSvStatusCb(GnssSvStatus_ext* status) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = status->num_svs;
+
+    if (svStatus.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+        ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, V1_0::GnssMax::SVS_COUNT);
+        svStatus.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+    }
+
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        auto svInfo = status->gnss_sv_list[i];
+        IGnssCallback::GnssSvInfo gnssSvInfo = {
+            .svid = svInfo.legacySvInfo.svid,
+            .constellation = static_cast<V1_0::GnssConstellationType>(
+                    svInfo.legacySvInfo.constellation),
+            .cN0Dbhz = svInfo.legacySvInfo.c_n0_dbhz,
+            .elevationDegrees = svInfo.legacySvInfo.elevation,
+            .azimuthDegrees = svInfo.legacySvInfo.azimuth,
+            .svFlag = static_cast<uint8_t>(svInfo.legacySvInfo.flags),
+            .carrierFrequencyHz = svInfo.carrier_frequency};
+        svStatus.gnssSvList[i] = gnssSvInfo;
+    }
+
+    auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+/*
+ * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
+ * to GnssSvStatus for backward compatibility. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum SvidValues : uint16_t {
+    GLONASS_SVID_OFFSET = 64,
+    GLONASS_SVID_COUNT = 24,
+    BEIDOU_SVID_OFFSET = 200,
+    BEIDOU_SVID_COUNT = 35,
+    SBAS_SVID_MIN = 33,
+    SBAS_SVID_MAX = 64,
+    SBAS_SVID_ADD = 87,
+    QZSS_SVID_MIN = 193,
+    QZSS_SVID_MAX = 200
+};
+
+/*
+ * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
+ * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
+ * being deprecated and is no longer part of the GNSS interface.
+ */
+void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (svInfo == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = svInfo->num_svs;
+    /*
+     * Clamp the list size since GnssSvStatus can support a maximum of
+     * GnssMax::SVS_COUNT entries.
+     */
+    ///M: fix max numSvs as GPS_MAX_SVS
+    if (svStatus.numSvs > static_cast<uint32_t>(GPS_MAX_SVS)) {
+        ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GPS_MAX_SVS);
+        svStatus.numSvs = static_cast<uint32_t>(GPS_MAX_SVS);
+    }
+    /// M: mtk update end
+
+    uint32_t ephemerisMask = svInfo->ephemeris_mask;
+    uint32_t almanacMask = svInfo->almanac_mask;
+    uint32_t usedInFixMask = svInfo->used_in_fix_mask;
+    /*
+     * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
+     */
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
+        info.svid = svInfo->sv_list[i].prn;
+        if (info.svid >= 1 && info.svid <= 32) {
+            info.constellation = GnssConstellationType::GPS;
+        } else if (info.svid > GLONASS_SVID_OFFSET &&
+                   info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
+            info.constellation = GnssConstellationType::GLONASS;
+            info.svid -= GLONASS_SVID_OFFSET;
+        } else if (info.svid > BEIDOU_SVID_OFFSET &&
+                 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
+            info.constellation = GnssConstellationType::BEIDOU;
+            info.svid -= BEIDOU_SVID_OFFSET;
+        } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
+            info.constellation = GnssConstellationType::SBAS;
+            info.svid += SBAS_SVID_ADD;
+        } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
+            info.constellation = GnssConstellationType::QZSS;
+        } else {
+            ALOGD("Unknown constellation type with Svid = %d.", info.svid);
+            info.constellation = GnssConstellationType::UNKNOWN;
+        }
+
+        info.cN0Dbhz = svInfo->sv_list[i].snr;
+        info.elevationDegrees = svInfo->sv_list[i].elevation;
+        info.azimuthDegrees = svInfo->sv_list[i].azimuth;
+        // TODO: b/31702236
+        info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+
+        /*
+         * Only GPS info is valid for these fields, as these masks are just 32
+         * bits, by GPS prn.
+         */
+        if (info.constellation == GnssConstellationType::GPS) {
+            int32_t svidMask = (1 << (info.svid - 1));
+            if ((ephemerisMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+            }
+            if ((almanacMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+            }
+            if ((usedInFixMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+            }
+        }
+    }
+
+    auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    android::hardware::hidl_string nmeaString;
+    nmeaString.setToExternal(nmea, length);
+    auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::setCapabilitiesCb(uint32_t capabilities) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sCapabilitiesCached = capabilities;
+    sem_post(&sSem);
+}
+
+void Gnss::acquireWakelockCb() {
+    acquireWakelockGnss();
+}
+
+void Gnss::releaseWakelockCb() {
+    releaseWakelockGnss();
+}
+
+
+void Gnss::acquireWakelockGnss() {
+    sWakelockHeldGnss = true;
+    updateWakelock();
+}
+
+void Gnss::releaseWakelockGnss() {
+    sWakelockHeldGnss = false;
+    updateWakelock();
+}
+
+void Gnss::acquireWakelockFused() {
+    sWakelockHeldFused = true;
+    updateWakelock();
+}
+
+void Gnss::releaseWakelockFused() {
+    sWakelockHeldFused = false;
+    updateWakelock();
+}
+
+void Gnss::updateWakelock() {
+    // Track the state of the last request - in case the wake lock in the layer above is reference
+    // counted.
+    static bool sWakelockHeld = false;
+
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (sWakelockHeldGnss || sWakelockHeldFused) {
+        if (!sWakelockHeld) {
+            ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
+                    sWakelockHeldGnss, sWakelockHeldFused);
+            sWakelockHeld = true;
+            auto ret = sGnssCbIface->gnssAcquireWakelockCb();
+            if (!ret.isOk()) {
+                ALOGE("%s: Unable to invoke callback", __func__);
+            }
+        }
+    } else {
+        if (sWakelockHeld) {
+            ALOGI("%s: GNSS HAL Wakelock released", __func__);
+        } else  {
+            // To avoid burning power, always release, even if logic got here with sWakelock false
+            // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
+            ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
+        }
+        sWakelockHeld = false;
+        auto ret = sGnssCbIface->gnssReleaseWakelockCb();
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+        }
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::requestUtcTimeCb() {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssRequestTimeCb();
+    if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (info == nullptr) {
+        ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSystemInfo gnssInfo = {
+        .yearOfHw = info->year_of_hw
+    };
+
+    auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sYearOfHwCached = info->year_of_hw;
+    sem_post(&sSem);
+}
+
+void Gnss::setNameCb(const char* name, int length) {
+    UNUSED(name);
+    UNUSED(length);
+}
+
+void Gnss::requestLocationCb(bool independentFromGnss) {
+    UNUSED(independentFromGnss);
+}
+
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    if (callback == nullptr)  {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sem_wait(&sSem);
+    if (sGnssCbIface != NULL) {
+        ALOGW("%s called more than once. Unexpected unless test.", __func__);
+        sGnssCbIface->unlinkToDeath(mDeathRecipient);
+    }
+
+    sGnssCbIface = callback;
+    callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
+    sem_post(&sSem);
+
+    // If this was received in the past, send it up again to refresh caller.
+    // mGnssIface will override after init() is called below, if needed
+    // (though it's unlikely the gps.h capabilities or system info will change.)
+    if (sCapabilitiesCached != 0) {
+        setCapabilitiesCb(sCapabilitiesCached);
+    }
+    if (sYearOfHwCached != 0) {
+        LegacyGnssSystemInfo info;
+        info.year_of_hw = sYearOfHwCached;
+        setSystemInfoCb(&info);
+    }
+
+    return (mGnssIface->init(&sGnssCb) == 0);
+}
+
+Return<bool> Gnss::start()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->start() == 0);
+}
+
+Return<bool> Gnss::stop()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->stop() == 0);
+}
+
+Return<void> Gnss::cleanup()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->cleanup();
+    }
+    return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+                                  double longitudeDegrees,
+                                  float accuracyMeters)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                              int32_t uncertaintyMs) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
+}
+
+Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
+    }
+    return Void();
+}
+
+Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
+                                   IGnss::GnssPositionRecurrence recurrence,
+                                   uint32_t minIntervalMs,
+                                   uint32_t preferredAccuracyMeters,
+                                   uint32_t preferredTimeMs)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
+                                          static_cast<GpsPositionRecurrence>(recurrence),
+                                          minIntervalMs,
+                                          preferredAccuracyMeters,
+                                          preferredTimeMs,
+                                          false /* lowPowerMode*/) == 0);
+}
+
+Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssRil == nullptr) {
+        const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
+                mGnssIface->get_extension(AGPS_RIL_INTERFACE));
+        if (agpsRilIface == nullptr) {
+            ALOGI("%s: GnssRil interface not implemented by HAL", __func__);
+        } else {
+            mGnssRil = new AGnssRil(agpsRilIface);
+        }
+    }
+    return mGnssRil;
+}
+
+Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    /*if (mGnssConfig == nullptr) {
+        const GnssConfigurationInterface* gnssConfigIface =
+                static_cast<const GnssConfigurationInterface*>(
+                        mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
+
+        if (gnssConfigIface == nullptr) {*/
+            ALOGW("%s: GnssConfiguration interface not implemented by HAL", __func__);
+        /*} else {
+            mGnssConfig = new GnssConfiguration(gnssConfigIface);
+        }
+    }*/
+    return mGnssConfig;
+}
+
+Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    /*if (mGnssGeofencingIface == nullptr) {
+        const GpsGeofencingInterface* gpsGeofencingIface =
+                static_cast<const GpsGeofencingInterface*>(
+                        mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
+
+        if (gpsGeofencingIface == nullptr) {*/
+            ALOGE("%s: GnssGeofencing interface not implemented by HAL", __func__);
+/*        } else {
+            mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
+        }
+    }
+*/
+    return mGnssGeofencingIface;
+}
+
+Return<sp<IAGnss>> Gnss::getExtensionAGnss()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mAGnssIface == nullptr) {
+        const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
+                mGnssIface->get_extension(AGPS_INTERFACE));
+        if (agpsIface == nullptr) {
+            ALOGE("%s: AGnss interface not implemented by HAL", __func__);
+        } else {
+            mAGnssIface = new V1_0::implementation::AGnss(agpsIface);
+        }
+    }
+    return mAGnssIface;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssNi == nullptr) {
+        const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
+                mGnssIface->get_extension(GPS_NI_INTERFACE));
+        if (gpsNiIface == nullptr) {
+            ALOGI("%s: GnssNi interface not implemented by HAL", __func__);
+        } else {
+            mGnssNi = new GnssNi(gpsNiIface);
+        }
+    }
+    return mGnssNi;
+}
+
+Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssMeasurement == nullptr) {
+        const GpsMeasurementInterface_ext* gpsMeasurementIface =
+                static_cast<const GpsMeasurementInterface_ext*>(
+                        mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
+
+        if (gpsMeasurementIface == nullptr) {
+            ALOGE("%s: GnssMeasurement interface not implemented by HAL", __func__);
+        } else {
+            mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
+        }
+    }
+    return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssNavigationMessage == nullptr) {
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface =
+                static_cast<const GpsNavigationMessageInterface*>(
+                        mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
+
+        if (gpsNavigationMessageIface == nullptr) {
+            ALOGI("%s: GnssNavigationMessage interface not implemented by HAL", __func__);
+        } else {
+            mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
+        }
+    }
+
+    return mGnssNavigationMessage;
+}
+
+Return<sp<IGnssXtra>> Gnss::getExtensionXtra()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssXtraIface == nullptr) {
+        const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
+                mGnssIface->get_extension(GPS_XTRA_INTERFACE));
+
+        if (gpsXtraIface == nullptr) {
+            ALOGI("%s: GnssXtra interface not implemented by HAL", __func__);
+        } else {
+            mGnssXtraIface = new GnssXtra(gpsXtraIface);
+        }
+    }
+
+    return mGnssXtraIface;
+}
+
+Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssDebug == nullptr) {
+        const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
+                mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
+
+        if (gpsDebugIface == nullptr) {
+            ALOGI("%s: GnssDebug interface not implemented by HAL", __func__);
+        } else {
+            mGnssDebug = new GnssDebug(gpsDebugIface);
+        }
+    }
+
+    return mGnssDebug;
+}
+
+Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssBatching == nullptr) {
+        hw_module_t* module;
+        const FlpLocationInterface* flpLocationIface = nullptr;
+        int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+        if (err != 0) {
+            ALOGE("gnss flp hw_get_module failed: %d", err);
+        } else if (module == nullptr) {
+            ALOGE("Fused Location hw_get_module returned null module");
+        } else if (module->methods == nullptr) {
+            ALOGE("Fused Location hw_get_module returned null methods");
+        } else {
+            hw_device_t* device;
+            err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
+            if (err != 0) {
+                ALOGE("flpDevice open failed: %d", err);
+            } else {
+                flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
+                flpLocationIface = flpDevice->get_flp_interface(flpDevice);
+            }
+        }
+
+        if (flpLocationIface == nullptr) {
+            ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
+        } else {
+            mGnssBatching = new GnssBatching(flpLocationIface);
+        }
+    }
+    return mGnssBatching;
+}
+
+void Gnss::handleHidlDeath() {
+    ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
+
+    /// M: move here! Do not callback to system_server to avoid gnss hidl service NE
+    /*
+     * This has died, so close it off in case (race condition) callbacks happen
+     * before HAL processes above messages.
+     */
+    sem_wait(&sSem);
+    sGnssCbIface = nullptr;
+    sem_post(&sSem);
+
+    // commands down to the HAL implementation
+    stop(); // stop ongoing GPS tracking
+    if (mGnssMeasurement != nullptr) {
+        mGnssMeasurement->close();
+    }
+    if (mGnssNavigationMessage != nullptr) {
+        mGnssNavigationMessage->close();
+    }
+    if (mGnssBatching != nullptr) {
+        mGnssBatching->stop();
+        mGnssBatching->cleanup();
+    }
+    cleanup();
+
+}
+
+IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
+    hw_module_t* module;
+    IGnss* iface = nullptr;
+    int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+    if (err == 0) {
+        hw_device_t* device;
+        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            iface = new Gnss(reinterpret_cast<gps_device_t_ext*>(device));
+        } else {
+            ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+        }
+    } else {
+      ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+    }
+    return iface;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/Gnss.h b/src/connectivity/gps/service/1.0/Gnss.h
new file mode 100644
index 0000000..96fcf6f
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/Gnss.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_Gnss_H_
+#define android_hardware_gnss_V1_0_Gnss_H_
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssDebug.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNavigationMessage.h>
+#include <GnssNi.h>
+#include <GnssXtra.h>
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hardware/fused_location.h>
+#include <hidl/Status.h>
+#include "hardware/gps_mtk.h"
+
+#include <semaphore.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssSystemInfo = ::GnssSystemInfo;
+using GnssConstellationType = V1_0::GnssConstellationType;
+using GnssLocation = V1_0::GnssLocation;
+
+/*
+ * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
+ * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+class Gnss : public IGnss {
+  public:
+    Gnss(gps_device_t_ext* gnss_device);
+    ~Gnss();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+     * These declarations were generated from Gnss.hal.
+     */
+    Return<bool> setCallback(const sp<IGnssCallback>& callback)  override;
+    Return<bool> start()  override;
+    Return<bool> stop()  override;
+    Return<void> cleanup()  override;
+    Return<bool> injectLocation(double latitudeDegrees,
+                                double longitudeDegrees,
+                                float accuracyMeters)  override;
+    Return<bool> injectTime(int64_t timeMs,
+                            int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<void> deleteAidingData(IGnss::GnssAidingData aidingDataFlags)  override;
+    Return<bool> setPositionMode(IGnss::GnssPositionMode mode,
+                                 IGnss::GnssPositionRecurrence recurrence,
+                                 uint32_t minIntervalMs,
+                                 uint32_t preferredAccuracyMeters,
+                                 uint32_t preferredTimeMs)  override;
+    Return<sp<IAGnssRil>> getExtensionAGnssRil() override;
+    Return<sp<IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<IAGnss>> getExtensionAGnss() override;
+    Return<sp<IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+    Return<sp<IGnssXtra>> getExtensionXtra() override;
+    Return<sp<IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<IGnssDebug>> getExtensionGnssDebug() override;
+    Return<sp<IGnssBatching>> getExtensionGnssBatching() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnss base class.
+     */
+    static void locationCb(GpsLocation_ext* location);
+    static void statusCb(GpsStatus* gnss_status);
+    static void nmeaCb(GpsUtcTime timestamp, const char* nmea, int length);
+    static void setCapabilitiesCb(uint32_t capabilities);
+    static void acquireWakelockCb();
+    static void releaseWakelockCb();
+    static void requestUtcTimeCb();
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssSvStatusCb(GnssSvStatus_ext* status);
+    /*
+     * Deprecated callback added for backward compatibility to devices that do
+     * not support GnssSvStatus.
+     */
+    static void gpsSvStatusCb(GpsSvStatus* status);
+    static void setSystemInfoCb(const LegacyGnssSystemInfo* info);
+
+    /*
+     * Wakelock consolidation, only needed for dual use of a gps.h & fused_location.h HAL
+     *
+     * Ensures that if the last call from either legacy .h was to acquire a wakelock, that a
+     * wakelock is held.  Otherwise releases it.
+     */
+    static void acquireWakelockFused();
+    static void releaseWakelockFused();
+
+    static void setNameCb(const char* name, int length);
+    static void requestLocationCb(bool independentFromGnss);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsCallbacks_ext sGnssCb;
+
+ private:
+    /*
+     * For handling system-server death while GNSS service lives on.
+     */
+    class GnssHidlDeathRecipient : public hidl_death_recipient {
+      public:
+        GnssHidlDeathRecipient(const sp<Gnss> gnss) : mGnss(gnss) {
+        }
+
+        virtual void serviceDied(uint64_t /*cookie*/,
+                const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+            mGnss->handleHidlDeath();
+        }
+      private:
+        sp<Gnss> mGnss;
+    };
+
+    // for wakelock consolidation, see above
+    static void acquireWakelockGnss();
+    static void releaseWakelockGnss();
+    static void updateWakelock();
+    static bool sWakelockHeldGnss;
+    static bool sWakelockHeldFused;
+
+    /*
+     * Cleanup for death notification
+     */
+    void handleHidlDeath();
+
+    sp<V1_0::implementation::GnssXtra> mGnssXtraIface = nullptr;
+    sp<V1_0::implementation::AGnssRil> mGnssRil = nullptr;
+    sp<V1_0::implementation::GnssGeofencing> mGnssGeofencingIface = nullptr;
+    sp<V1_0::implementation::AGnss> mAGnssIface = nullptr;
+    sp<V1_0::implementation::GnssNi> mGnssNi = nullptr;
+    sp<V1_0::implementation::GnssMeasurement> mGnssMeasurement = nullptr;
+    sp<V1_0::implementation::GnssNavigationMessage> mGnssNavigationMessage = nullptr;
+    sp<V1_0::implementation::GnssDebug> mGnssDebug = nullptr;
+    sp<V1_0::implementation::GnssConfiguration> mGnssConfig = nullptr;
+    sp<V1_0::implementation::GnssBatching> mGnssBatching = nullptr;
+
+    ///M: add semphore protection
+    static sem_t sSem;
+
+    sp<GnssHidlDeathRecipient> mDeathRecipient;
+    const GpsInterface_ext* mGnssIface = nullptr;
+    static sp<IGnssCallback> sGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+
+    // Values saved for resend
+    static uint32_t sCapabilitiesCached;
+    static uint16_t sYearOfHwCached;
+};
+
+extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_Gnss_H_
diff --git a/src/connectivity/gps/service/1.0/GnssBatching.cpp b/src/connectivity/gps/service/1.0/GnssBatching.cpp
new file mode 100644
index 0000000..1601ea8
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssBatching.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssBatchingInterface"
+
+#include "GnssBatching.h"
+#include <Gnss.h> // for wakelock consolidation
+#include <GnssUtils.h>
+
+#include <log/log.h>  // for ALOGE
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssBatchingCallback> GnssBatching::sGnssBatchingCbIface = nullptr;
+bool GnssBatching::sFlpSupportsBatching = false;
+
+FlpCallbacks GnssBatching::sFlpCb = {
+    .size = sizeof(FlpCallbacks),
+    .location_cb = locationCb,
+    .acquire_wakelock_cb = acquireWakelockCb,
+    .release_wakelock_cb = releaseWakelockCb,
+    .set_thread_event_cb = setThreadEventCb,
+    .flp_capabilities_cb = flpCapabilitiesCb,
+    .flp_status_cb = flpStatusCb,
+};
+
+GnssBatching::GnssBatching(const FlpLocationInterface* flpLocationIface) :
+    mFlpLocationIface(flpLocationIface) {
+}
+
+/*
+ * This enum is used locally by various methods below. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum BatchingValues : uint16_t {
+    // Numbers 0-3 were used in earlier implementations - using 4 to be distinct to the HAL
+    FLP_GNSS_BATCHING_CLIENT_ID = 4,
+    // Tech. mask of GNSS, and sensor aiding, for legacy HAL to fit with GnssBatching API
+    FLP_TECH_MASK_GNSS_AND_SENSORS = FLP_TECH_MASK_GNSS | FLP_TECH_MASK_SENSORS,
+    // Putting a cap to avoid possible memory issues.  Unlikely values this high are supported.
+    MAX_LOCATIONS_PER_BATCH = 1000
+};
+
+void GnssBatching::locationCb(int32_t locationsCount, FlpLocation** locations) {
+    if (sGnssBatchingCbIface == nullptr) {
+        ALOGE("%s: GNSS Batching Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (locations == nullptr) {
+        ALOGE("%s: Invalid locations from GNSS HAL", __func__);
+        return;
+    }
+
+    if (locationsCount < 0) {
+        ALOGE("%s: Negative location count: %d set to 0", __func__, locationsCount);
+        locationsCount = 0;
+    } else if (locationsCount > MAX_LOCATIONS_PER_BATCH) {
+        ALOGW("%s: Unexpected high location count: %d set to %d", __func__, locationsCount,
+                MAX_LOCATIONS_PER_BATCH);
+        locationsCount = MAX_LOCATIONS_PER_BATCH;
+    }
+
+    /**
+     * Note:
+     * Some existing implementations may drop duplicate locations.  These could be expanded here
+     * but as there's ambiguity between no-GPS-fix vs. dropped duplicates in that implementation,
+     * and that's not specified by the fused_location.h, that isn't safe to do here.
+     * Fortunately, this shouldn't be a major issue in cases where GNSS batching is typically
+     * used (e.g. when user is likely in vehicle/bicycle.)
+     */
+    std::vector<android::hardware::gnss::V1_0::GnssLocation> gnssLocations;
+    for (int iLocation = 0; iLocation < locationsCount; iLocation++) {
+        if (locations[iLocation] == nullptr) {
+            ALOGE("%s: Null location at slot: %d of %d, skipping", __func__, iLocation,
+                    locationsCount);
+            continue;
+        }
+        if ((locations[iLocation]->sources_used & ~FLP_TECH_MASK_GNSS_AND_SENSORS) != 0)
+        {
+            ALOGE("%s: Unrequested location type %d at slot: %d of %d, skipping", __func__,
+                    locations[iLocation]->sources_used, iLocation, locationsCount);
+            continue;
+        }
+        gnssLocations.push_back(convertToGnssLocation(locations[iLocation]));
+    }
+
+    auto ret = sGnssBatchingCbIface->gnssLocationBatchCb(gnssLocations);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssBatching::acquireWakelockCb() {
+    Gnss::acquireWakelockFused();
+}
+
+void GnssBatching::releaseWakelockCb() {
+    Gnss::releaseWakelockFused();
+}
+
+// this can just return success, because threads are now set up on demand in the jni layer
+int32_t GnssBatching::setThreadEventCb(ThreadEvent /*event*/) {
+    return FLP_RESULT_SUCCESS;
+}
+
+void GnssBatching::flpCapabilitiesCb(int32_t capabilities) {
+    ALOGD("%s capabilities %d", __func__, capabilities);
+
+    if (capabilities & CAPABILITY_GNSS) {
+        // once callback is received and capabilities high enough, we know version is
+        // high enough for flush()
+        sFlpSupportsBatching = true;
+    }
+}
+
+void GnssBatching::flpStatusCb(int32_t status) {
+    ALOGD("%s (default implementation) not forwarding status: %d", __func__, status);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching is unavailable", __func__);
+        return false;
+    }
+
+    sGnssBatchingCbIface = callback;
+
+    return (mFlpLocationIface->init(&sFlpCb) == 0);
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return 0;
+    }
+
+    return mFlpLocationIface->get_batch_size();
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return false;
+    }
+
+    if (!sFlpSupportsBatching) {
+        ALOGE("%s: Flp batching interface not supported, no capabilities callback received",
+                __func__);
+        return false;
+    }
+
+    FlpBatchOptions optionsHw;
+    // Legacy code used 9999 mW for High accuracy, and 21 mW for balanced.
+    // New GNSS API just expects reasonable GNSS chipset behavior - do something efficient
+    // given the interval.  This 100 mW limit should be quite sufficient (esp. given legacy code
+    // implementations may not even use this value.)
+    optionsHw.max_power_allocation_mW = 100;
+    optionsHw.sources_to_use = FLP_TECH_MASK_GNSS_AND_SENSORS;
+    optionsHw.flags = 0;
+    if (options.flags & Flag::WAKEUP_ON_FIFO_FULL) {
+        optionsHw.flags |= FLP_BATCH_WAKEUP_ON_FIFO_FULL;
+    }
+    optionsHw.period_ns = options.periodNanos;
+    optionsHw.smallest_displacement_meters = 0; // Zero offset - just use time interval
+
+    return (mFlpLocationIface->start_batching(FLP_GNSS_BATCHING_CLIENT_ID, &optionsHw)
+            == FLP_RESULT_SUCCESS);
+}
+
+Return<void> GnssBatching::flush() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return Void();
+    }
+
+    mFlpLocationIface->flush_batched_locations();
+
+    return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mFlpLocationIface->stop_batching(FLP_GNSS_BATCHING_CLIENT_ID) == FLP_RESULT_SUCCESS);
+}
+
+Return<void> GnssBatching::cleanup() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return Void();
+    }
+
+    mFlpLocationIface->cleanup();
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssBatching.h b/src/connectivity/gps/service/1.0/GnssBatching.h
new file mode 100644
index 0000000..001c27d
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssBatching.h
@@ -0,0 +1,67 @@
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hardware/fused_location.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct GnssBatching : public IGnssBatching {
+    GnssBatching(const FlpLocationInterface* flpLocationIface);
+
+    // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+    Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+    Return<uint16_t> getBatchSize() override;
+    Return<bool> start(const IGnssBatching::Options& options ) override;
+    Return<void> flush() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+
+    /*
+     * Callback methods to be passed into the conventional FLP HAL by the default
+     * implementation. These methods are not part of the IGnssBatching base class.
+     */
+    static void locationCb(int32_t locationsCount, FlpLocation** locations);
+    static void acquireWakelockCb();
+    static void releaseWakelockCb();
+    static int32_t setThreadEventCb(ThreadEvent event);
+    static void flpCapabilitiesCb(int32_t capabilities);
+    static void flpStatusCb(int32_t status);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static FlpCallbacks sFlpCb;
+
+ private:
+    const FlpLocationInterface* mFlpLocationIface = nullptr;
+    static sp<IGnssBatchingCallback> sGnssBatchingCbIface;
+    static bool sFlpSupportsBatching;
+};
+
+extern "C" IGnssBatching* HIDL_FETCH_IGnssBatching(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
diff --git a/src/connectivity/gps/service/1.0/GnssConfiguration.cpp b/src/connectivity/gps/service/1.0/GnssConfiguration.cpp
new file mode 100644
index 0000000..0c1aa86
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssConfiguration.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssConfigurationInterface"
+
+#include <log/log.h>
+
+#include "GnssConfiguration.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssConfiguration::GnssConfiguration(const GnssConfigurationInterface* gnssConfigInfc)
+    : mGnssConfigIface(gnssConfigInfc) {}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_ES=" + std::to_string(enabled ? 1 : 0) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_VER=" + std::to_string(version) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_MODE=" + std::to_string(mode) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "LPP_PROFILE=" + std::to_string(lppProfile) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "A_GLONASS_POS_PROTOCOL_SELECT=" +
+            std::to_string(protocol) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "GPS_LOCK=" + std::to_string(lock) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=" + std::to_string(enabled ? 1 : 0)
+            + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssConfiguration.h b/src/connectivity/gps/service/1.0/GnssConfiguration.h
new file mode 100644
index 0000000..a6eca88
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssConfiguration.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef android_hardware_gnss_V1_0_GnssConfiguration_H_
+#define android_hardware_gnss_V1_0_GnssConfiguration_H_
+
+#include <android/hardware/gnss/1.0/IGnssConfiguration.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct GnssConfiguration : public IGnssConfiguration {
+    GnssConfiguration(const GnssConfigurationInterface* gnssConfigIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+     * These declarations were generated from IGnssConfiguration.hal.
+     */
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(uint8_t mode) override;
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setLppProfile(uint8_t lppProfile) override;
+    Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+    Return<bool> setGpsLock(uint8_t lock) override;
+
+ private:
+    const GnssConfigurationInterface* mGnssConfigIface = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssConfiguration_H_
diff --git a/src/connectivity/gps/service/1.0/GnssDebug.cpp b/src/connectivity/gps/service/1.0/GnssDebug.cpp
new file mode 100644
index 0000000..cfc38ca
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssDebug.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssDebugInterface"
+
+#include <log/log.h>
+
+#include "GnssDebug.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssDebug::GnssDebug(const GpsDebugInterface* gpsDebugIface) : mGnssDebugIface(gpsDebugIface) {}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)  {
+    /*
+     * This is a new interface and hence there is no way to retrieve the
+     * debug data from the HAL.
+     */
+    DebugData data = {};
+
+    _hidl_cb(data);
+
+    /*
+     * Log the debug data sent from the conventional Gnss HAL. This code is
+     * moved here from GnssLocationProvider.
+     */
+    if (mGnssDebugIface) {
+        char buffer[kMaxDebugStrLen + 1];
+        size_t length = mGnssDebugIface->get_internal_state(buffer, kMaxDebugStrLen);
+        length = std::max(length, kMaxDebugStrLen);
+        buffer[length] = '\0';
+        ALOGD("Gnss Debug Data: %s", buffer);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssDebug.h b/src/connectivity/gps/service/1.0/GnssDebug.h
new file mode 100644
index 0000000..9a17dde
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssDebug_H_
+#define android_hardware_gnss_V1_0_GnssDebug_H_
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct GnssDebug : public IGnssDebug {
+    GnssDebug(const GpsDebugInterface* gpsDebugIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+     * These declarations were generated from IGnssDebug.hal.
+     */
+    Return<void> getDebugData(getDebugData_cb _hidl_cb)  override;
+
+ private:
+    /*
+     * Constant added for backward compatibility to conventional GPS Hals which
+     * returned a debug string.
+     */
+    const size_t kMaxDebugStrLen = 2047;
+    const GpsDebugInterface* mGnssDebugIface = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssDebug_H_
diff --git a/src/connectivity/gps/service/1.0/GnssGeofencing.cpp b/src/connectivity/gps/service/1.0/GnssGeofencing.cpp
new file mode 100644
index 0000000..3d51140
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssGeofencing.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include "GnssGeofencing.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssGeofencing::sThreadFuncArgsList;
+sp<IGnssGeofenceCallback> GnssGeofencing::mGnssGeofencingCbIface = nullptr;
+bool GnssGeofencing::sInterfaceExists = false;
+
+GpsGeofenceCallbacks_ext GnssGeofencing::sGnssGfCb = {
+    .geofence_transition_callback = gnssGfTransitionCb,
+    .geofence_status_callback = gnssGfStatusCb,
+    .geofence_add_callback = gnssGfAddCb,
+    .geofence_remove_callback = gnssGfRemoveCb,
+    .geofence_pause_callback = gnssGfPauseCb,
+    .geofence_resume_callback = gnssGfResumeCb,
+    .create_thread_cb = createThreadCb
+};
+
+GnssGeofencing::GnssGeofencing(const GpsGeofencingInterface_ext* gpsGeofencingIface)
+    : mGnssGeofencingIface(gpsGeofencingIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+GnssGeofencing::~GnssGeofencing() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+void GnssGeofencing::gnssGfTransitionCb(int32_t geofenceId,
+                                        GpsLocation_ext* location,
+                                        int32_t transition,
+                                        GpsUtcTime timestamp) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s : Invalid location from GNSS HAL", __func__);
+        return;
+    }
+
+    GnssLocation gnssLocation = convertToGnssLocation(location);
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+            geofenceId,
+            gnssLocation,
+            static_cast<IGnssGeofenceCallback::GeofenceTransition>(transition),
+            timestamp);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfStatusCb(int32_t status, GpsLocation_ext* location) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    GnssLocation gnssLocation;
+
+    if (location != nullptr) {
+        gnssLocation = convertToGnssLocation(location);
+    } else {
+        gnssLocation = {};
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceStatusCb(
+            static_cast<IGnssGeofenceCallback::GeofenceAvailability>(status), gnssLocation);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfAddCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceAddCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfRemoveCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfPauseCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofencePauseCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfResumeCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceResumeCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+pthread_t GnssGeofencing::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback)  {
+    mGnssGeofencingCbIface = callback;
+
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->init(&sGnssGfCb);
+    }
+
+    return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+        int32_t geofenceId,
+        double latitudeDegrees,
+        double longitudeDegrees,
+        double radiusMeters,
+        IGnssGeofenceCallback::GeofenceTransition lastTransition,
+        int32_t monitorTransitions,
+        uint32_t notificationResponsivenessMs,
+        uint32_t unknownTimerMs)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+        return Void();
+    } else {
+        mGnssGeofencingIface->add_geofence_area(
+                geofenceId,
+                latitudeDegrees,
+                longitudeDegrees,
+                radiusMeters,
+                static_cast<int32_t>(lastTransition),
+                monitorTransitions,
+                notificationResponsivenessMs,
+                unknownTimerMs);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->pause_geofence(geofenceId);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->resume_geofence(geofenceId, monitorTransitions);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->remove_geofence_area(geofenceId);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssGeofencing.h b/src/connectivity/gps/service/1.0/GnssGeofencing.h
new file mode 100644
index 0000000..ef93163
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssGeofencing.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssGeofencing_H_
+#define android_hardware_gnss_V1_0_GnssGeofencing_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+#include "hardware/gps_mtk.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for GNSS Geofencing support. It also contains wrapper methods to allow
+ * methods from IGnssGeofenceCallback interface to be passed into the
+ * conventional implementation of the GNSS HAL.
+ */
+struct GnssGeofencing : public IGnssGeofencing {
+    GnssGeofencing(const GpsGeofencingInterface_ext* gpsGeofencingIface);
+    ~GnssGeofencing();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+     * These declarations were generated from IGnssGeofencing.hal.
+     */
+    Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback)  override;
+    Return<void> addGeofence(int32_t geofenceId,
+                             double latitudeDegrees,
+                             double longitudeDegrees,
+                             double radiusMeters,
+                             IGnssGeofenceCallback::GeofenceTransition lastTransition,
+                             int32_t monitorTransitions,
+                             uint32_t notificationResponsivenessMs,
+                             uint32_t unknownTimerMs)  override;
+
+    Return<void> pauseGeofence(int32_t geofenceId)  override;
+    Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  override;
+    Return<void> removeGeofence(int32_t geofenceId)  override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssGeofencing base class.
+     */
+    static void gnssGfTransitionCb(int32_t geofence_id, GpsLocation_ext* location,
+                                   int32_t transition, GpsUtcTime timestamp);
+    static void gnssGfStatusCb(int32_t status, GpsLocation_ext* last_location);
+    static void gnssGfAddCb(int32_t geofence_id, int32_t status);
+    static void gnssGfRemoveCb(int32_t geofence_id, int32_t status);
+    static void gnssGfPauseCb(int32_t geofence_id, int32_t status);
+    static void gnssGfResumeCb(int32_t geofence_id, int32_t status);
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsGeofenceCallbacks_ext sGnssGfCb;
+
+ private:
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static sp<IGnssGeofenceCallback> mGnssGeofencingCbIface;
+    const GpsGeofencingInterface_ext* mGnssGeofencingIface = nullptr;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssGeofencing_H_
diff --git a/src/connectivity/gps/service/1.0/GnssMeasurement.cpp b/src/connectivity/gps/service/1.0/GnssMeasurement.cpp
new file mode 100644
index 0000000..8b47086
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssMeasurement.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssMeasurementInterface"
+
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssMeasurementCallback> GnssMeasurement::sGnssMeasureCbIface = nullptr;
+GpsMeasurementCallbacks_ext GnssMeasurement::sGnssMeasurementCbs = {
+    .size = sizeof(GpsMeasurementCallbacks_ext),
+    .measurement_callback = gpsMeasurementCb,
+    .gnss_measurement_callback = gnssMeasurementCb
+};
+
+GnssMeasurement::GnssMeasurement(const GpsMeasurementInterface_ext* gpsMeasurementIface)
+    : mGnssMeasureIface(gpsMeasurementIface) {}
+
+void GnssMeasurement::gnssMeasurementCb(GnssData_ext* halGnssData) {
+    if (sGnssMeasureCbIface == nullptr) {
+        ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (halGnssData == nullptr) {
+        ALOGE("%s: Invalid GnssData from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssMeasurementCallback::GnssData gnssData;
+    gnssData.measurementCount = std::min(halGnssData->measurement_count,
+                                         static_cast<size_t>(GnssMax::SVS_COUNT));
+
+    for (size_t i = 0; i < gnssData.measurementCount; i++) {
+        auto entry = halGnssData->measurements[i];
+        auto state = static_cast<GnssMeasurementState>(entry.legacyMeasurement.state);
+        if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED) {
+          state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+        }
+        if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED) {
+          state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+        }
+        gnssData.measurements[i] = (V1_0::IGnssMeasurementCallback::GnssMeasurement){
+            .flags = entry.legacyMeasurement.flags,
+            .svid = entry.legacyMeasurement.svid,
+            .constellation = static_cast<V1_0::GnssConstellationType>(
+                    entry.legacyMeasurement.constellation),
+            .timeOffsetNs = entry.legacyMeasurement.time_offset_ns,
+            .state = state,
+            .receivedSvTimeInNs = entry.legacyMeasurement.received_sv_time_in_ns,
+            .receivedSvTimeUncertaintyInNs =
+                    entry.legacyMeasurement.received_sv_time_uncertainty_in_ns,
+            .cN0DbHz = entry.legacyMeasurement.c_n0_dbhz,
+            .pseudorangeRateMps = entry.legacyMeasurement.pseudorange_rate_mps,
+            .pseudorangeRateUncertaintyMps =
+                    entry.legacyMeasurement.pseudorange_rate_uncertainty_mps,
+            .accumulatedDeltaRangeState = entry.legacyMeasurement.accumulated_delta_range_state,
+            .accumulatedDeltaRangeM = entry.legacyMeasurement.accumulated_delta_range_m,
+            .accumulatedDeltaRangeUncertaintyM =
+                    entry.legacyMeasurement.accumulated_delta_range_uncertainty_m,
+            .carrierFrequencyHz = entry.legacyMeasurement.carrier_frequency_hz,
+            .carrierCycles = entry.legacyMeasurement.carrier_cycles,
+            .carrierPhase = entry.legacyMeasurement.carrier_phase,
+            .carrierPhaseUncertainty = entry.legacyMeasurement.carrier_phase_uncertainty,
+            .multipathIndicator = static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+                    entry.legacyMeasurement.multipath_indicator),
+            .snrDb = entry.legacyMeasurement.snr_db,
+            .agcLevelDb = entry.agc_level_db
+        };
+    }
+
+    auto clockVal = halGnssData->clock;
+    gnssData.clock = {
+        .gnssClockFlags = clockVal.flags,
+        .leapSecond = clockVal.leap_second,
+        .timeNs = clockVal.time_ns,
+        .timeUncertaintyNs = clockVal.time_uncertainty_ns,
+        .fullBiasNs = clockVal.full_bias_ns,
+        .biasNs = clockVal.bias_ns,
+        .biasUncertaintyNs = clockVal.bias_uncertainty_ns,
+        .driftNsps = clockVal.drift_nsps,
+        .driftUncertaintyNsps = clockVal.drift_uncertainty_nsps,
+        .hwClockDiscontinuityCount = clockVal.hw_clock_discontinuity_count
+    };
+
+    auto ret = sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+/*
+ * The code in the following method has been moved here from GnssLocationProvider.
+ * It converts GpsData to GnssData. This code is no longer required in
+ * GnssLocationProvider since GpsData is deprecated and no longer part of the
+ * GNSS interface.
+ */
+void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
+    if (sGnssMeasureCbIface == nullptr) {
+        ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (gpsData == nullptr) {
+        ALOGE("%s: Invalid GpsData from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssMeasurementCallback::GnssData gnssData;
+    gnssData.measurementCount = std::min(gpsData->measurement_count,
+                                         static_cast<size_t>(GnssMax::SVS_COUNT));
+
+
+    for (size_t i = 0; i < gnssData.measurementCount; i++) {
+        auto entry = gpsData->measurements[i];
+        gnssData.measurements[i].flags = entry.flags;
+        gnssData.measurements[i].svid = static_cast<int32_t>(entry.prn);
+        if (entry.prn >= 1 && entry.prn <= 32) {
+            gnssData.measurements[i].constellation = GnssConstellationType::GPS;
+        } else {
+            gnssData.measurements[i].constellation =
+                  GnssConstellationType::UNKNOWN;
+        }
+
+        gnssData.measurements[i].timeOffsetNs = entry.time_offset_ns;
+        gnssData.measurements[i].state = entry.state;
+        gnssData.measurements[i].receivedSvTimeInNs = entry.received_gps_tow_ns;
+        gnssData.measurements[i].receivedSvTimeUncertaintyInNs =
+            entry.received_gps_tow_uncertainty_ns;
+        gnssData.measurements[i].cN0DbHz = entry.c_n0_dbhz;
+        gnssData.measurements[i].pseudorangeRateMps = entry.pseudorange_rate_mps;
+        gnssData.measurements[i].pseudorangeRateUncertaintyMps =
+                entry.pseudorange_rate_uncertainty_mps;
+        gnssData.measurements[i].accumulatedDeltaRangeState =
+                entry.accumulated_delta_range_state;
+        gnssData.measurements[i].accumulatedDeltaRangeM =
+                entry.accumulated_delta_range_m;
+        gnssData.measurements[i].accumulatedDeltaRangeUncertaintyM =
+                entry.accumulated_delta_range_uncertainty_m;
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
+            gnssData.measurements[i].carrierFrequencyHz = entry.carrier_frequency_hz;
+        } else {
+            gnssData.measurements[i].carrierFrequencyHz = 0;
+        }
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE) {
+            gnssData.measurements[i].carrierPhase = entry.carrier_phase;
+        } else {
+            gnssData.measurements[i].carrierPhase = 0;
+        }
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
+            gnssData.measurements[i].carrierPhaseUncertainty = entry.carrier_phase_uncertainty;
+        } else {
+            gnssData.measurements[i].carrierPhaseUncertainty = 0;
+        }
+
+        gnssData.measurements[i].multipathIndicator =
+                static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+                        entry.multipath_indicator);
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_SNR) {
+            gnssData.measurements[i].snrDb = entry.snr_db;
+        } else {
+            gnssData.measurements[i].snrDb = 0;
+        }
+    }
+
+    auto clockVal = gpsData->clock;
+    static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
+
+    gnssData.clock.leapSecond = clockVal.leap_second;
+    /*
+     * GnssClock only supports the more effective HW_CLOCK type, so type
+     * handling and documentation complexity has been removed.  To convert the
+     * old GPS_CLOCK types (active only in a limited number of older devices),
+     * the GPS time information is handled as an always discontinuous HW clock,
+     * with the GPS time information put into the full_bias_ns instead - so that
+     * time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
+     * sign of full_bias_ns and bias_ns has flipped between GpsClock &
+     * GnssClock, so that is also handled below.
+     */
+    switch (clockVal.type) {
+        case GPS_CLOCK_TYPE_UNKNOWN:
+            // Clock type unsupported.
+            ALOGE("Unknown clock type provided.");
+            break;
+        case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
+            // Already local hardware time. No need to do anything.
+            break;
+        case GPS_CLOCK_TYPE_GPS_TIME:
+            // GPS time, need to convert.
+            clockVal.flags |= GPS_CLOCK_HAS_FULL_BIAS;
+            clockVal.full_bias_ns = clockVal.time_ns;
+            clockVal.time_ns = 0;
+            gnssData.clock.hwClockDiscontinuityCount =
+                    discontinuity_count_to_handle_old_clock_type++;
+            break;
+    }
+
+    gnssData.clock.timeNs = clockVal.time_ns;
+    gnssData.clock.timeUncertaintyNs = clockVal.time_uncertainty_ns;
+    /*
+     * Definition of sign for full_bias_ns & bias_ns has been changed since N,
+     * so flip signs here.
+     */
+    gnssData.clock.fullBiasNs = -(clockVal.full_bias_ns);
+    gnssData.clock.biasNs = -(clockVal.bias_ns);
+    gnssData.clock.biasUncertaintyNs = clockVal.bias_uncertainty_ns;
+    gnssData.clock.driftNsps = clockVal.drift_nsps;
+    gnssData.clock.driftUncertaintyNsps = clockVal.drift_uncertainty_nsps;
+    gnssData.clock.gnssClockFlags = clockVal.flags;
+
+    auto ret = sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+        const sp<IGnssMeasurementCallback>& callback)  {
+    if (mGnssMeasureIface == nullptr) {
+        ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+        return GnssMeasurementStatus::ERROR_GENERIC;
+    }
+    sGnssMeasureCbIface = callback;
+
+    return static_cast<GnssMeasurement::GnssMeasurementStatus>(
+            mGnssMeasureIface->init(&sGnssMeasurementCbs, false /*enableFullTracking*/));
+}
+
+Return<void> GnssMeasurement::close()  {
+    if (mGnssMeasureIface == nullptr) {
+        ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+    } else {
+        mGnssMeasureIface->close();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssMeasurement.h b/src/connectivity/gps/service/1.0/GnssMeasurement.h
new file mode 100644
index 0000000..219de89
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssMeasurement.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssMeasurement_H_
+#define android_hardware_gnss_V1_0_GnssMeasurement_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+#include <hardware/gps_mtk.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+
+/*
+ * Extended interface for GNSS Measurements support. Also contains wrapper methods to allow methods
+ * from IGnssMeasurementCallback interface to be passed into the conventional implementation of the
+ * GNSS HAL.
+ */
+struct GnssMeasurement : public IGnssMeasurement {
+    GnssMeasurement(const GpsMeasurementInterface_ext* gpsMeasurementIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+     * These declarations were generated from IGnssMeasurement.hal.
+     */
+    Return<GnssMeasurementStatus> setCallback(
+        const sp<IGnssMeasurementCallback>& callback) override;
+    Return<void> close() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssMeasurement base class.
+     */
+    static void gnssMeasurementCb(GnssData_ext* data);
+     /*
+      * Deprecated callback added for backward compatibity for devices that do
+      * not support GnssData measurements.
+      */
+    static void gpsMeasurementCb(GpsData* data);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsMeasurementCallbacks_ext sGnssMeasurementCbs;
+
+ private:
+    const GpsMeasurementInterface_ext* mGnssMeasureIface = nullptr;
+    static sp<IGnssMeasurementCallback> sGnssMeasureCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssMeasurement_H_
diff --git a/src/connectivity/gps/service/1.0/GnssNavigationMessage.cpp b/src/connectivity/gps/service/1.0/GnssNavigationMessage.cpp
new file mode 100644
index 0000000..6f509d0
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssNavigationMessage.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssNavigationMessageInterface"
+
+#include <log/log.h>
+
+#include "GnssNavigationMessage.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssNavigationMessageCallback> GnssNavigationMessage::sGnssNavigationMsgCbIface = nullptr;
+
+GpsNavigationMessageCallbacks GnssNavigationMessage::sGnssNavigationMessageCb = {
+    .size = sizeof(GpsNavigationMessageCallbacks),
+    .navigation_message_callback = nullptr,
+    .gnss_navigation_message_callback = gnssNavigationMessageCb
+};
+
+GnssNavigationMessage::GnssNavigationMessage(
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface) :
+    mGnssNavigationMessageIface(gpsNavigationMessageIface) {}
+
+void GnssNavigationMessage::gnssNavigationMessageCb(LegacyGnssNavigationMessage* message) {
+    if (sGnssNavigationMsgCbIface == nullptr) {
+        ALOGE("%s: GnssNavigation Message Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (message == nullptr) {
+        ALOGE("%s, received invalid GnssNavigationMessage from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssNavigationMessageCallback::GnssNavigationMessage navigationMsg;
+
+    navigationMsg.svid = message->svid;
+    navigationMsg.type =
+            static_cast<IGnssNavigationMessageCallback::GnssNavigationMessageType>(message->type);
+    navigationMsg.status = message->status;
+    navigationMsg.messageId = message->message_id;
+    navigationMsg.submessageId = message->submessage_id;
+    navigationMsg.data.setToExternal(message->data, message->data_length);
+
+    auto ret = sGnssNavigationMsgCbIface->gnssNavigationMessageCb(navigationMsg);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+Return<GnssNavigationMessage::GnssNavigationMessageStatus> GnssNavigationMessage::setCallback(
+        const sp<IGnssNavigationMessageCallback>& callback)  {
+    if (mGnssNavigationMessageIface == nullptr) {
+        ALOGE("%s: GnssNavigationMessage not available", __func__);
+        return GnssNavigationMessageStatus::ERROR_GENERIC;
+    }
+
+    sGnssNavigationMsgCbIface = callback;
+
+    return static_cast<GnssNavigationMessage::GnssNavigationMessageStatus>(
+            mGnssNavigationMessageIface->init(&sGnssNavigationMessageCb));
+}
+
+Return<void> GnssNavigationMessage::close()  {
+    if (mGnssNavigationMessageIface == nullptr) {
+        ALOGE("%s: GnssNavigationMessage not available", __func__);
+    } else {
+        mGnssNavigationMessageIface->close();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssNavigationMessage.h b/src/connectivity/gps/service/1.0/GnssNavigationMessage.h
new file mode 100644
index 0000000..882854b
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssNavigationMessage.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+#define android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+
+#include <android/hardware/gnss/1.0/IGnssNavigationMessage.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssNavigationMessage = ::GnssNavigationMessage;
+
+/*
+ * Extended interface for GNSS navigation message reporting support. Also contains wrapper methods
+ * to allow methods from IGnssNavigationMessageCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct GnssNavigationMessage : public IGnssNavigationMessage {
+    GnssNavigationMessage(const GpsNavigationMessageInterface* gpsNavigationMessageIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+     * These declarations were generated from IGnssNavigationMessage.hal.
+     */
+    Return<GnssNavigationMessageStatus> setCallback(
+        const sp<IGnssNavigationMessageCallback>& callback) override;
+    Return<void> close() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+     * These methods are not part of the IGnssNavigationMessage base class.
+     */
+    static void gnssNavigationMessageCb(LegacyGnssNavigationMessage* message);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsNavigationMessageCallbacks sGnssNavigationMessageCb;
+ private:
+    const GpsNavigationMessageInterface* mGnssNavigationMessageIface = nullptr;
+    static sp<IGnssNavigationMessageCallback> sGnssNavigationMsgCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssNavigationMessage_H_
diff --git a/src/connectivity/gps/service/1.0/GnssNi.cpp b/src/connectivity/gps/service/1.0/GnssNi.cpp
new file mode 100644
index 0000000..d17891d
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssNi.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssNiInterface"
+
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssNi::sThreadFuncArgsList;
+sp<IGnssNiCallback> GnssNi::sGnssNiCbIface = nullptr;
+bool GnssNi::sInterfaceExists = false;
+
+GpsNiCallbacks GnssNi::sGnssNiCb = {
+    .notify_cb = niNotifyCb,
+    .create_thread_cb = createThreadCb
+};
+
+GnssNi::GnssNi(const GpsNiInterface* gpsNiIface) : mGnssNiIface(gpsNiIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+GnssNi::~GnssNi() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+pthread_t GnssNi::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void GnssNi::niNotifyCb(GpsNiNotification* notification) {
+    if (sGnssNiCbIface == nullptr) {
+        ALOGE("%s: GNSS NI Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (notification == nullptr) {
+        ALOGE("%s: Invalid GpsNotification callback from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssNiCallback::GnssNiNotification notificationGnss = {
+        .notificationId =  notification->notification_id,
+        .niType = static_cast<IGnssNiCallback::GnssNiType>(notification->ni_type),
+        .notifyFlags = notification->notify_flags,
+        .timeoutSec = static_cast<uint32_t>(notification->timeout),
+        .defaultResponse =
+                static_cast<IGnssNiCallback::GnssUserResponseType>(notification->default_response),
+        .requestorId = notification->requestor_id,
+        .notificationMessage = notification->text,
+        .requestorIdEncoding =
+                static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->requestor_id_encoding),
+        .notificationIdEncoding =
+                static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->text_encoding)
+    };
+
+    auto ret = sGnssNiCbIface->niNotifyCb(notificationGnss);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback)  {
+    if (mGnssNiIface == nullptr) {
+       ALOGE("%s: GnssNi interface is unavailable", __func__);
+       return Void();
+    }
+
+    sGnssNiCbIface = callback;
+
+    mGnssNiIface->init(&sGnssNiCb);
+    return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse)  {
+    if (mGnssNiIface == nullptr) {
+        ALOGE("%s: GnssNi interface is unavailable", __func__);
+    } else {
+        mGnssNiIface->respond(notifId, static_cast<GpsUserResponseType>(userResponse));
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssNi.h b/src/connectivity/gps/service/1.0/GnssNi.h
new file mode 100644
index 0000000..fe850b1
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssNi.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssNi_H_
+#define android_hardware_gnss_V1_0_GnssNi_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for Network-initiated (NI) support. This interface is used to respond to
+ * NI notifications originating from the HAL. Also contains wrapper methods to allow methods from
+ * IGnssNiCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct GnssNi : public IGnssNi {
+    GnssNi(const GpsNiInterface* gpsNiIface);
+    ~GnssNi();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+     * These declarations were generated from IGnssNi.hal.
+     */
+    Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+    Return<void> respond(int32_t notifId,
+                         IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssNi base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void niNotifyCb(GpsNiNotification* notification);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsNiCallbacks sGnssNiCb;
+
+ private:
+    const GpsNiInterface* mGnssNiIface = nullptr;
+    static sp<IGnssNiCallback> sGnssNiCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssNi_H_
diff --git a/src/connectivity/gps/service/1.0/GnssUtils.cpp b/src/connectivity/gps/service/1.0/GnssUtils.cpp
new file mode 100644
index 0000000..0234aa3
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssUtils.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GnssUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using android::hardware::gnss::V1_0::GnssLocation;
+
+GnssLocation convertToGnssLocation(GpsLocation_ext* location) {
+    GnssLocation gnssLocation = {};
+    if (location != nullptr) {
+        gnssLocation = {
+            .gnssLocationFlags = static_cast<uint16_t>(location->legacyLocation.flags & 0xff),
+            .latitudeDegrees = location->legacyLocation.latitude,
+            .longitudeDegrees = location->legacyLocation.longitude,
+            .altitudeMeters = location->legacyLocation.altitude,
+            .speedMetersPerSec = location->legacyLocation.speed,
+            .bearingDegrees = location->legacyLocation.bearing,
+            .horizontalAccuracyMeters = location->horizontalAccuracyMeters,
+            .verticalAccuracyMeters = location->verticalAccuracyMeters,
+            .speedAccuracyMetersPerSecond = location->speedAccuracyMetersPerSecond,
+            .bearingAccuracyDegrees = location->bearingAccuracyDegrees,
+            .timestamp = location->legacyLocation.timestamp
+        };
+    }
+
+    return gnssLocation;
+}
+
+GnssLocation convertToGnssLocation(FlpLocation* flpLocation) {
+    GnssLocation gnssLocation = {};
+    if (flpLocation != nullptr) {
+        gnssLocation = {.gnssLocationFlags = 0,  // clear here and set below
+                        .latitudeDegrees = flpLocation->latitude,
+                        .longitudeDegrees = flpLocation->longitude,
+                        .altitudeMeters = flpLocation->altitude,
+                        .speedMetersPerSec = flpLocation->speed,
+                        .bearingDegrees = flpLocation->bearing,
+                        .horizontalAccuracyMeters = flpLocation->accuracy,
+                        .verticalAccuracyMeters = 0,
+                        .speedAccuracyMetersPerSecond = 0,
+                        .bearingAccuracyDegrees = 0,
+                        .timestamp = flpLocation->timestamp};
+        // FlpLocation flags different from GnssLocation flags
+        if (flpLocation->flags & FLP_LOCATION_HAS_LAT_LONG) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_LAT_LONG;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_ALTITUDE) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_ALTITUDE;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_SPEED) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_SPEED;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_BEARING) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_BEARING;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_ACCURACY) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+        }
+    }
+
+    return gnssLocation;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssUtils.h b/src/connectivity/gps/service/1.0/GnssUtils.h
new file mode 100644
index 0000000..7cfef2e
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssUtils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef android_hardware_gnss_V1_0_GnssUtil_H_
+#define android_hardware_gnss_V1_0_GnssUtil_H_
+
+#include <hardware/fused_location.h>
+#include <hardware/gps.h>
+#include <hardware/gps_mtk.h>
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+/*
+ * This method converts a GpsLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(GpsLocation_ext* location);
+
+/*
+ * This method converts an FlpLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(FlpLocation* location);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif
diff --git a/src/connectivity/gps/service/1.0/GnssXtra.cpp b/src/connectivity/gps/service/1.0/GnssXtra.cpp
new file mode 100644
index 0000000..d124ce1
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssXtra.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssXtraInterface"
+
+#include "GnssXtra.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssXtra::sThreadFuncArgsList;
+sp<IGnssXtraCallback> GnssXtra::sGnssXtraCbIface = nullptr;
+bool GnssXtra::sInterfaceExists = false;
+
+GpsXtraCallbacks GnssXtra::sGnssXtraCb = {
+    .download_request_cb = gnssXtraDownloadRequestCb,
+    .create_thread_cb = createThreadCb,
+};
+
+GnssXtra::~GnssXtra() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+pthread_t GnssXtra::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+GnssXtra::GnssXtra(const GpsXtraInterface* xtraIface) : mGnssXtraIface(xtraIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+void GnssXtra::gnssXtraDownloadRequestCb() {
+    if (sGnssXtraCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = sGnssXtraCbIface->downloadRequestCb();
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+Return<bool> GnssXtra::setCallback(const sp<IGnssXtraCallback>& callback)  {
+    if (mGnssXtraIface == nullptr) {
+        ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+        return false;
+    }
+
+    sGnssXtraCbIface = callback;
+
+    return (mGnssXtraIface->init(&sGnssXtraCb) == 0);
+}
+
+Return<bool> GnssXtra::injectXtraData(const hidl_string& xtraData)  {
+    if (mGnssXtraIface == nullptr) {
+        ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+        return false;
+    }
+
+    char* buf = new char[xtraData.size()];
+    const char* data = xtraData.c_str();
+
+    memcpy(buf, data, xtraData.size());
+
+    int ret = mGnssXtraIface->inject_xtra_data(buf, xtraData.size());
+    delete[] buf;
+    return (ret == 0);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.0/GnssXtra.h b/src/connectivity/gps/service/1.0/GnssXtra.h
new file mode 100644
index 0000000..7a0733a
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/GnssXtra.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssXtra_H_
+#define android_hardware_gnss_V1_0_GnssXtra_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssXtra.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssXtra;
+using ::android::hardware::gnss::V1_0::IGnssXtraCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * This interface is used by the GNSS HAL to request the framework to download XTRA data.
+ * Also contains wrapper methods to allow methods from IGnssXtraCallback interface to be passed
+ * into the conventional implementation of the GNSS HAL.
+ */
+struct GnssXtra : public IGnssXtra {
+    GnssXtra(const GpsXtraInterface* xtraIface);
+    ~GnssXtra();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+     * These declarations were generated from IGnssXtra.hal.
+     */
+    Return<bool> setCallback(const sp<IGnssXtraCallback>& callback) override;
+    Return<bool> injectXtraData(const hidl_string& xtraData) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+     * These methods are not part of the IGnssXtra base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssXtraDownloadRequestCb();
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsXtraCallbacks sGnssXtraCb;
+
+ private:
+    const GpsXtraInterface* mGnssXtraIface = nullptr;
+    static sp<IGnssXtraCallback> sGnssXtraCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssXtra_H_
diff --git a/src/connectivity/gps/service/1.0/NOTICE b/src/connectivity/gps/service/1.0/NOTICE
new file mode 100644
index 0000000..bf532e5
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/NOTICE
@@ -0,0 +1,182 @@
+
+Copyright (C) 2016 The Android Open Source Project
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
diff --git a/src/connectivity/gps/service/1.0/OWNERS b/src/connectivity/gps/service/1.0/OWNERS
new file mode 100644
index 0000000..6c25bd7
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/OWNERS
@@ -0,0 +1,3 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
diff --git a/src/connectivity/gps/service/1.0/ThreadCreationWrapper.cpp b/src/connectivity/gps/service/1.0/ThreadCreationWrapper.cpp
new file mode 100644
index 0000000..2a5638f
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/ThreadCreationWrapper.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ThreadCreationWrapper.h>
+
+void* threadFunc(void* arg) {
+    ThreadFuncArgs* threadArgs = reinterpret_cast<ThreadFuncArgs*>(arg);
+    threadArgs->fptr(threadArgs->args);
+    return nullptr;
+}
+
+pthread_t createPthread(const char* name,
+                        void (*start)(void*),
+                        void* arg, std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs) {
+    pthread_t threadId;
+    auto threadArgs = new ThreadFuncArgs(start, arg);
+    auto argPtr = std::unique_ptr<ThreadFuncArgs>(threadArgs);
+
+    listArgs->push_back(std::move(argPtr));
+
+    int ret = pthread_create(&threadId, nullptr, threadFunc, reinterpret_cast<void*>(
+            threadArgs));
+    if (ret != 0) {
+        ALOGE("pthread creation unsuccessful");
+    } else {
+        pthread_setname_np(threadId, name);
+    }
+    return threadId;
+}
diff --git a/src/connectivity/gps/service/1.0/ThreadCreationWrapper.h b/src/connectivity/gps/service/1.0/ThreadCreationWrapper.h
new file mode 100644
index 0000000..99c8670
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/ThreadCreationWrapper.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+#define ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+
+#include <pthread.h>
+#include <vector>
+#include <log/log.h>
+
+typedef void (*threadEntryFunc)(void* ret);
+
+/*
+ * This class facilitates createThreadCb methods in various GNSS interfaces to wrap
+ * pthread_create() from libc since its function signature differs from what is required by the
+ * conventional GNSS HAL. The arguments passed to pthread_create() need to be on heap and not on
+ * the stack of createThreadCb.
+ */
+struct ThreadFuncArgs {
+    ThreadFuncArgs(void (*start)(void*), void* arg) : fptr(start), args(arg) {}
+
+    /* pointer to the function of type void()(void*) that needs to be wrapped */
+    threadEntryFunc fptr;
+    /* argument for fptr to be called with */
+    void* args;
+};
+
+/*
+ * This method is simply a wrapper. It is required since pthread_create() requires an entry
+ * function pointer of type void*()(void*) and the GNSS hal requires as input a function pointer of
+ * type void()(void*).
+ */
+void* threadFunc(void* arg);
+
+/*
+ * This method is called by createThreadCb with a pointer to the vector that
+ * holds the pointers to the thread arguments. The arg and start parameters are
+ * first used to create a ThreadFuncArgs object which is then saved in the
+ * listArgs parameters. The created ThreadFuncArgs object is then used to invoke
+ * threadFunc() method which in-turn invokes pthread_create.
+ */
+pthread_t createPthread(const char* name, void (*start)(void*), void* arg,
+                        std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs);
+
+#endif
diff --git a/src/connectivity/gps/service/1.0/android.hardware.gnss@1.0-service-mediatek.rc b/src/connectivity/gps/service/1.0/android.hardware.gnss@1.0-service-mediatek.rc
new file mode 100644
index 0000000..9f05c56
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/android.hardware.gnss@1.0-service-mediatek.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service-mediatek
+    class hal
+    user system
+    group system gps
diff --git a/src/connectivity/gps/service/1.0/hardware/gps_mtk.h b/src/connectivity/gps/service/1.0/hardware/gps_mtk.h
new file mode 100644
index 0000000..b32199e
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/hardware/gps_mtk.h
@@ -0,0 +1,682 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+
+#include <hardware/gps_internal.h>
+
+__BEGIN_DECLS
+
+// MTK extended GpsAidingData values.
+#define GPS_DELETE_HOT_STILL 0x2000
+#define GPS_DELETE_EPO      0x4000
+
+// ====================vzw debug screen API =================
+/**
+ * Name for the VZW debug interface.
+ */
+#define VZW_DEBUG_INTERFACE      "vzw-debug"
+
+#define VZW_DEBUG_STRING_MAXLEN      200
+
+/** Represents data of VzwDebugData. */
+typedef struct {
+    /** set to sizeof(VzwDebugData) */
+    size_t size;
+
+    char  vzw_msg_data[VZW_DEBUG_STRING_MAXLEN];
+} VzwDebugData;
+
+
+typedef void (* vzw_debug_callback)(VzwDebugData* vzw_message);
+
+/** Callback structure for the Vzw debug interface. */
+typedef struct {
+    vzw_debug_callback vzw_debug_cb;
+} VzwDebugCallbacks;
+
+
+/** Extended interface for VZW DEBUG support. */
+typedef struct {
+    /** set to sizeof(VzwDebugInterface) */
+    size_t          size;
+
+    /** Registers the callbacks for Vzw debug message. */
+    int  (*init)( VzwDebugCallbacks* callbacks );
+
+    /** Set Vzw debug screen enable/disable **/
+    void (*set_vzw_debug_screen)(bool enabled);
+} VzwDebugInterface;
+
+////////////////////// GNSS HIDL v1.0 ////////////////////////////
+
+/** Represents a location. */
+typedef struct {
+    GpsLocation legacyLocation;
+    /**
+    * Represents expected horizontal position accuracy, radial, in meters
+    * (68% confidence).
+    */
+    float           horizontalAccuracyMeters;
+
+    /**
+    * Represents expected vertical position accuracy in meters
+    * (68% confidence).
+    */
+    float           verticalAccuracyMeters;
+
+    /**
+    * Represents expected speed accuracy in meter per seconds
+    * (68% confidence).
+    */
+    float           speedAccuracyMetersPerSecond;
+
+    /**
+    * Represents expected bearing accuracy in degrees
+    * (68% confidence).
+    */
+    float           bearingAccuracyDegrees;
+
+} GpsLocation_ext;
+
+
+typedef struct {
+    GnssSvInfo legacySvInfo;
+
+    /// v1.0 ///
+    float carrier_frequency;
+
+} GnssSvInfo_ext;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo_ext gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus_ext;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_ext_callback)(GpsLocation_ext* location);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_ext_callback)(GnssSvStatus_ext* sv_info);
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_ext_callback) (int32_t geofence_id,
+        GpsLocation_ext* location, int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_ext_callback) (int32_t status,
+        GpsLocation_ext* last_location);
+
+typedef struct {
+    gps_geofence_transition_ext_callback geofence_transition_callback;
+    gps_geofence_status_ext_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks_ext;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks_ext* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface_ext;
+
+typedef struct {
+    GnssMeasurement legacyMeasurement;
+
+    /**
+     * Automatic gain control (AGC) level. AGC acts as a variable gain
+     * amplifier adjusting the power of the incoming signal. The AGC level
+     * may be used to indicate potential interference. When AGC is at a
+     * nominal level, this value must be set as 0. Higher gain (and/or lower
+     * input power) must be output as a positive number. Hence in cases of
+     * strong jamming, in the band of this signal, this value must go more
+     * negative.
+     *
+     * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+     * other RF HW components) may also affect the typical output of of this
+     * value on any given hardware design in an open sky test - the
+     * important aspect of this output is that changes in this value are
+     * indicative of changes on input signal power in the frequency band for
+     * this measurement.
+     */
+    double agc_level_db;
+} GnssMeasurement_ext;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement_ext measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData_ext;
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_ext_callback) (GnssData_ext* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_ext_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks_ext;
+
+
+/////// Gnss debug ////
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+typedef enum {
+    /** Ephemeris is known for this satellite. */
+    EPHEMERIS,
+    /**
+     * Ephemeris is not known, but Almanac (approximate location) is known.
+     */
+    ALMANAC_ONLY,
+    /**
+     * Both ephemeris & almanac are not known (e.g. during a cold start
+     * blind search.)
+     */
+    NOT_AVAILABLE
+} SatelliteEphemerisType;
+
+typedef enum {
+    /**
+     * The ephemeris (or almanac only) information was demodulated from the
+     * signal received on the device
+     */
+    DEMODULATED,
+    /**
+     * The ephemeris (or almanac only) information was received from a SUPL
+     * server.
+     */
+    SUPL_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * server.
+     */
+    OTHER_SERVER_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * method, e.g. injected via a local debug tool, from build defaults
+     * (e.g. almanac), or is from a satellite
+     * with SatelliteEphemerisType::NOT_AVAILABLE.
+     */
+    OTHER
+} SatelliteEphemerisSource;
+
+typedef enum {
+    /** The ephemeris is known good. */
+    GOOD,
+    /** The ephemeris is known bad. */
+    BAD,
+    /** The ephemeris is unknown to be good or bad. */
+    UNKNOWN
+} SatelliteEphemerisHealth;
+
+/**
+ * Provides the current best known position from any
+ * source (GNSS or injected assistance).
+ */
+typedef struct {
+    /**
+     * Validity of the data in this struct. False only if no
+     * latitude/longitude information is known.
+     */
+    bool valid;
+    /** Latitude expressed in degrees */
+    double latitudeDegrees;
+    /** Longitude expressed in degrees */
+    double longitudeDegrees;
+    /** Altitude above ellipsoid expressed in meters */
+    float altitudeMeters;
+    /** Represents horizontal speed in meters per second. */
+    float speedMetersPerSec;
+    /** Represents heading in degrees. */
+    float bearingDegrees;
+    /**
+     * Estimated horizontal accuracy of position expressed in meters,
+     * radial, 68% confidence.
+     */
+    double horizontalAccuracyMeters;
+    /**
+     * Estimated vertical accuracy of position expressed in meters, with
+     * 68% confidence.
+     */
+    double verticalAccuracyMeters;
+    /**
+     * Estimated speed accuracy in meters per second with 68% confidence.
+     */
+    double speedAccuracyMetersPerSecond;
+    /**
+     * estimated bearing accuracy degrees with 68% confidence.
+     */
+    double bearingAccuracyDegrees;
+    /**
+     * Time duration before this report that this position information was
+     * valid.  This can, for example, be a previous injected location with
+     * an age potentially thousands of seconds old, or
+     * extrapolated to the current time (with appropriately increased
+     * accuracy estimates), with a (near) zero age.
+     */
+    float ageSeconds;
+} PositionDebug;
+
+/**
+ * Provides the current best known UTC time estimate.
+ * If no fresh information is available, e.g. after a delete all,
+ * then whatever the effective defaults are on the device must be
+ * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+ * in the specified units.
+ */
+typedef struct {
+    /** UTC time estimate. */
+    GnssUtcTime timeEstimate;
+    /** 68% error estimate in time. */
+    float timeUncertaintyNs;
+    /**
+     * 68% error estimate in local clock drift,
+     * in nanoseconds per second (also known as parts per billion - ppb.)
+     */
+    float frequencyUncertaintyNsPerSec;
+} TimeDebug;
+
+/**
+ * Provides a single satellite info that has decoded navigation data.
+ */
+typedef struct {
+    /** Satellite vehicle ID number */
+    int16_t svid;
+    /** Defines the constellation type of the given SV. */
+    GnssConstellationType constellation;
+
+    /**
+     * Defines the standard broadcast ephemeris or almanac availability for
+     * the satellite.  To report status of predicted orbit and clock
+     * information, see the serverPrediction fields below.
+     */
+    SatelliteEphemerisType ephemerisType;
+    /** Defines the ephemeris source of the satellite. */
+    SatelliteEphemerisSource ephemerisSource;
+    /**
+     * Defines whether the satellite is known healthy
+     * (safe for use in location calculation.)
+     */
+    SatelliteEphemerisHealth ephemerisHealth;
+    /**
+     * Time duration from this report (current time), minus the
+     * effective time of the ephemeris source (e.g. TOE, TOA.)
+     * Set to 0 when ephemerisType is NOT_AVAILABLE.
+     */
+    float ephemerisAgeSeconds;
+
+    /**
+     * True if a server has provided a predicted orbit and clock model for
+     * this satellite.
+     */
+    bool serverPredictionIsAvailable;
+    /**
+     * Time duration from this report (current time) minus the time of the
+     * start of the server predicted information.  For example, a 1 day
+     * old prediction would be reported as 86400 seconds here.
+     */
+    float serverPredictionAgeSeconds;
+} SatelliteData;
+
+/**
+ * Provides a set of debug information that is filled by the GNSS chipset
+ * when the method getDebugData() is invoked.
+ */
+typedef struct {
+    /** Current best known position. */
+    PositionDebug position;
+    /** Current best know time estimate */
+    TimeDebug time;
+    /**
+     * Provides a list of the available satellite data, for all
+     * satellites and constellations the device can track,
+     * including GnssConstellationType UNKNOWN.
+     */
+    SatelliteData satelliteDataArray[GNSS_MAX_SVS];
+} DebugData;
+
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    // size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+    /// v1.0 ///
+    bool (*get_internal_state)(DebugData* debugData);
+} GpsDebugInterface_ext;
+
+
+////////////////////// GNSS HIDL v1.1 ////////////////////////////
+
+/**
+ * Callback for reporting driver name information.
+ */
+typedef void (* gnss_set_name_callback)(const char* name, int length);
+
+/**
+ * Callback for requesting framework NLP or Fused location injection.
+ */
+typedef void (* gnss_request_location_callback)(bool independentFromGnss);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_ext_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_ext_callback gnss_sv_status_cb;
+
+    /////v1.1////
+    gnss_set_name_callback set_name_cb;
+    gnss_request_location_callback request_location_cb;
+} GpsCallbacks_ext;
+
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    /// v1.0 ///
+//    int   (*init)( GpsCallbacks* callbacks );
+    /// v1.1 ///
+    int   (*init)( GpsCallbacks_ext* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+     /// v1.0 ///
+//    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+//            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+    /// v1.1 ///
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time,
+            bool lowPowerMode);
+
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+
+    /// v1.1 ///
+    int  (*inject_fused_location)(double latitude, double longitude, float accuracy);
+
+} GpsInterface_ext;
+
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface_ext) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    /// v1.0 ///
+//    int (*init) (GpsMeasurementCallbacks* callbacks);
+    /// v1.1 ///
+    int (*init) (GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface_ext;
+
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+
+   //// v1.1 ////
+   void (*setBlacklist) (long long* blacklist, int32_t size);
+} GnssConfigurationInterface_ext;
+
+struct gps_device_t_ext {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_MTK_H */
+
diff --git a/src/connectivity/gps/service/1.0/service.cpp b/src/connectivity/gps/service/1.0/service.cpp
new file mode 100644
index 0000000..0704e7f
--- /dev/null
+++ b/src/connectivity/gps/service/1.0/service.cpp
@@ -0,0 +1,17 @@
+#define LOG_TAG "android.hardware.gnss@1.0-service"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hidl/LegacySupport.h>
+
+#include <binder/ProcessState.h>
+
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    // The GNSS HAL may communicate to other vendor components via
+    // /dev/vndbinder
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    return defaultPassthroughServiceImplementation<IGnss>();
+}
diff --git a/src/connectivity/gps/service/1.1/AGnss.cpp b/src/connectivity/gps/service/1.1/AGnss.cpp
new file mode 100644
index 0000000..29c6ddd
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/AGnss.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_AGnssInterface"
+
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
+sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
+bool AGnss::sInterfaceExists = false;
+
+AGpsCallbacks AGnss::sAGnssCb = {
+    .status_cb = statusCb,
+    .create_thread_cb = createThreadCb
+};
+
+AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+AGnss::~AGnss() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+void AGnss::statusCb(AGpsStatus* status) {
+    if (sAGnssCbIface == nullptr) {
+        ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("AGNSS status is invalid");
+        return;
+    }
+
+    /*
+     * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
+     * AGpsStatus is checked for backward compatibility since some devices may
+     * be sending out an older version of AGpsStatus that only supports IPv4.
+     */
+    size_t statusSize = status->size;
+    if (status->size == sizeof(AGpsStatus)) {
+        switch (status->addr.ss_family)
+        {
+            case AF_INET:
+                {
+                    /*
+                     * ss_family indicates IPv4.
+                     */
+                    struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
+                    IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+                        .type = static_cast<IAGnssCallback::AGnssType>(status->type),
+                        .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+                        .ipV4Addr = in->sin_addr.s_addr,
+                    };
+
+                    /*
+                     * Callback to client with agnssStatusIpV4Cb.
+                     */
+                    auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+                    if (!ret.isOk()) {
+                        ALOGE("%s: Unable to invoke callback", __func__);
+                    }
+                    break;
+                }
+            case AF_INET6:
+                {
+                    /*
+                     * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
+                     */
+                    IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
+
+                    aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
+                    aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
+                            status->status);
+
+                    struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
+                            &(status->addr));
+                    memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
+                           aGnssStatusIpV6.ipV6Addr.size());
+                    auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
+                    if (!ret.isOk()) {
+                        ALOGE("%s: Unable to invoke callback", __func__);
+                    }
+                    break;
+                }
+             default:
+                    ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
+        }
+    } else if (statusSize >= sizeof(AGpsStatus_v2)) {
+        AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
+        uint32_t ipV4Addr = statusV2->ipaddr;
+        IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+            .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
+            .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+            /*
+             * For older versions of AGpsStatus, change IP addr to net order. This
+             * was earlier being done in GnssLocationProvider.
+             */
+            .ipV4Addr = htonl(ipV4Addr)
+        };
+        /*
+         * Callback to client with agnssStatusIpV4Cb.
+         */
+        auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+        }
+    } else {
+        ALOGE("%s: Invalid size for AGPS Status", __func__);
+    }
+}
+
+pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+/*
+ * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
+ */
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return Void();
+    }
+
+    sAGnssCbIface = callback;
+
+    mAGnssIface->init(&sAGnssCb);
+    return Void();
+}
+
+Return<bool> AGnss::dataConnClosed()  {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_closed() == 0);
+}
+
+Return<bool> AGnss::dataConnFailed()  {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_failed() == 0);
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+                              const hidl_string& hostname,
+                              int32_t port) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
+                                                     static_cast<uint16_t>(apnIpType)) == 0);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/AGnss.h b/src/connectivity/gps/service/1.1/AGnss.h
new file mode 100644
index 0000000..2a8eed0
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/AGnss.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_AGnss_H_
+#define android_hardware_gnss_V1_0_AGnss_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hardware/gps_internal.h>
+#include <hidl/Status.h>
+#include <netinet/in.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for AGNSS support. Also contains wrapper methods to allow
+ * methods from IAGnssCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct AGnss : public IAGnss {
+    AGnss(const AGpsInterface* agpsIface);
+    ~AGnss();
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+     * These declarations were generated from IAGnss.hal.
+     */
+    Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+    Return<bool> dataConnClosed() override;
+    Return<bool> dataConnFailed() override;
+    Return<bool> setServer(IAGnssCallback::AGnssType type,
+                         const hidl_string& hostname, int32_t port) override;
+    Return<bool> dataConnOpen(const hidl_string& apn,
+                                           IAGnss::ApnIpType apnIpType) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IAGnss base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void statusCb(AGpsStatus* status);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static AGpsCallbacks sAGnssCb;
+
+ private:
+    const AGpsInterface* mAGnssIface = nullptr;
+    static sp<IAGnssCallback> sAGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_AGnss_H_
diff --git a/src/connectivity/gps/service/1.1/AGnssRil.cpp b/src/connectivity/gps/service/1.1/AGnssRil.cpp
new file mode 100644
index 0000000..1458327
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/AGnssRil.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_AGnssRilInterface"
+
+#include "AGnssRil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnssRil::sThreadFuncArgsList;
+sp<IAGnssRilCallback> AGnssRil::sAGnssRilCbIface = nullptr;
+bool AGnssRil::sInterfaceExists = false;
+
+AGpsRilCallbacks AGnssRil::sAGnssRilCb = {
+    .request_setid = AGnssRil::requestSetId,
+    .request_refloc = AGnssRil::requestRefLoc,
+    .create_thread_cb = AGnssRil::createThreadCb
+};
+
+AGnssRil::AGnssRil(const AGpsRilInterface* aGpsRilIface) : mAGnssRilIface(aGpsRilIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+AGnssRil::~AGnssRil() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+void AGnssRil::requestSetId(uint32_t flags) {
+    if (sAGnssRilCbIface == nullptr) {
+        ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = sAGnssRilCbIface->requestSetIdCb(flags);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void AGnssRil::requestRefLoc(uint32_t /*flags*/) {
+    if (sAGnssRilCbIface == nullptr) {
+        ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = sAGnssRilCbIface->requestRefLocCb();
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+pthread_t AGnssRil::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+Return<void> AGnssRil::setCallback(const sp<IAGnssRilCallback>& callback)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return Void();
+    }
+
+    sAGnssRilCbIface = callback;
+
+    mAGnssRilIface->init(&sAGnssRilCb);
+    return Void();
+}
+
+Return<void> AGnssRil::setRefLocation(const IAGnssRil::AGnssRefLocation& aGnssRefLocation)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return Void();
+    }
+
+    AGpsRefLocation aGnssRefloc;
+    aGnssRefloc.type = static_cast<uint16_t>(aGnssRefLocation.type);
+
+    auto& cellID = aGnssRefLocation.cellID;
+    aGnssRefloc.u.cellID = {
+        .type = static_cast<uint16_t>(cellID.type),
+        .mcc = cellID.mcc,
+        .mnc = cellID.mnc,
+        .lac = cellID.lac,
+        .cid = cellID.cid,
+        .tac = cellID.tac,
+        .pcid = cellID.pcid
+    };
+
+    mAGnssRilIface->set_ref_location(&aGnssRefloc, sizeof(aGnssRefloc));
+    return Void();
+}
+
+Return<bool> AGnssRil::setSetId(IAGnssRil::SetIDType type, const hidl_string& setid)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->set_set_id(static_cast<uint16_t>(type), setid.c_str());
+    return true;
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected,
+                                          IAGnssRil::NetworkType type,
+                                          bool roaming) {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->update_network_state(connected,
+                                         static_cast<int>(type),
+                                         roaming,
+                                         nullptr /* extra_info */);
+    return true;
+}
+
+Return<bool> AGnssRil::updateNetworkAvailability(bool available, const hidl_string& apn)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->update_network_availability(available, apn.c_str());
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/AGnssRil.h b/src/connectivity/gps/service/1.1/AGnssRil.h
new file mode 100644
index 0000000..6215a9e
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/AGnssRil.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_AGnssRil_H_
+#define android_hardware_gnss_V1_0_AGnssRil_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+    AGnssRil(const AGpsRilInterface* aGpsRilIface);
+    ~AGnssRil();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+     * These declarations were generated from IAGnssRil.hal.
+     */
+    Return<void> setCallback(const sp<IAGnssRilCallback>& callback) override;
+    Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& agnssReflocation) override;
+    Return<bool> setSetId(IAGnssRil::SetIDType type, const hidl_string& setid) override;
+    Return<bool> updateNetworkState(bool connected,
+                                    IAGnssRil::NetworkType type,
+                                    bool roaming) override;
+    Return<bool> updateNetworkAvailability(bool available, const hidl_string& apn) override;
+    static void requestSetId(uint32_t flags);
+    static void requestRefLoc(uint32_t flags);
+
+    /*
+     * Callback method to be passed into the conventional GNSS HAL by the default
+     * implementation. This method is not part of the IAGnssRil base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static AGpsRilCallbacks sAGnssRilCb;
+
+ private:
+    const AGpsRilInterface* mAGnssRilIface = nullptr;
+    static sp<IAGnssRilCallback> sAGnssRilCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_AGnssRil_H_
diff --git a/src/connectivity/gps/service/1.1/Android.mk b/src/connectivity/gps/service/1.1/Android.mk
new file mode 100644
index 0000000..acd55f8
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/Android.mk
@@ -0,0 +1,64 @@
+ifdef HIDL_V1_1
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.1-impl-mediatek
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    ThreadCreationWrapper.cpp \
+    AGnss.cpp \
+    AGnssRil.cpp \
+    Gnss.cpp \
+    GnssBatching.cpp \
+    GnssDebug.cpp \
+    GnssGeofencing.cpp \
+    GnssMeasurement.cpp \
+    GnssNavigationMessage.cpp \
+    GnssNi.cpp \
+    GnssXtra.cpp \
+    GnssConfiguration.cpp \
+    GnssUtils.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libhidlbase \
+    libhidltransport \
+    libutils \
+    android.hardware.gnss@1.0 \
+    android.hardware.gnss@1.1 \
+    libhardware \
+
+LOCAL_CFLAGS += -Werror
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+LOCAL_MODULE := android.hardware.gnss@1.1-service-mediatek
+LOCAL_INIT_RC := android.hardware.gnss@1.1-service-mediatek.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware \
+    libbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.gnss@1.1 \
+
+LOCAL_REQUIRED_MODULES := \
+    android.hardware.gnss@1.1-impl-mediatek
+
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/src/connectivity/gps/service/1.1/Gnss.cpp b/src/connectivity/gps/service/1.1/Gnss.cpp
new file mode 100644
index 0000000..4559008
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/Gnss.cpp
@@ -0,0 +1,872 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssInterface"
+
+#include "Gnss.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> Gnss::sThreadFuncArgsList;
+sp<IGnssCallback> Gnss::sGnssCbIface = nullptr;
+bool Gnss::sInterfaceExists = false;
+bool Gnss::sWakelockHeldGnss = false;
+bool Gnss::sWakelockHeldFused = false;
+
+GpsCallbacks_ext Gnss::sGnssCb = {
+    .size = sizeof(GpsCallbacks_ext),
+    .location_cb = locationCb,
+    .status_cb = statusCb,
+    .sv_status_cb = gpsSvStatusCb,
+    .nmea_cb = nmeaCb,
+    .set_capabilities_cb = setCapabilitiesCb,
+    .acquire_wakelock_cb = acquireWakelockCb,
+    .release_wakelock_cb = releaseWakelockCb,
+    .create_thread_cb = createThreadCb,
+    .request_utc_time_cb = requestUtcTimeCb,
+    .set_system_info_cb = setSystemInfoCb,
+    .gnss_sv_status_cb = gnssSvStatusCb,
+
+    .set_name_cb = setNameCb,
+    .request_location_cb = requestLocationCb
+};
+
+uint32_t Gnss::sCapabilitiesCached = 0;
+uint16_t Gnss::sYearOfHwCached = 0;
+sem_t Gnss::sSem;
+
+Gnss::Gnss(gps_device_t_ext* gnssDevice) :
+        mDeathRecipient(new GnssHidlDeathRecipient(this)) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+
+    if (gnssDevice == nullptr) {
+        ALOGE("%s: Invalid device_t handle", __func__);
+        return;
+    }
+
+    mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
+    sem_init(&sSem, 0, 1);
+}
+
+Gnss::~Gnss() {
+    sInterfaceExists = false;
+    sThreadFuncArgsList.clear();
+    sem_destroy(&sSem);
+}
+
+void Gnss::locationCb(GpsLocation_ext* location) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s: Invalid location from GNSS HAL", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    GnssLocation gnssLocation = V1_0::implementation::convertToGnssLocation(location);
+    auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::statusCb(GpsStatus* gnssStatus) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (gnssStatus == nullptr) {
+        ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssStatusValue status =
+            static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
+
+    auto ret = sGnssCbIface->gnssStatusCb(status);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::gnssSvStatusCb(GnssSvStatus_ext* status) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = status->num_svs;
+
+    if (svStatus.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+        ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, V1_0::GnssMax::SVS_COUNT);
+        svStatus.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+    }
+
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        auto svInfo = status->gnss_sv_list[i];
+        IGnssCallback::GnssSvInfo gnssSvInfo = {
+            .svid = svInfo.legacySvInfo.svid,
+            .constellation = static_cast<V1_0::GnssConstellationType>(
+                    svInfo.legacySvInfo.constellation),
+            .cN0Dbhz = svInfo.legacySvInfo.c_n0_dbhz,
+            .elevationDegrees = svInfo.legacySvInfo.elevation,
+            .azimuthDegrees = svInfo.legacySvInfo.azimuth,
+            .svFlag = static_cast<uint8_t>(svInfo.legacySvInfo.flags),
+            .carrierFrequencyHz = svInfo.carrier_frequency};
+        svStatus.gnssSvList[i] = gnssSvInfo;
+    }
+
+    auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+/*
+ * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
+ * to GnssSvStatus for backward compatibility. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum SvidValues : uint16_t {
+    GLONASS_SVID_OFFSET = 64,
+    GLONASS_SVID_COUNT = 24,
+    BEIDOU_SVID_OFFSET = 200,
+    BEIDOU_SVID_COUNT = 35,
+    SBAS_SVID_MIN = 33,
+    SBAS_SVID_MAX = 64,
+    SBAS_SVID_ADD = 87,
+    QZSS_SVID_MIN = 193,
+    QZSS_SVID_MAX = 200
+};
+
+/*
+ * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
+ * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
+ * being deprecated and is no longer part of the GNSS interface.
+ */
+void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (svInfo == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = svInfo->num_svs;
+    /*
+     * Clamp the list size since GnssSvStatus can support a maximum of
+     * GnssMax::SVS_COUNT entries.
+     */
+    ///M: fix max numSvs as GPS_MAX_SVS
+    if (svStatus.numSvs > static_cast<uint32_t>(GPS_MAX_SVS)) {
+        ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GPS_MAX_SVS);
+        svStatus.numSvs = static_cast<uint32_t>(GPS_MAX_SVS);
+    }
+    /// M: mtk update end
+
+    uint32_t ephemerisMask = svInfo->ephemeris_mask;
+    uint32_t almanacMask = svInfo->almanac_mask;
+    uint32_t usedInFixMask = svInfo->used_in_fix_mask;
+    /*
+     * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
+     */
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
+        info.svid = svInfo->sv_list[i].prn;
+        if (info.svid >= 1 && info.svid <= 32) {
+            info.constellation = GnssConstellationType::GPS;
+        } else if (info.svid > GLONASS_SVID_OFFSET &&
+                   info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
+            info.constellation = GnssConstellationType::GLONASS;
+            info.svid -= GLONASS_SVID_OFFSET;
+        } else if (info.svid > BEIDOU_SVID_OFFSET &&
+                 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
+            info.constellation = GnssConstellationType::BEIDOU;
+            info.svid -= BEIDOU_SVID_OFFSET;
+        } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
+            info.constellation = GnssConstellationType::SBAS;
+            info.svid += SBAS_SVID_ADD;
+        } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
+            info.constellation = GnssConstellationType::QZSS;
+        } else {
+            ALOGD("Unknown constellation type with Svid = %d.", info.svid);
+            info.constellation = GnssConstellationType::UNKNOWN;
+        }
+
+        info.cN0Dbhz = svInfo->sv_list[i].snr;
+        info.elevationDegrees = svInfo->sv_list[i].elevation;
+        info.azimuthDegrees = svInfo->sv_list[i].azimuth;
+        // TODO: b/31702236
+        info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+
+        /*
+         * Only GPS info is valid for these fields, as these masks are just 32
+         * bits, by GPS prn.
+         */
+        if (info.constellation == GnssConstellationType::GPS) {
+            int32_t svidMask = (1 << (info.svid - 1));
+            if ((ephemerisMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+            }
+            if ((almanacMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+            }
+            if ((usedInFixMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+            }
+        }
+    }
+
+    auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    android::hardware::hidl_string nmeaString;
+    nmeaString.setToExternal(nmea, length);
+    auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::setCapabilitiesCb(uint32_t capabilities) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sCapabilitiesCached = capabilities;
+    sem_post(&sSem);
+}
+
+void Gnss::acquireWakelockCb() {
+    acquireWakelockGnss();
+}
+
+void Gnss::releaseWakelockCb() {
+    releaseWakelockGnss();
+}
+
+
+void Gnss::acquireWakelockGnss() {
+    sWakelockHeldGnss = true;
+    updateWakelock();
+}
+
+void Gnss::releaseWakelockGnss() {
+    sWakelockHeldGnss = false;
+    updateWakelock();
+}
+
+void Gnss::acquireWakelockFused() {
+    sWakelockHeldFused = true;
+    updateWakelock();
+}
+
+void Gnss::releaseWakelockFused() {
+    sWakelockHeldFused = false;
+    updateWakelock();
+}
+
+void Gnss::updateWakelock() {
+    // Track the state of the last request - in case the wake lock in the layer above is reference
+    // counted.
+    static bool sWakelockHeld = false;
+
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (sWakelockHeldGnss || sWakelockHeldFused) {
+        if (!sWakelockHeld) {
+            ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
+                    sWakelockHeldGnss, sWakelockHeldFused);
+            sWakelockHeld = true;
+            auto ret = sGnssCbIface->gnssAcquireWakelockCb();
+            if (!ret.isOk()) {
+                ALOGE("%s: Unable to invoke callback", __func__);
+            }
+        }
+    } else {
+        if (sWakelockHeld) {
+            ALOGI("%s: GNSS HAL Wakelock released", __func__);
+        } else  {
+            // To avoid burning power, always release, even if logic got here with sWakelock false
+            // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
+            ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
+        }
+        sWakelockHeld = false;
+        auto ret = sGnssCbIface->gnssReleaseWakelockCb();
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+        }
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::requestUtcTimeCb() {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssRequestTimeCb();
+    if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (info == nullptr) {
+        ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSystemInfo gnssInfo = {
+        .yearOfHw = info->year_of_hw
+    };
+
+    auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sYearOfHwCached = info->year_of_hw;
+    sem_post(&sSem);
+}
+
+void Gnss::setNameCb(const char* name, int length) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    android::hardware::hidl_string nameString;
+    nameString.setToExternal(name, length);
+    auto ret = sGnssCbIface->gnssNameCb(nameString);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void Gnss::requestLocationCb(bool independentFromGnss) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssRequestLocationCb(independentFromGnss);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+Return<bool> Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) {
+    return false;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(
+    const sp<::android::hardware::gnss::V1_1::IGnssCallback>& callback) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    if (callback == nullptr)  {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sem_wait(&sSem);
+    if (sGnssCbIface != NULL) {
+        ALOGW("%s called more than once. Unexpected unless test.", __func__);
+        sGnssCbIface->unlinkToDeath(mDeathRecipient);
+    }
+
+    sGnssCbIface = callback;
+    callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
+    sem_post(&sSem);
+
+    // If this was received in the past, send it up again to refresh caller.
+    // mGnssIface will override after init() is called below, if needed
+    // (though it's unlikely the gps.h capabilities or system info will change.)
+    if (sCapabilitiesCached != 0) {
+        setCapabilitiesCb(sCapabilitiesCached);
+    }
+    if (sYearOfHwCached != 0) {
+        LegacyGnssSystemInfo info;
+        info.year_of_hw = sYearOfHwCached;
+        setSystemInfoCb(&info);
+    }
+
+    return (mGnssIface->init(&sGnssCb) == 0);
+}
+
+Return<bool> Gnss::start()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->start() == 0);
+}
+
+Return<bool> Gnss::stop()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->stop() == 0);
+}
+
+Return<void> Gnss::cleanup()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->cleanup();
+    }
+    return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+                                  double longitudeDegrees,
+                                  float accuracyMeters)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation&) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    double latitudeDegrees = 0;
+    double longitudeDegrees = 0;
+    float accuracyMeters = 0;
+
+    return (mGnssIface->inject_fused_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
+}
+
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                              int32_t uncertaintyMs) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
+    }
+    return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode,
+        V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t, uint32_t)  {
+    return false;
+}
+
+Return<bool> Gnss::setPositionMode_1_1(
+    ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode mode,
+    ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence recurrence,
+    uint32_t minIntervalMs,
+    uint32_t preferredAccuracyMeters,
+    uint32_t preferredTimeMs,
+    bool lowPowerMode) {
+                                  
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
+                                          static_cast<GpsPositionRecurrence>(recurrence),
+                                          minIntervalMs,
+                                          preferredAccuracyMeters,
+                                          preferredTimeMs,
+                                          lowPowerMode) == 0);
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssRil == nullptr) {
+        const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
+                mGnssIface->get_extension(AGPS_RIL_INTERFACE));
+        if (agpsRilIface == nullptr) {
+            ALOGI("%s: GnssRil interface not implemented by HAL", __func__);
+        } else {
+            mGnssRil = new V1_0::implementation::AGnssRil(agpsRilIface);
+        }
+    }
+    return mGnssRil;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration()  {
+    return nullptr;
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssConfig == nullptr) {
+        const GnssConfigurationInterface_ext* gnssConfigIface =
+                static_cast<const GnssConfigurationInterface_ext*>(
+                        mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
+
+        if (gnssConfigIface == nullptr) {
+            ALOGW("%s: GnssConfiguration interface not implemented by HAL", __func__);
+        } else {
+            mGnssConfig = new V1_1::implementation::GnssConfiguration(gnssConfigIface);
+        }
+    }
+    return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssGeofencingIface == nullptr) {
+        const GpsGeofencingInterface_ext* gpsGeofencingIface =
+                static_cast<const GpsGeofencingInterface_ext*>(
+                        mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
+
+        if (gpsGeofencingIface == nullptr) {
+            ALOGE("%s: GnssGeofencing interface not implemented by HAL", __func__);
+        } else {
+            mGnssGeofencingIface = new V1_0::implementation::GnssGeofencing(gpsGeofencingIface);
+        }
+    }
+
+    return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mAGnssIface == nullptr) {
+        const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
+                mGnssIface->get_extension(AGPS_INTERFACE));
+        if (agpsIface == nullptr) {
+            ALOGE("%s: AGnss interface not implemented by HAL", __func__);
+        } else {
+            mAGnssIface = new V1_0::implementation::AGnss(agpsIface);
+        }
+    }
+    return mAGnssIface;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssNi == nullptr) {
+        const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
+                mGnssIface->get_extension(GPS_NI_INTERFACE));
+        if (gpsNiIface == nullptr) {
+            ALOGI("%s: GnssNi interface not implemented by HAL", __func__);
+        } else {
+            mGnssNi = new V1_0::implementation::GnssNi(gpsNiIface);
+        }
+    }
+    return mGnssNi;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+    return nullptr;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssMeasurement == nullptr) {
+        const GpsMeasurementInterface_ext* gpsMeasurementIface =
+                static_cast<const GpsMeasurementInterface_ext*>(
+                        mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
+
+        if (gpsMeasurementIface == nullptr) {
+            ALOGE("%s: GnssMeasurement interface not implemented by HAL", __func__);
+        } else {
+            mGnssMeasurement = new V1_1::implementation::GnssMeasurement(gpsMeasurementIface);
+        }
+    }
+    return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssNavigationMessage == nullptr) {
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface =
+                static_cast<const GpsNavigationMessageInterface*>(
+                        mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
+
+        if (gpsNavigationMessageIface == nullptr) {
+            ALOGI("%s: GnssNavigationMessage interface not implemented by HAL", __func__);
+        } else {
+            mGnssNavigationMessage = new V1_0::implementation::GnssNavigationMessage(gpsNavigationMessageIface);
+        }
+    }
+
+    return mGnssNavigationMessage;
+}
+
+Return<sp<V1_0::IGnssXtra>> Gnss::getExtensionXtra()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssXtraIface == nullptr) {
+        const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
+                mGnssIface->get_extension(GPS_XTRA_INTERFACE));
+
+        if (gpsXtraIface == nullptr) {
+            ALOGI("%s: GnssXtra interface not implemented by HAL", __func__);
+        } else {
+            mGnssXtraIface = new V1_0::implementation::GnssXtra(gpsXtraIface);
+        }
+    }
+
+    return mGnssXtraIface;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssDebug == nullptr) {
+        const GpsDebugInterface_ext* gpsDebugIface = static_cast<const GpsDebugInterface_ext*>(
+                mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
+
+        if (gpsDebugIface == nullptr) {
+            ALOGI("%s: GnssDebug interface not implemented by HAL", __func__);
+        } else {
+            mGnssDebug = new V1_0::implementation::GnssDebug(gpsDebugIface);
+        }
+    }
+
+    return mGnssDebug;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssBatching == nullptr) {
+        hw_module_t* module;
+        const FlpLocationInterface* flpLocationIface = nullptr;
+        int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+        if (err != 0) {
+            ALOGE("gnss flp hw_get_module failed: %d", err);
+        } else if (module == nullptr) {
+            ALOGE("Fused Location hw_get_module returned null module");
+        } else if (module->methods == nullptr) {
+            ALOGE("Fused Location hw_get_module returned null methods");
+        } else {
+            hw_device_t* device;
+            err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
+            if (err != 0) {
+                ALOGE("flpDevice open failed: %d", err);
+            } else {
+                flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
+                flpLocationIface = flpDevice->get_flp_interface(flpDevice);
+            }
+        }
+
+        if (flpLocationIface == nullptr) {
+            ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
+        } else {
+            mGnssBatching = new V1_0::implementation::GnssBatching(flpLocationIface);
+        }
+    }
+    return mGnssBatching;
+}
+
+void Gnss::handleHidlDeath() {
+    ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
+
+    /// M: move here! Do not callback to system_server to avoid gnss hidl service NE
+    /*
+     * This has died, so close it off in case (race condition) callbacks happen
+     * before HAL processes above messages.
+     */
+    sem_wait(&sSem);
+    sGnssCbIface = nullptr;
+    sem_post(&sSem);
+
+    // commands down to the HAL implementation
+    stop(); // stop ongoing GPS tracking
+    if (mGnssMeasurement != nullptr) {
+        mGnssMeasurement->close();
+    }
+    if (mGnssNavigationMessage != nullptr) {
+        mGnssNavigationMessage->close();
+    }
+    if (mGnssBatching != nullptr) {
+        mGnssBatching->stop();
+        mGnssBatching->cleanup();
+    }
+    cleanup();
+
+}
+
+IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
+    hw_module_t* module;
+    IGnss* iface = nullptr;
+    int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+    if (err == 0) {
+        hw_device_t* device;
+        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            iface = new Gnss(reinterpret_cast<gps_device_t_ext*>(device));
+        } else {
+            ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+        }
+    } else {
+      ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+    }
+    return iface;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/Gnss.h b/src/connectivity/gps/service/1.1/Gnss.h
new file mode 100644
index 0000000..602482d
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/Gnss.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_1_Gnss_H_
+#define android_hardware_gnss_V1_1_Gnss_H_
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssDebug.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNavigationMessage.h>
+#include <GnssNi.h>
+#include <GnssXtra.h>
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <hardware/fused_location.h>
+#include <hidl/Status.h>
+#include "hardware/gps_mtk.h"
+
+#include <semaphore.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssSystemInfo = ::GnssSystemInfo;
+using GnssConstellationType = V1_0::GnssConstellationType;
+using GnssLocation = V1_0::GnssLocation;
+
+/*
+ * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
+ * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+class Gnss : public IGnss {
+  public:
+    Gnss(gps_device_t_ext* gnss_device);
+    ~Gnss();
+
+    // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+    Return<bool> setCallback(
+        const sp<V1_0::IGnssCallback>& callback) override;
+    Return<bool> start() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+    Return<bool> injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<bool> injectLocation(double latitudeDegrees, double longitudeDegrees,
+                                float accuracyMeters) override;
+    Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+    Return<bool> setPositionMode(
+        V1_0::IGnss::GnssPositionMode mode,
+        V1_0::IGnss::GnssPositionRecurrence recurrence,
+        uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+        uint32_t preferredTimeMs) override;
+    Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+    Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+    Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<V1_0::IGnssNavigationMessage>>
+    getExtensionGnssNavigationMessage() override;
+    Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override;
+    Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+    Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+    Return<bool> setCallback_1_1(
+        const sp<V1_1::IGnssCallback>& callback) override;
+    Return<bool> setPositionMode_1_1(
+        V1_0::IGnss::GnssPositionMode mode,
+        V1_0::IGnss::GnssPositionRecurrence recurrence,
+        uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+        bool lowPowerMode) override;
+    Return<sp<V1_1::IGnssConfiguration>>
+    getExtensionGnssConfiguration_1_1() override;
+    Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+    Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
+
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnss base class.
+     */
+    static void locationCb(GpsLocation_ext* location);
+    static void statusCb(GpsStatus* gnss_status);
+    static void nmeaCb(GpsUtcTime timestamp, const char* nmea, int length);
+    static void setCapabilitiesCb(uint32_t capabilities);
+    static void acquireWakelockCb();
+    static void releaseWakelockCb();
+    static void requestUtcTimeCb();
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssSvStatusCb(GnssSvStatus_ext* status);
+    /*
+     * Deprecated callback added for backward compatibility to devices that do
+     * not support GnssSvStatus.
+     */
+    static void gpsSvStatusCb(GpsSvStatus* status);
+    static void setSystemInfoCb(const LegacyGnssSystemInfo* info);
+
+    /*
+     * Wakelock consolidation, only needed for dual use of a gps.h & fused_location.h HAL
+     *
+     * Ensures that if the last call from either legacy .h was to acquire a wakelock, that a
+     * wakelock is held.  Otherwise releases it.
+     */
+    static void acquireWakelockFused();
+    static void releaseWakelockFused();
+
+    static void setNameCb(const char* name, int length);
+    static void requestLocationCb(bool independentFromGnss);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsCallbacks_ext sGnssCb;
+
+ private:
+    /*
+     * For handling system-server death while GNSS service lives on.
+     */
+    class GnssHidlDeathRecipient : public hidl_death_recipient {
+      public:
+        GnssHidlDeathRecipient(const sp<Gnss> gnss) : mGnss(gnss) {
+        }
+
+        virtual void serviceDied(uint64_t /*cookie*/,
+                const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+            mGnss->handleHidlDeath();
+        }
+      private:
+        sp<Gnss> mGnss;
+    };
+
+    // for wakelock consolidation, see above
+    static void acquireWakelockGnss();
+    static void releaseWakelockGnss();
+    static void updateWakelock();
+    static bool sWakelockHeldGnss;
+    static bool sWakelockHeldFused;
+
+    /*
+     * Cleanup for death notification
+     */
+    void handleHidlDeath();
+
+    sp<V1_0::implementation::GnssXtra> mGnssXtraIface = nullptr;
+    sp<V1_0::implementation::AGnssRil> mGnssRil = nullptr;
+    sp<V1_0::implementation::GnssGeofencing> mGnssGeofencingIface = nullptr;
+    sp<V1_0::implementation::AGnss> mAGnssIface = nullptr;
+    sp<V1_0::implementation::GnssNi> mGnssNi = nullptr;
+    sp<V1_1::implementation::GnssMeasurement> mGnssMeasurement = nullptr;
+    sp<V1_0::implementation::GnssNavigationMessage> mGnssNavigationMessage = nullptr;
+    sp<V1_0::implementation::GnssDebug> mGnssDebug = nullptr;
+    sp<V1_1::implementation::GnssConfiguration> mGnssConfig = nullptr;
+    sp<V1_0::implementation::GnssBatching> mGnssBatching = nullptr;
+
+    ///M: add semphore protection
+    static sem_t sSem;
+
+    sp<GnssHidlDeathRecipient> mDeathRecipient;
+    const GpsInterface_ext* mGnssIface = nullptr;
+    static sp<V1_1::IGnssCallback> sGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+
+    // Values saved for resend
+    static uint32_t sCapabilitiesCached;
+    static uint16_t sYearOfHwCached;
+};
+
+extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_1_Gnss_H_
diff --git a/src/connectivity/gps/service/1.1/GnssBatching.cpp b/src/connectivity/gps/service/1.1/GnssBatching.cpp
new file mode 100644
index 0000000..292b811
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssBatching.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssBatchingInterface"
+
+#include "GnssBatching.h"
+#include <Gnss.h> // for wakelock consolidation
+#include <GnssUtils.h>
+
+#include <log/log.h>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssBatchingCallback> GnssBatching::sGnssBatchingCbIface = nullptr;
+bool GnssBatching::sFlpSupportsBatching = false;
+
+FlpCallbacks GnssBatching::sFlpCb = {
+    .size = sizeof(FlpCallbacks),
+    .location_cb = locationCb,
+    .acquire_wakelock_cb = acquireWakelockCb,
+    .release_wakelock_cb = releaseWakelockCb,
+    .set_thread_event_cb = setThreadEventCb,
+    .flp_capabilities_cb = flpCapabilitiesCb,
+    .flp_status_cb = flpStatusCb,
+};
+
+GnssBatching::GnssBatching(const FlpLocationInterface* flpLocationIface) :
+    mFlpLocationIface(flpLocationIface) {
+}
+
+/*
+ * This enum is used locally by various methods below. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum BatchingValues : uint16_t {
+    // Numbers 0-3 were used in earlier implementations - using 4 to be distinct to the HAL
+    FLP_GNSS_BATCHING_CLIENT_ID = 4,
+    // Tech. mask of GNSS, and sensor aiding, for legacy HAL to fit with GnssBatching API
+    FLP_TECH_MASK_GNSS_AND_SENSORS = FLP_TECH_MASK_GNSS | FLP_TECH_MASK_SENSORS,
+    // Putting a cap to avoid possible memory issues.  Unlikely values this high are supported.
+    MAX_LOCATIONS_PER_BATCH = 1000
+};
+
+void GnssBatching::locationCb(int32_t locationsCount, FlpLocation** locations) {
+    if (sGnssBatchingCbIface == nullptr) {
+        ALOGE("%s: GNSS Batching Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (locations == nullptr) {
+        ALOGE("%s: Invalid locations from GNSS HAL", __func__);
+        return;
+    }
+
+    if (locationsCount < 0) {
+        ALOGE("%s: Negative location count: %d set to 0", __func__, locationsCount);
+        locationsCount = 0;
+    } else if (locationsCount > MAX_LOCATIONS_PER_BATCH) {
+        ALOGW("%s: Unexpected high location count: %d set to %d", __func__, locationsCount,
+                MAX_LOCATIONS_PER_BATCH);
+        locationsCount = MAX_LOCATIONS_PER_BATCH;
+    }
+
+    /**
+     * Note:
+     * Some existing implementations may drop duplicate locations.  These could be expanded here
+     * but as there's ambiguity between no-GPS-fix vs. dropped duplicates in that implementation,
+     * and that's not specified by the fused_location.h, that isn't safe to do here.
+     * Fortunately, this shouldn't be a major issue in cases where GNSS batching is typically
+     * used (e.g. when user is likely in vehicle/bicycle.)
+     */
+    std::vector<android::hardware::gnss::V1_0::GnssLocation> gnssLocations;
+    for (int iLocation = 0; iLocation < locationsCount; iLocation++) {
+        if (locations[iLocation] == nullptr) {
+            ALOGE("%s: Null location at slot: %d of %d, skipping", __func__, iLocation,
+                    locationsCount);
+            continue;
+        }
+        if ((locations[iLocation]->sources_used & ~FLP_TECH_MASK_GNSS_AND_SENSORS) != 0)
+        {
+            ALOGE("%s: Unrequested location type %d at slot: %d of %d, skipping", __func__,
+                    locations[iLocation]->sources_used, iLocation, locationsCount);
+            continue;
+        }
+        gnssLocations.push_back(convertToGnssLocation(locations[iLocation]));
+    }
+
+    auto ret = sGnssBatchingCbIface->gnssLocationBatchCb(gnssLocations);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssBatching::acquireWakelockCb() {
+    V1_1::implementation::Gnss::acquireWakelockFused();
+}
+
+void GnssBatching::releaseWakelockCb() {
+    V1_1::implementation::Gnss::releaseWakelockFused();
+}
+
+// this can just return success, because threads are now set up on demand in the jni layer
+int32_t GnssBatching::setThreadEventCb(ThreadEvent /*event*/) {
+    return FLP_RESULT_SUCCESS;
+}
+
+void GnssBatching::flpCapabilitiesCb(int32_t capabilities) {
+    ALOGD("%s capabilities %d", __func__, capabilities);
+
+    if (capabilities & CAPABILITY_GNSS) {
+        // once callback is received and capabilities high enough, we know version is
+        // high enough for flush()
+        sFlpSupportsBatching = true;
+    }
+}
+
+void GnssBatching::flpStatusCb(int32_t status) {
+    ALOGD("%s (default implementation) not forwarding status: %d", __func__, status);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching is unavailable", __func__);
+        return false;
+    }
+
+    sGnssBatchingCbIface = callback;
+
+    return (mFlpLocationIface->init(&sFlpCb) == 0);
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return 0;
+    }
+
+    return mFlpLocationIface->get_batch_size();
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return false;
+    }
+
+    if (!sFlpSupportsBatching) {
+        ALOGE("%s: Flp batching interface not supported, no capabilities callback received",
+                __func__);
+        return false;
+    }
+
+    FlpBatchOptions optionsHw;
+    // Legacy code used 9999 mW for High accuracy, and 21 mW for balanced.
+    // New GNSS API just expects reasonable GNSS chipset behavior - do something efficient
+    // given the interval.  This 100 mW limit should be quite sufficient (esp. given legacy code
+    // implementations may not even use this value.)
+    optionsHw.max_power_allocation_mW = 100;
+    optionsHw.sources_to_use = FLP_TECH_MASK_GNSS_AND_SENSORS;
+    optionsHw.flags = 0;
+    if (options.flags & Flag::WAKEUP_ON_FIFO_FULL) {
+        optionsHw.flags |= FLP_BATCH_WAKEUP_ON_FIFO_FULL;
+    }
+    optionsHw.period_ns = options.periodNanos;
+    optionsHw.smallest_displacement_meters = 0; // Zero offset - just use time interval
+
+    return (mFlpLocationIface->start_batching(FLP_GNSS_BATCHING_CLIENT_ID, &optionsHw)
+            == FLP_RESULT_SUCCESS);
+}
+
+Return<void> GnssBatching::flush() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return Void();
+    }
+
+    mFlpLocationIface->flush_batched_locations();
+
+    return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mFlpLocationIface->stop_batching(FLP_GNSS_BATCHING_CLIENT_ID) == FLP_RESULT_SUCCESS);
+}
+
+Return<void> GnssBatching::cleanup() {
+    if (mFlpLocationIface == nullptr) {
+        ALOGE("%s: Flp batching interface is unavailable", __func__);
+        return Void();
+    }
+
+    mFlpLocationIface->cleanup();
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssBatching.h b/src/connectivity/gps/service/1.1/GnssBatching.h
new file mode 100644
index 0000000..001c27d
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssBatching.h
@@ -0,0 +1,67 @@
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hardware/fused_location.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct GnssBatching : public IGnssBatching {
+    GnssBatching(const FlpLocationInterface* flpLocationIface);
+
+    // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+    Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+    Return<uint16_t> getBatchSize() override;
+    Return<bool> start(const IGnssBatching::Options& options ) override;
+    Return<void> flush() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+
+    /*
+     * Callback methods to be passed into the conventional FLP HAL by the default
+     * implementation. These methods are not part of the IGnssBatching base class.
+     */
+    static void locationCb(int32_t locationsCount, FlpLocation** locations);
+    static void acquireWakelockCb();
+    static void releaseWakelockCb();
+    static int32_t setThreadEventCb(ThreadEvent event);
+    static void flpCapabilitiesCb(int32_t capabilities);
+    static void flpStatusCb(int32_t status);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static FlpCallbacks sFlpCb;
+
+ private:
+    const FlpLocationInterface* mFlpLocationIface = nullptr;
+    static sp<IGnssBatchingCallback> sGnssBatchingCbIface;
+    static bool sFlpSupportsBatching;
+};
+
+extern "C" IGnssBatching* HIDL_FETCH_IGnssBatching(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
diff --git a/src/connectivity/gps/service/1.1/GnssConfiguration.cpp b/src/connectivity/gps/service/1.1/GnssConfiguration.cpp
new file mode 100644
index 0000000..be57d24
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssConfiguration.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssConfigurationInterface"
+
+#include <log/log.h>
+
+#include "GnssConfiguration.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+GnssConfiguration::GnssConfiguration(const GnssConfigurationInterface_ext* gnssConfigInfc)
+    : mGnssConfigIface(gnssConfigInfc) {}
+
+// Methods from ::android::hardware::gps::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_ES=" + std::to_string(enabled ? 1 : 0) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_VER=" + std::to_string(version) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_MODE=" + std::to_string(mode) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "LPP_PROFILE=" + std::to_string(lppProfile) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "A_GLONASS_POS_PROTOCOL_SELECT=" +
+            std::to_string(protocol) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "GPS_LOCK=" + std::to_string(lock) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=" + std::to_string(enabled ? 1 : 0)
+            + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(const hidl_vec<BlacklistedSource>& sourceList) {
+    size_t listSize = sourceList.size();
+    long long blackSvid[7];  /// V1_0::GnssConstellationType size is 7
+    memset(blackSvid, 0x00, sizeof(long long)*7);
+
+    for (size_t i = 0; i < listSize; i++) {
+        int idx = (int) sourceList[i].constellation;
+        if (idx > 6) {
+            ALOGE("%s: GnssConstellation type is out of boundary.", __func__);
+            continue;
+        } else if (sourceList[i].svid == 0) { /// all sv are blocked
+            blackSvid[idx] = (long long)(((long long)0xFFFFFFFFL << 32) | 0xFFFFFFFFL);
+        } else {
+            blackSvid[idx] |= (long long)((long long)0x01L << (sourceList[i].svid -1));
+        }
+    }
+
+    mGnssConfigIface->setBlacklist(blackSvid, 7);
+    return true;
+}
+
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssConfiguration.h b/src/connectivity/gps/service/1.1/GnssConfiguration.h
new file mode 100644
index 0000000..8b6c781
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssConfiguration.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef android_hardware_gnss_V1_1_GnssConfiguration_H_
+#define android_hardware_gnss_V1_1_GnssConfiguration_H_
+
+#include <android/hardware/gnss/1.1/IGnssConfiguration.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+#include <hardware/gps_mtk.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_1::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using BlacklistedSource = V1_1::IGnssConfiguration::BlacklistedSource;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct GnssConfiguration : public IGnssConfiguration {
+    GnssConfiguration(const GnssConfigurationInterface_ext* gnssConfigIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+     * These declarations were generated from IGnssConfiguration.hal.
+     */
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(uint8_t mode) override;
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setLppProfile(uint8_t lppProfile) override;
+    Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+    Return<bool> setGpsLock(uint8_t lock) override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist(const hidl_vec<BlacklistedSource>& blacklist) override;
+
+ private:
+    const GnssConfigurationInterface_ext* mGnssConfigIface = nullptr;
+
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_1_GnssConfiguration_H_
diff --git a/src/connectivity/gps/service/1.1/GnssDebug.cpp b/src/connectivity/gps/service/1.1/GnssDebug.cpp
new file mode 100644
index 0000000..d2d64b5
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssDebug.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssDebugInterface"
+
+#include <log/log.h>
+
+#include "GnssDebug.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssDebug::GnssDebug(const GpsDebugInterface_ext* gpsDebugIface) : mGnssDebugIface(gpsDebugIface) {}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)  {
+    /*
+     * This is a new interface and hence there is no way to retrieve the
+     * debug data from the HAL.
+     */
+    if (mGnssDebugIface) {
+        ::DebugData debugData;
+        IGnssDebug::DebugData data;
+        bool ret = mGnssDebugIface->get_internal_state(&debugData);
+        if (ret) {
+            data.position = (IGnssDebug::PositionDebug){
+                .valid = debugData.position.valid,
+                .latitudeDegrees = debugData.position.latitudeDegrees,
+                .longitudeDegrees = debugData.position.longitudeDegrees,
+                .altitudeMeters = debugData.position.altitudeMeters,
+                .speedMetersPerSec = debugData.position.speedMetersPerSec,
+                .bearingDegrees = debugData.position.bearingDegrees,
+                .horizontalAccuracyMeters = debugData.position.horizontalAccuracyMeters,
+                .verticalAccuracyMeters = debugData.position.verticalAccuracyMeters,
+                .speedAccuracyMetersPerSecond = debugData.position.speedAccuracyMetersPerSecond,
+                .bearingAccuracyDegrees = debugData.position.bearingAccuracyDegrees,
+                .ageSeconds = debugData.position.ageSeconds
+            };
+            data.time = (IGnssDebug::TimeDebug){
+                .timeEstimate = debugData.time.timeEstimate,
+                .timeUncertaintyNs = debugData.time.timeUncertaintyNs,
+                .frequencyUncertaintyNsPerSec = debugData.time.frequencyUncertaintyNsPerSec,
+            };
+
+            int count = 0;
+            for (; count < GNSS_MAX_SVS; count++) {
+                if (debugData.satelliteDataArray[count].svid == 0) {
+                    break;
+                }
+            }
+            data.satelliteDataArray.resize(count);
+            for (int i = 0; i < count; i++) {
+                auto entry = debugData.satelliteDataArray[i];
+                data.satelliteDataArray[i] = (IGnssDebug::SatelliteData) {
+                    .svid = entry.svid,
+                    .constellation = (V1_0::GnssConstellationType) entry.constellation,
+                    .ephemerisType = (IGnssDebug::SatelliteEphemerisType) entry.ephemerisType,
+                    .ephemerisSource = (IGnssDebug::SatelliteEphemerisSource)entry.ephemerisSource,
+                    .ephemerisHealth = (IGnssDebug::SatelliteEphemerisHealth)entry.ephemerisHealth,
+                    .ephemerisAgeSeconds = entry.ephemerisAgeSeconds,
+                    .serverPredictionIsAvailable = entry.serverPredictionIsAvailable,
+                    .serverPredictionAgeSeconds = entry.serverPredictionAgeSeconds
+                };
+            }
+            _hidl_cb(data);
+        }
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssDebug.h b/src/connectivity/gps/service/1.1/GnssDebug.h
new file mode 100644
index 0000000..7a2c6e9
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssDebug_H_
+#define android_hardware_gnss_V1_0_GnssDebug_H_
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+#include <hardware/gps_mtk.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct GnssDebug : public IGnssDebug {
+    GnssDebug(const GpsDebugInterface_ext* gpsDebugIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+     * These declarations were generated from IGnssDebug.hal.
+     */
+    Return<void> getDebugData(getDebugData_cb _hidl_cb)  override;
+
+ private:
+    /*
+     * Constant added for backward compatibility to conventional GPS Hals which
+     * returned a debug string.
+     */
+    const GpsDebugInterface_ext* mGnssDebugIface = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssDebug_H_
diff --git a/src/connectivity/gps/service/1.1/GnssGeofencing.cpp b/src/connectivity/gps/service/1.1/GnssGeofencing.cpp
new file mode 100644
index 0000000..3d51140
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssGeofencing.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include "GnssGeofencing.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssGeofencing::sThreadFuncArgsList;
+sp<IGnssGeofenceCallback> GnssGeofencing::mGnssGeofencingCbIface = nullptr;
+bool GnssGeofencing::sInterfaceExists = false;
+
+GpsGeofenceCallbacks_ext GnssGeofencing::sGnssGfCb = {
+    .geofence_transition_callback = gnssGfTransitionCb,
+    .geofence_status_callback = gnssGfStatusCb,
+    .geofence_add_callback = gnssGfAddCb,
+    .geofence_remove_callback = gnssGfRemoveCb,
+    .geofence_pause_callback = gnssGfPauseCb,
+    .geofence_resume_callback = gnssGfResumeCb,
+    .create_thread_cb = createThreadCb
+};
+
+GnssGeofencing::GnssGeofencing(const GpsGeofencingInterface_ext* gpsGeofencingIface)
+    : mGnssGeofencingIface(gpsGeofencingIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+GnssGeofencing::~GnssGeofencing() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+void GnssGeofencing::gnssGfTransitionCb(int32_t geofenceId,
+                                        GpsLocation_ext* location,
+                                        int32_t transition,
+                                        GpsUtcTime timestamp) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s : Invalid location from GNSS HAL", __func__);
+        return;
+    }
+
+    GnssLocation gnssLocation = convertToGnssLocation(location);
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+            geofenceId,
+            gnssLocation,
+            static_cast<IGnssGeofenceCallback::GeofenceTransition>(transition),
+            timestamp);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfStatusCb(int32_t status, GpsLocation_ext* location) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    GnssLocation gnssLocation;
+
+    if (location != nullptr) {
+        gnssLocation = convertToGnssLocation(location);
+    } else {
+        gnssLocation = {};
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceStatusCb(
+            static_cast<IGnssGeofenceCallback::GeofenceAvailability>(status), gnssLocation);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfAddCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceAddCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfRemoveCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfPauseCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofencePauseCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void GnssGeofencing::gnssGfResumeCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = mGnssGeofencingCbIface->gnssGeofenceResumeCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+pthread_t GnssGeofencing::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback)  {
+    mGnssGeofencingCbIface = callback;
+
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->init(&sGnssGfCb);
+    }
+
+    return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+        int32_t geofenceId,
+        double latitudeDegrees,
+        double longitudeDegrees,
+        double radiusMeters,
+        IGnssGeofenceCallback::GeofenceTransition lastTransition,
+        int32_t monitorTransitions,
+        uint32_t notificationResponsivenessMs,
+        uint32_t unknownTimerMs)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+        return Void();
+    } else {
+        mGnssGeofencingIface->add_geofence_area(
+                geofenceId,
+                latitudeDegrees,
+                longitudeDegrees,
+                radiusMeters,
+                static_cast<int32_t>(lastTransition),
+                monitorTransitions,
+                notificationResponsivenessMs,
+                unknownTimerMs);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->pause_geofence(geofenceId);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->resume_geofence(geofenceId, monitorTransitions);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->remove_geofence_area(geofenceId);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssGeofencing.h b/src/connectivity/gps/service/1.1/GnssGeofencing.h
new file mode 100644
index 0000000..1615d8f
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssGeofencing.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssGeofencing_H_
+#define android_hardware_gnss_V1_0_GnssGeofencing_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+#include <hardware/gps_mtk.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for GNSS Geofencing support. It also contains wrapper methods to allow
+ * methods from IGnssGeofenceCallback interface to be passed into the
+ * conventional implementation of the GNSS HAL.
+ */
+struct GnssGeofencing : public IGnssGeofencing {
+    GnssGeofencing(const GpsGeofencingInterface_ext* gpsGeofencingIface);
+    ~GnssGeofencing();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+     * These declarations were generated from IGnssGeofencing.hal.
+     */
+    Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback)  override;
+    Return<void> addGeofence(int32_t geofenceId,
+                             double latitudeDegrees,
+                             double longitudeDegrees,
+                             double radiusMeters,
+                             IGnssGeofenceCallback::GeofenceTransition lastTransition,
+                             int32_t monitorTransitions,
+                             uint32_t notificationResponsivenessMs,
+                             uint32_t unknownTimerMs)  override;
+
+    Return<void> pauseGeofence(int32_t geofenceId)  override;
+    Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  override;
+    Return<void> removeGeofence(int32_t geofenceId)  override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssGeofencing base class.
+     */
+    static void gnssGfTransitionCb(int32_t geofence_id, GpsLocation_ext* location,
+                                   int32_t transition, GpsUtcTime timestamp);
+    static void gnssGfStatusCb(int32_t status, GpsLocation_ext* last_location);
+    static void gnssGfAddCb(int32_t geofence_id, int32_t status);
+    static void gnssGfRemoveCb(int32_t geofence_id, int32_t status);
+    static void gnssGfPauseCb(int32_t geofence_id, int32_t status);
+    static void gnssGfResumeCb(int32_t geofence_id, int32_t status);
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsGeofenceCallbacks_ext sGnssGfCb;
+
+ private:
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static sp<IGnssGeofenceCallback> mGnssGeofencingCbIface;
+    const GpsGeofencingInterface_ext* mGnssGeofencingIface = nullptr;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssGeofencing_H_
diff --git a/src/connectivity/gps/service/1.1/GnssMeasurement.cpp b/src/connectivity/gps/service/1.1/GnssMeasurement.cpp
new file mode 100644
index 0000000..b474ed9
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssMeasurement.cpp
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssMeasurementInterface"
+
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+sp<V1_1::IGnssMeasurementCallback>
+        GnssMeasurement::sGnssMeasureCbIface = nullptr;
+GpsMeasurementCallbacks_ext GnssMeasurement::sGnssMeasurementCbs = {
+    .size = sizeof(GpsMeasurementCallbacks_ext),
+    .measurement_callback = gpsMeasurementCb,
+    .gnss_measurement_callback = gnssMeasurementCb
+};
+
+GnssMeasurement::GnssMeasurement(const GpsMeasurementInterface_ext* gpsMeasurementIface)
+    : mGnssMeasureIface(gpsMeasurementIface) {}
+
+void GnssMeasurement::gnssMeasurementCb(GnssData_ext* halGnssData) {
+    if (sGnssMeasureCbIface == nullptr) {
+        ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (halGnssData == nullptr) {
+        ALOGE("%s: Invalid GnssData from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssMeasurementCallback::GnssData gnssData;
+    size_t measurementCount = std::min(halGnssData->measurement_count,
+                                         static_cast<size_t>(V1_0::GnssMax::SVS_COUNT));
+    gnssData.measurements.resize(measurementCount);
+
+    for (size_t i = 0; i < measurementCount; i++) {
+        auto entry = halGnssData->measurements[i];
+        auto state = static_cast<GnssMeasurementState>(entry.legacyMeasurement.state);
+        if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED) {
+          state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+        }
+        if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED) {
+          state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+        }
+
+        gnssData.measurements[i].v1_0 = (V1_0::IGnssMeasurementCallback::GnssMeasurement){
+            .flags = entry.legacyMeasurement.flags,
+            .svid = entry.legacyMeasurement.svid,
+            .constellation = static_cast<V1_0::GnssConstellationType>(
+                    entry.legacyMeasurement.constellation),
+            .timeOffsetNs = entry.legacyMeasurement.time_offset_ns,
+            .state = state,
+            .receivedSvTimeInNs = entry.legacyMeasurement.received_sv_time_in_ns,
+            .receivedSvTimeUncertaintyInNs =
+                    entry.legacyMeasurement.received_sv_time_uncertainty_in_ns,
+            .cN0DbHz = entry.legacyMeasurement.c_n0_dbhz,
+            .pseudorangeRateMps = entry.legacyMeasurement.pseudorange_rate_mps,
+            .pseudorangeRateUncertaintyMps =
+                    entry.legacyMeasurement.pseudorange_rate_uncertainty_mps,
+            .accumulatedDeltaRangeState = entry.legacyMeasurement.accumulated_delta_range_state,
+            .accumulatedDeltaRangeM = entry.legacyMeasurement.accumulated_delta_range_m,
+            .accumulatedDeltaRangeUncertaintyM =
+                    entry.legacyMeasurement.accumulated_delta_range_uncertainty_m,
+            .carrierFrequencyHz = entry.legacyMeasurement.carrier_frequency_hz,
+            .carrierCycles = entry.legacyMeasurement.carrier_cycles,
+            .carrierPhase = entry.legacyMeasurement.carrier_phase,
+            .carrierPhaseUncertainty = entry.legacyMeasurement.carrier_phase_uncertainty,
+            .multipathIndicator = static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+                    entry.legacyMeasurement.multipath_indicator),
+            .snrDb = entry.legacyMeasurement.snr_db,
+            .agcLevelDb = entry.agc_level_db
+        };
+        gnssData.measurements[i].accumulatedDeltaRangeState =
+                    entry.legacyMeasurement.accumulated_delta_range_state;
+    }
+
+    auto clockVal = halGnssData->clock;
+    gnssData.clock = {
+        .gnssClockFlags = clockVal.flags,
+        .leapSecond = clockVal.leap_second,
+        .timeNs = clockVal.time_ns,
+        .timeUncertaintyNs = clockVal.time_uncertainty_ns,
+        .fullBiasNs = clockVal.full_bias_ns,
+        .biasNs = clockVal.bias_ns,
+        .biasUncertaintyNs = clockVal.bias_uncertainty_ns,
+        .driftNsps = clockVal.drift_nsps,
+        .driftUncertaintyNsps = clockVal.drift_uncertainty_nsps,
+        .hwClockDiscontinuityCount = clockVal.hw_clock_discontinuity_count
+    };
+
+    auto ret = sGnssMeasureCbIface->gnssMeasurementCb(gnssData);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+/*
+ * The code in the following method has been moved here from GnssLocationProvider.
+ * It converts GpsData to GnssData. This code is no longer required in
+ * GnssLocationProvider since GpsData is deprecated and no longer part of the
+ * GNSS interface.
+ */
+void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
+    if (sGnssMeasureCbIface == nullptr) {
+        ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (gpsData == nullptr) {
+        ALOGE("%s: Invalid GpsData from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssMeasurementCallback::GnssData gnssData;
+    size_t measurementCount = std::min(gpsData->measurement_count,
+                                         static_cast<size_t>(V1_0::GnssMax::SVS_COUNT));
+    gnssData.measurements.resize(measurementCount);
+
+    for (size_t i = 0; i < measurementCount; i++) {
+        auto entry = gpsData->measurements[i];
+        gnssData.measurements[i].v1_0.flags = entry.flags;
+        gnssData.measurements[i].v1_0.svid = static_cast<int32_t>(entry.prn);
+        if (entry.prn >= 1 && entry.prn <= 32) {
+            gnssData.measurements[i].v1_0.constellation = V1_0::GnssConstellationType::GPS;
+        } else {
+            gnssData.measurements[i].v1_0.constellation =
+                  V1_0::GnssConstellationType::UNKNOWN;
+        }
+
+        gnssData.measurements[i].v1_0.timeOffsetNs = entry.time_offset_ns;
+        gnssData.measurements[i].v1_0.state = entry.state;
+        gnssData.measurements[i].v1_0.receivedSvTimeInNs = entry.received_gps_tow_ns;
+        gnssData.measurements[i].v1_0.receivedSvTimeUncertaintyInNs =
+            entry.received_gps_tow_uncertainty_ns;
+        gnssData.measurements[i].v1_0.cN0DbHz = entry.c_n0_dbhz;
+        gnssData.measurements[i].v1_0.pseudorangeRateMps = entry.pseudorange_rate_mps;
+        gnssData.measurements[i].v1_0.pseudorangeRateUncertaintyMps =
+                entry.pseudorange_rate_uncertainty_mps;
+        gnssData.measurements[i].v1_0.accumulatedDeltaRangeState =
+                entry.accumulated_delta_range_state;
+        gnssData.measurements[i].v1_0.accumulatedDeltaRangeM =
+                entry.accumulated_delta_range_m;
+        gnssData.measurements[i].v1_0.accumulatedDeltaRangeUncertaintyM =
+                entry.accumulated_delta_range_uncertainty_m;
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
+            gnssData.measurements[i].v1_0.carrierFrequencyHz = entry.carrier_frequency_hz;
+        } else {
+            gnssData.measurements[i].v1_0.carrierFrequencyHz = 0;
+        }
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE) {
+            gnssData.measurements[i].v1_0.carrierPhase = entry.carrier_phase;
+        } else {
+            gnssData.measurements[i].v1_0.carrierPhase = 0;
+        }
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
+            gnssData.measurements[i].v1_0.carrierPhaseUncertainty = entry.carrier_phase_uncertainty;
+        } else {
+            gnssData.measurements[i].v1_0.carrierPhaseUncertainty = 0;
+        }
+
+        gnssData.measurements[i].v1_0.multipathIndicator =
+                static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+                        entry.multipath_indicator);
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_SNR) {
+            gnssData.measurements[i].v1_0.snrDb = entry.snr_db;
+        } else {
+            gnssData.measurements[i].v1_0.snrDb = 0;
+        }
+
+        gnssData.measurements[i].v1_0.agcLevelDb = 0;
+        gnssData.measurements[i].accumulatedDeltaRangeState = entry.accumulated_delta_range_state;
+    }
+
+    auto clockVal = gpsData->clock;
+    static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
+
+    gnssData.clock.leapSecond = clockVal.leap_second;
+    /*
+     * GnssClock only supports the more effective HW_CLOCK type, so type
+     * handling and documentation complexity has been removed.  To convert the
+     * old GPS_CLOCK types (active only in a limited number of older devices),
+     * the GPS time information is handled as an always discontinuous HW clock,
+     * with the GPS time information put into the full_bias_ns instead - so that
+     * time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
+     * sign of full_bias_ns and bias_ns has flipped between GpsClock &
+     * GnssClock, so that is also handled below.
+     */
+    switch (clockVal.type) {
+        case GPS_CLOCK_TYPE_UNKNOWN:
+            // Clock type unsupported.
+            ALOGE("Unknown clock type provided.");
+            break;
+        case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
+            // Already local hardware time. No need to do anything.
+            break;
+        case GPS_CLOCK_TYPE_GPS_TIME:
+            // GPS time, need to convert.
+            clockVal.flags |= GPS_CLOCK_HAS_FULL_BIAS;
+            clockVal.full_bias_ns = clockVal.time_ns;
+            clockVal.time_ns = 0;
+            gnssData.clock.hwClockDiscontinuityCount =
+                    discontinuity_count_to_handle_old_clock_type++;
+            break;
+    }
+
+    gnssData.clock.timeNs = clockVal.time_ns;
+    gnssData.clock.timeUncertaintyNs = clockVal.time_uncertainty_ns;
+    /*
+     * Definition of sign for full_bias_ns & bias_ns has been changed since N,
+     * so flip signs here.
+     */
+    gnssData.clock.fullBiasNs = -(clockVal.full_bias_ns);
+    gnssData.clock.biasNs = -(clockVal.bias_ns);
+    gnssData.clock.biasUncertaintyNs = clockVal.bias_uncertainty_ns;
+    gnssData.clock.driftNsps = clockVal.drift_nsps;
+    gnssData.clock.driftUncertaintyNsps = clockVal.drift_uncertainty_nsps;
+    gnssData.clock.gnssClockFlags = clockVal.flags;
+
+    auto ret = sGnssMeasureCbIface->gnssMeasurementCb(gnssData);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus>
+GnssMeasurement::setCallback(const sp<V1_0::IGnssMeasurementCallback>&) {
+    return V1_0::IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+}
+
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus>
+GnssMeasurement::setCallback_1_1(
+        const sp<V1_1::IGnssMeasurementCallback>& callback,
+        bool enableFullTracking) {
+
+    if (mGnssMeasureIface == nullptr) {
+        ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+        return GnssMeasurementStatus::ERROR_GENERIC;
+    }
+    sGnssMeasureCbIface = callback;
+
+    return static_cast<GnssMeasurement::GnssMeasurementStatus>(
+            mGnssMeasureIface->init(&sGnssMeasurementCbs, enableFullTracking));
+}
+
+Return<void> GnssMeasurement::close()  {
+    if (mGnssMeasureIface == nullptr) {
+        ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+    } else {
+        mGnssMeasureIface->close();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssMeasurement.h b/src/connectivity/gps/service/1.1/GnssMeasurement.h
new file mode 100644
index 0000000..4fa5426
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssMeasurement.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_1_GnssMeasurement_H_
+#define android_hardware_gnss_V1_1_GnssMeasurement_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+#include <hardware/gps_mtk.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_1::IGnssMeasurement;
+using ::android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+
+/*
+ * Extended interface for GNSS Measurements support. Also contains wrapper methods to allow methods
+ * from IGnssMeasurementCallback interface to be passed into the conventional implementation of the
+ * GNSS HAL.
+ */
+struct GnssMeasurement : public IGnssMeasurement {
+    GnssMeasurement(const GpsMeasurementInterface_ext* gpsMeasurementIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+     * These declarations were generated from IGnssMeasurement.hal.
+     */
+    Return<::android::hardware::gnss::V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
+        const sp<::android::hardware::gnss::V1_0::IGnssMeasurementCallback>& callback) override;
+    Return<void> close() override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+    Return<::android::hardware::gnss::V1_0::IGnssMeasurement::GnssMeasurementStatus>
+    setCallback_1_1(const sp<::android::hardware::gnss::V1_1::IGnssMeasurementCallback>& callback,
+            bool enableFullTracking) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssMeasurement base class.
+     */
+    static void gnssMeasurementCb(GnssData_ext* data);
+     /*
+      * Deprecated callback added for backward compatibity for devices that do
+      * not support GnssData measurements.
+      */
+    static void gpsMeasurementCb(GpsData* data);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsMeasurementCallbacks_ext sGnssMeasurementCbs;
+
+ private:
+    const GpsMeasurementInterface_ext* mGnssMeasureIface = nullptr;
+    static sp<IGnssMeasurementCallback> sGnssMeasureCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssMeasurement_H_
diff --git a/src/connectivity/gps/service/1.1/GnssNavigationMessage.cpp b/src/connectivity/gps/service/1.1/GnssNavigationMessage.cpp
new file mode 100644
index 0000000..6f509d0
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssNavigationMessage.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssNavigationMessageInterface"
+
+#include <log/log.h>
+
+#include "GnssNavigationMessage.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssNavigationMessageCallback> GnssNavigationMessage::sGnssNavigationMsgCbIface = nullptr;
+
+GpsNavigationMessageCallbacks GnssNavigationMessage::sGnssNavigationMessageCb = {
+    .size = sizeof(GpsNavigationMessageCallbacks),
+    .navigation_message_callback = nullptr,
+    .gnss_navigation_message_callback = gnssNavigationMessageCb
+};
+
+GnssNavigationMessage::GnssNavigationMessage(
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface) :
+    mGnssNavigationMessageIface(gpsNavigationMessageIface) {}
+
+void GnssNavigationMessage::gnssNavigationMessageCb(LegacyGnssNavigationMessage* message) {
+    if (sGnssNavigationMsgCbIface == nullptr) {
+        ALOGE("%s: GnssNavigation Message Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (message == nullptr) {
+        ALOGE("%s, received invalid GnssNavigationMessage from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssNavigationMessageCallback::GnssNavigationMessage navigationMsg;
+
+    navigationMsg.svid = message->svid;
+    navigationMsg.type =
+            static_cast<IGnssNavigationMessageCallback::GnssNavigationMessageType>(message->type);
+    navigationMsg.status = message->status;
+    navigationMsg.messageId = message->message_id;
+    navigationMsg.submessageId = message->submessage_id;
+    navigationMsg.data.setToExternal(message->data, message->data_length);
+
+    auto ret = sGnssNavigationMsgCbIface->gnssNavigationMessageCb(navigationMsg);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+Return<GnssNavigationMessage::GnssNavigationMessageStatus> GnssNavigationMessage::setCallback(
+        const sp<IGnssNavigationMessageCallback>& callback)  {
+    if (mGnssNavigationMessageIface == nullptr) {
+        ALOGE("%s: GnssNavigationMessage not available", __func__);
+        return GnssNavigationMessageStatus::ERROR_GENERIC;
+    }
+
+    sGnssNavigationMsgCbIface = callback;
+
+    return static_cast<GnssNavigationMessage::GnssNavigationMessageStatus>(
+            mGnssNavigationMessageIface->init(&sGnssNavigationMessageCb));
+}
+
+Return<void> GnssNavigationMessage::close()  {
+    if (mGnssNavigationMessageIface == nullptr) {
+        ALOGE("%s: GnssNavigationMessage not available", __func__);
+    } else {
+        mGnssNavigationMessageIface->close();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssNavigationMessage.h b/src/connectivity/gps/service/1.1/GnssNavigationMessage.h
new file mode 100644
index 0000000..882854b
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssNavigationMessage.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+#define android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+
+#include <android/hardware/gnss/1.0/IGnssNavigationMessage.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssNavigationMessage = ::GnssNavigationMessage;
+
+/*
+ * Extended interface for GNSS navigation message reporting support. Also contains wrapper methods
+ * to allow methods from IGnssNavigationMessageCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct GnssNavigationMessage : public IGnssNavigationMessage {
+    GnssNavigationMessage(const GpsNavigationMessageInterface* gpsNavigationMessageIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+     * These declarations were generated from IGnssNavigationMessage.hal.
+     */
+    Return<GnssNavigationMessageStatus> setCallback(
+        const sp<IGnssNavigationMessageCallback>& callback) override;
+    Return<void> close() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+     * These methods are not part of the IGnssNavigationMessage base class.
+     */
+    static void gnssNavigationMessageCb(LegacyGnssNavigationMessage* message);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsNavigationMessageCallbacks sGnssNavigationMessageCb;
+ private:
+    const GpsNavigationMessageInterface* mGnssNavigationMessageIface = nullptr;
+    static sp<IGnssNavigationMessageCallback> sGnssNavigationMsgCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssNavigationMessage_H_
diff --git a/src/connectivity/gps/service/1.1/GnssNi.cpp b/src/connectivity/gps/service/1.1/GnssNi.cpp
new file mode 100644
index 0000000..d17891d
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssNi.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssNiInterface"
+
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssNi::sThreadFuncArgsList;
+sp<IGnssNiCallback> GnssNi::sGnssNiCbIface = nullptr;
+bool GnssNi::sInterfaceExists = false;
+
+GpsNiCallbacks GnssNi::sGnssNiCb = {
+    .notify_cb = niNotifyCb,
+    .create_thread_cb = createThreadCb
+};
+
+GnssNi::GnssNi(const GpsNiInterface* gpsNiIface) : mGnssNiIface(gpsNiIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+GnssNi::~GnssNi() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+pthread_t GnssNi::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void GnssNi::niNotifyCb(GpsNiNotification* notification) {
+    if (sGnssNiCbIface == nullptr) {
+        ALOGE("%s: GNSS NI Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (notification == nullptr) {
+        ALOGE("%s: Invalid GpsNotification callback from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssNiCallback::GnssNiNotification notificationGnss = {
+        .notificationId =  notification->notification_id,
+        .niType = static_cast<IGnssNiCallback::GnssNiType>(notification->ni_type),
+        .notifyFlags = notification->notify_flags,
+        .timeoutSec = static_cast<uint32_t>(notification->timeout),
+        .defaultResponse =
+                static_cast<IGnssNiCallback::GnssUserResponseType>(notification->default_response),
+        .requestorId = notification->requestor_id,
+        .notificationMessage = notification->text,
+        .requestorIdEncoding =
+                static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->requestor_id_encoding),
+        .notificationIdEncoding =
+                static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->text_encoding)
+    };
+
+    auto ret = sGnssNiCbIface->niNotifyCb(notificationGnss);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback)  {
+    if (mGnssNiIface == nullptr) {
+       ALOGE("%s: GnssNi interface is unavailable", __func__);
+       return Void();
+    }
+
+    sGnssNiCbIface = callback;
+
+    mGnssNiIface->init(&sGnssNiCb);
+    return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse)  {
+    if (mGnssNiIface == nullptr) {
+        ALOGE("%s: GnssNi interface is unavailable", __func__);
+    } else {
+        mGnssNiIface->respond(notifId, static_cast<GpsUserResponseType>(userResponse));
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssNi.h b/src/connectivity/gps/service/1.1/GnssNi.h
new file mode 100644
index 0000000..fe850b1
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssNi.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssNi_H_
+#define android_hardware_gnss_V1_0_GnssNi_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for Network-initiated (NI) support. This interface is used to respond to
+ * NI notifications originating from the HAL. Also contains wrapper methods to allow methods from
+ * IGnssNiCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct GnssNi : public IGnssNi {
+    GnssNi(const GpsNiInterface* gpsNiIface);
+    ~GnssNi();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+     * These declarations were generated from IGnssNi.hal.
+     */
+    Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+    Return<void> respond(int32_t notifId,
+                         IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssNi base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void niNotifyCb(GpsNiNotification* notification);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsNiCallbacks sGnssNiCb;
+
+ private:
+    const GpsNiInterface* mGnssNiIface = nullptr;
+    static sp<IGnssNiCallback> sGnssNiCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssNi_H_
diff --git a/src/connectivity/gps/service/1.1/GnssUtils.cpp b/src/connectivity/gps/service/1.1/GnssUtils.cpp
new file mode 100644
index 0000000..0234aa3
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssUtils.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GnssUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using android::hardware::gnss::V1_0::GnssLocation;
+
+GnssLocation convertToGnssLocation(GpsLocation_ext* location) {
+    GnssLocation gnssLocation = {};
+    if (location != nullptr) {
+        gnssLocation = {
+            .gnssLocationFlags = static_cast<uint16_t>(location->legacyLocation.flags & 0xff),
+            .latitudeDegrees = location->legacyLocation.latitude,
+            .longitudeDegrees = location->legacyLocation.longitude,
+            .altitudeMeters = location->legacyLocation.altitude,
+            .speedMetersPerSec = location->legacyLocation.speed,
+            .bearingDegrees = location->legacyLocation.bearing,
+            .horizontalAccuracyMeters = location->horizontalAccuracyMeters,
+            .verticalAccuracyMeters = location->verticalAccuracyMeters,
+            .speedAccuracyMetersPerSecond = location->speedAccuracyMetersPerSecond,
+            .bearingAccuracyDegrees = location->bearingAccuracyDegrees,
+            .timestamp = location->legacyLocation.timestamp
+        };
+    }
+
+    return gnssLocation;
+}
+
+GnssLocation convertToGnssLocation(FlpLocation* flpLocation) {
+    GnssLocation gnssLocation = {};
+    if (flpLocation != nullptr) {
+        gnssLocation = {.gnssLocationFlags = 0,  // clear here and set below
+                        .latitudeDegrees = flpLocation->latitude,
+                        .longitudeDegrees = flpLocation->longitude,
+                        .altitudeMeters = flpLocation->altitude,
+                        .speedMetersPerSec = flpLocation->speed,
+                        .bearingDegrees = flpLocation->bearing,
+                        .horizontalAccuracyMeters = flpLocation->accuracy,
+                        .verticalAccuracyMeters = 0,
+                        .speedAccuracyMetersPerSecond = 0,
+                        .bearingAccuracyDegrees = 0,
+                        .timestamp = flpLocation->timestamp};
+        // FlpLocation flags different from GnssLocation flags
+        if (flpLocation->flags & FLP_LOCATION_HAS_LAT_LONG) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_LAT_LONG;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_ALTITUDE) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_ALTITUDE;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_SPEED) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_SPEED;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_BEARING) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_BEARING;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_ACCURACY) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+        }
+    }
+
+    return gnssLocation;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssUtils.h b/src/connectivity/gps/service/1.1/GnssUtils.h
new file mode 100644
index 0000000..7cfef2e
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssUtils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef android_hardware_gnss_V1_0_GnssUtil_H_
+#define android_hardware_gnss_V1_0_GnssUtil_H_
+
+#include <hardware/fused_location.h>
+#include <hardware/gps.h>
+#include <hardware/gps_mtk.h>
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+/*
+ * This method converts a GpsLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(GpsLocation_ext* location);
+
+/*
+ * This method converts an FlpLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(FlpLocation* location);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif
diff --git a/src/connectivity/gps/service/1.1/GnssXtra.cpp b/src/connectivity/gps/service/1.1/GnssXtra.cpp
new file mode 100644
index 0000000..d124ce1
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssXtra.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssXtraInterface"
+
+#include "GnssXtra.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssXtra::sThreadFuncArgsList;
+sp<IGnssXtraCallback> GnssXtra::sGnssXtraCbIface = nullptr;
+bool GnssXtra::sInterfaceExists = false;
+
+GpsXtraCallbacks GnssXtra::sGnssXtraCb = {
+    .download_request_cb = gnssXtraDownloadRequestCb,
+    .create_thread_cb = createThreadCb,
+};
+
+GnssXtra::~GnssXtra() {
+    sThreadFuncArgsList.clear();
+    sInterfaceExists = false;
+}
+
+pthread_t GnssXtra::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+GnssXtra::GnssXtra(const GpsXtraInterface* xtraIface) : mGnssXtraIface(xtraIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+void GnssXtra::gnssXtraDownloadRequestCb() {
+    if (sGnssXtraCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    auto ret = sGnssXtraCbIface->downloadRequestCb();
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+Return<bool> GnssXtra::setCallback(const sp<IGnssXtraCallback>& callback)  {
+    if (mGnssXtraIface == nullptr) {
+        ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+        return false;
+    }
+
+    sGnssXtraCbIface = callback;
+
+    return (mGnssXtraIface->init(&sGnssXtraCb) == 0);
+}
+
+Return<bool> GnssXtra::injectXtraData(const hidl_string& xtraData)  {
+    if (mGnssXtraIface == nullptr) {
+        ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+        return false;
+    }
+
+    char* buf = new char[xtraData.size()];
+    const char* data = xtraData.c_str();
+
+    memcpy(buf, data, xtraData.size());
+
+    int ret = mGnssXtraIface->inject_xtra_data(buf, xtraData.size());
+    delete[] buf;
+    return (ret == 0);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/src/connectivity/gps/service/1.1/GnssXtra.h b/src/connectivity/gps/service/1.1/GnssXtra.h
new file mode 100644
index 0000000..7a0733a
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/GnssXtra.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssXtra_H_
+#define android_hardware_gnss_V1_0_GnssXtra_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssXtra.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssXtra;
+using ::android::hardware::gnss::V1_0::IGnssXtraCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * This interface is used by the GNSS HAL to request the framework to download XTRA data.
+ * Also contains wrapper methods to allow methods from IGnssXtraCallback interface to be passed
+ * into the conventional implementation of the GNSS HAL.
+ */
+struct GnssXtra : public IGnssXtra {
+    GnssXtra(const GpsXtraInterface* xtraIface);
+    ~GnssXtra();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+     * These declarations were generated from IGnssXtra.hal.
+     */
+    Return<bool> setCallback(const sp<IGnssXtraCallback>& callback) override;
+    Return<bool> injectXtraData(const hidl_string& xtraData) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+     * These methods are not part of the IGnssXtra base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssXtraDownloadRequestCb();
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsXtraCallbacks sGnssXtraCb;
+
+ private:
+    const GpsXtraInterface* mGnssXtraIface = nullptr;
+    static sp<IGnssXtraCallback> sGnssXtraCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssXtra_H_
diff --git a/src/connectivity/gps/service/1.1/MtkGnss.cpp b/src/connectivity/gps/service/1.1/MtkGnss.cpp
new file mode 100644
index 0000000..f0ebcc5
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/MtkGnss.cpp
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MtkGnssHAL_GnssInterface"
+
+#include "MtkGnss.h"
+#include <GnssUtils.h>
+#include "hardware/gps_mtk.h"
+
+namespace vendor {
+namespace mediatek {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> MtkGnss::sThreadFuncArgsList;
+sp<IGnssCallback> MtkGnss::sGnssCbIface = nullptr;
+bool MtkGnss::sInterfaceExists = false;
+bool MtkGnss::sWakelockHeldGnss = false;
+bool MtkGnss::sWakelockHeldFused = false;
+
+GpsCallbacks MtkGnss::sGnssCb = {
+    .size = sizeof(GpsCallbacks),
+    .location_cb = locationCb,
+    .status_cb = statusCb,
+    .sv_status_cb = gpsSvStatusCb,
+    .nmea_cb = nmeaCb,
+    .set_capabilities_cb = setCapabilitiesCb,
+    .acquire_wakelock_cb = acquireWakelockCb,
+    .release_wakelock_cb = releaseWakelockCb,
+    .create_thread_cb = createThreadCb,
+    .request_utc_time_cb = requestUtcTimeCb,
+    .set_system_info_cb = setSystemInfoCb,
+    .gnss_sv_status_cb = gnssSvStatusCb,
+};
+
+uint32_t MtkGnss::sCapabilitiesCached = 0;
+uint16_t MtkGnss::sYearOfHwCached = 0;
+sem_t MtkGnss::sSem;
+
+
+MtkGnss::MtkGnss(gps_device_t* gnssDevice) :
+        mDeathRecipient(new GnssHidlDeathRecipient(this)) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+
+    if (gnssDevice == nullptr) {
+        ALOGE("%s: Invalid device_t handle", __func__);
+        return;
+    }
+
+    mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
+    sem_init(&sSem, 0, 1);
+}
+
+MtkGnss::~MtkGnss() {
+    sInterfaceExists = false;
+    sThreadFuncArgsList.clear();
+    sem_destroy(&sSem);
+}
+
+void MtkGnss::locationCb(GpsLocation* location) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s: Invalid location from GNSS HAL", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    android::hardware::gnss::V1_0::GnssLocation gnssLocation = convertToGnssLocation(location);
+    auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void MtkGnss::statusCb(GpsStatus* gnssStatus) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (gnssStatus == nullptr) {
+        ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssStatusValue status =
+            static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
+
+    auto ret = sGnssCbIface->gnssStatusCb(status);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void MtkGnss::gnssSvStatusCb(GnssSvStatus* status) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = status->num_svs;
+
+    if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
+        ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+        svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
+    }
+
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        auto svInfo = status->gnss_sv_list[i];
+        IGnssCallback::GnssSvInfo gnssSvInfo = {
+            .svid = svInfo.svid,
+            .constellation = static_cast<
+                android::hardware::gnss::V1_0::GnssConstellationType>(
+                svInfo.constellation),
+            .cN0Dbhz = svInfo.c_n0_dbhz,
+            .elevationDegrees = svInfo.elevation,
+            .azimuthDegrees = svInfo.azimuth,
+            // Older chipsets do not provide carrier frequency, hence
+            // HAS_CARRIER_FREQUENCY flag and the carrierFrequencyHz fields
+            // are not set. So we are resetting both fields here.
+            .svFlag = static_cast<uint8_t>(
+                svInfo.flags &= ~(static_cast<uint8_t>(
+                    IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY))),
+            .carrierFrequencyHz = 0};
+        svStatus.gnssSvList[i] = gnssSvInfo;
+    }
+
+    auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+/*
+ * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
+ * to GnssSvStatus for backward compatibility. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum SvidValues : uint16_t {
+    GLONASS_SVID_OFFSET = 64,
+    GLONASS_SVID_COUNT = 24,
+    BEIDOU_SVID_OFFSET = 200,
+    BEIDOU_SVID_COUNT = 35,
+    SBAS_SVID_MIN = 33,
+    SBAS_SVID_MAX = 64,
+    SBAS_SVID_ADD = 87,
+    QZSS_SVID_MIN = 193,
+    QZSS_SVID_MAX = 200
+};
+
+/*
+ * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
+ * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
+ * being deprecated and is no longer part of the GNSS interface.
+ */
+void MtkGnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (svInfo == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = svInfo->num_svs;
+    /*
+     * Clamp the list size since GnssSvStatus can support a maximum of
+     * GnssMax::SVS_COUNT entries.
+     */
+    ///M: fix max numSvs as GPS_MAX_SVS
+    if (svStatus.numSvs > static_cast<uint32_t>(GPS_MAX_SVS)) {
+        ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GPS_MAX_SVS);
+        svStatus.numSvs = static_cast<uint32_t>(GPS_MAX_SVS);
+    }
+    /// M: mtk update end
+
+    uint32_t ephemerisMask = svInfo->ephemeris_mask;
+    uint32_t almanacMask = svInfo->almanac_mask;
+    uint32_t usedInFixMask = svInfo->used_in_fix_mask;
+    /*
+     * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
+     */
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
+        info.svid = svInfo->sv_list[i].prn;
+        if (info.svid >= 1 && info.svid <= 32) {
+            /// Mtk added to specify namespace
+            info.constellation = android::hardware::gnss::V1_0::GnssConstellationType::GPS;
+        } else if (info.svid > GLONASS_SVID_OFFSET &&
+                   info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
+            /// Mtk added to specify namespace
+            info.constellation = android::hardware::gnss::V1_0::GnssConstellationType::GLONASS;
+            info.svid -= GLONASS_SVID_OFFSET;
+        } else if (info.svid > BEIDOU_SVID_OFFSET &&
+                 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
+            /// Mtk added to specify namespace
+            info.constellation = android::hardware::gnss::V1_0::GnssConstellationType::BEIDOU;
+            info.svid -= BEIDOU_SVID_OFFSET;
+        } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
+            /// Mtk added to specify namespace
+            info.constellation = android::hardware::gnss::V1_0::GnssConstellationType::SBAS;
+            info.svid += SBAS_SVID_ADD;
+        } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
+            /// Mtk added to specify namespace
+            info.constellation = android::hardware::gnss::V1_0::GnssConstellationType::QZSS;
+        } else {
+            ALOGD("Unknown constellation type with Svid = %d.", info.svid);
+            /// Mtk added to specify namespace
+            info.constellation = android::hardware::gnss::V1_0::GnssConstellationType::UNKNOWN;
+        }
+
+        info.cN0Dbhz = svInfo->sv_list[i].snr;
+        info.elevationDegrees = svInfo->sv_list[i].elevation;
+        info.azimuthDegrees = svInfo->sv_list[i].azimuth;
+        // TODO: b/31702236
+        info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+
+        /*
+         * Only GPS info is valid for these fields, as these masks are just 32
+         * bits, by GPS prn.
+         */
+        /// Mtk added to specify namespace
+        if (info.constellation == android::hardware::gnss::V1_0::GnssConstellationType::GPS) {
+            int32_t svidMask = (1 << (info.svid - 1));
+            if ((ephemerisMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+            }
+            if ((almanacMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+            }
+            if ((usedInFixMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+            }
+        }
+    }
+
+    auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void MtkGnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    android::hardware::hidl_string nmeaString;
+    nmeaString.setToExternal(nmea, length);
+    auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+void MtkGnss::setCapabilitiesCb(uint32_t capabilities) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sCapabilitiesCached = capabilities;
+    sem_post(&sSem);
+}
+
+void MtkGnss::acquireWakelockCb() {
+    acquireWakelockGnss();
+}
+
+void MtkGnss::releaseWakelockCb() {
+    releaseWakelockGnss();
+}
+
+
+void MtkGnss::acquireWakelockGnss() {
+    sWakelockHeldGnss = true;
+    updateWakelock();
+}
+
+void MtkGnss::releaseWakelockGnss() {
+    sWakelockHeldGnss = false;
+    updateWakelock();
+}
+
+void MtkGnss::acquireWakelockFused() {
+    sWakelockHeldFused = true;
+    updateWakelock();
+}
+
+void MtkGnss::releaseWakelockFused() {
+    sWakelockHeldFused = false;
+    updateWakelock();
+}
+
+void MtkGnss::updateWakelock() {
+    // Track the state of the last request - in case the wake lock in the layer above is reference
+    // counted.
+    static bool sWakelockHeld = false;
+
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (sWakelockHeldGnss || sWakelockHeldFused) {
+        if (!sWakelockHeld) {
+            ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
+                    sWakelockHeldGnss, sWakelockHeldFused);
+            sWakelockHeld = true;
+            auto ret = sGnssCbIface->gnssAcquireWakelockCb();
+            if (!ret.isOk()) {
+                ALOGE("%s: Unable to invoke callback", __func__);
+            }
+        }
+    } else {
+        if (sWakelockHeld) {
+            ALOGI("%s: GNSS HAL Wakelock released", __func__);
+        } else  {
+            // To avoid burning power, always release, even if logic got here with sWakelock false
+            // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
+            ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
+        }
+        sWakelockHeld = false;
+        auto ret = sGnssCbIface->gnssReleaseWakelockCb();
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+        }
+    }
+    sem_post(&sSem);
+}
+
+void MtkGnss::requestUtcTimeCb() {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    auto ret = sGnssCbIface->gnssRequestTimeCb();
+    if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    sem_post(&sSem);
+}
+
+pthread_t MtkGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void MtkGnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
+    sem_wait(&sSem);
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    if (info == nullptr) {
+        ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
+        sem_post(&sSem);
+        return;
+    }
+
+    IGnssCallback::GnssSystemInfo gnssInfo = {
+        .yearOfHw = info->year_of_hw
+    };
+
+    auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sYearOfHwCached = info->year_of_hw;
+    sem_post(&sSem);
+}
+
+
+// Methods from ::android::hardware::MtkGnss::V1_0::IGnss follow.
+Return<bool> MtkGnss::setCallback(const sp<IGnssCallback>& callback)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    if (callback == nullptr)  {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sem_wait(&sSem);
+    if (sGnssCbIface != NULL) {
+        ALOGW("%s called more than once. Unexpected unless test.", __func__);
+        sGnssCbIface->unlinkToDeath(mDeathRecipient);
+    }
+
+    sGnssCbIface = callback;
+    callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
+    sem_post(&sSem);
+
+    // If this was received in the past, send it up again to refresh caller.
+    // mGnssIface will override after init() is called below, if needed
+    // (though it's unlikely the gps.h capabilities or system info will change.)
+    if (sCapabilitiesCached != 0) {
+        setCapabilitiesCb(sCapabilitiesCached);
+    }
+    if (sYearOfHwCached != 0) {
+        LegacyGnssSystemInfo info;
+        info.year_of_hw = sYearOfHwCached;
+        setSystemInfoCb(&info);
+    }
+
+    return (mGnssIface->init(&sGnssCb) == 0);
+}
+
+Return<bool> MtkGnss::start()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->start() == 0);
+}
+
+Return<bool> MtkGnss::stop()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->stop() == 0);
+}
+
+Return<void> MtkGnss::cleanup()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->cleanup();
+    }
+    return Void();
+}
+
+Return<bool> MtkGnss::injectLocation(double latitudeDegrees,
+                                  double longitudeDegrees,
+                                  float accuracyMeters)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
+}
+
+Return<bool> MtkGnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                              int32_t uncertaintyMs) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
+}
+
+Return<void> MtkGnss::deleteAidingData(IMtkGnss::GnssAidingData aidingDataFlags)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
+    }
+    return Void();
+}
+
+Return<bool> MtkGnss::setPositionMode(IMtkGnss::GnssPositionMode mode,
+                                   IMtkGnss::GnssPositionRecurrence recurrence,
+                                   uint32_t minIntervalMs,
+                                   uint32_t preferredAccuracyMeters,
+                                   uint32_t preferredTimeMs)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
+                                          static_cast<GpsPositionRecurrence>(recurrence),
+                                          minIntervalMs,
+                                          preferredAccuracyMeters,
+                                          preferredTimeMs) == 0);
+}
+
+Return<sp<IAGnssRil>> MtkGnss::getExtensionAGnssRil()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssRil == nullptr) {
+        const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
+                mGnssIface->get_extension(AGPS_RIL_INTERFACE));
+        if (agpsRilIface == nullptr) {
+            ALOGE("%s GnssRil interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssRil = new AGnssRil(agpsRilIface);
+        }
+    }
+    return mGnssRil;
+}
+
+Return<sp<IGnssConfiguration>> MtkGnss::getExtensionGnssConfiguration()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssConfig == nullptr) {
+        const GnssConfigurationInterface* gnssConfigIface =
+                static_cast<const GnssConfigurationInterface*>(
+                        mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
+
+        if (gnssConfigIface == nullptr) {
+            ALOGW("%s GnssConfiguration interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssConfig = new GnssConfiguration(gnssConfigIface);
+        }
+    }
+    return mGnssConfig;
+}
+
+Return<sp<IGnssGeofencing>> MtkGnss::getExtensionGnssGeofencing()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssGeofencingIface == nullptr) {
+        const GpsGeofencingInterface* gpsGeofencingIface =
+                static_cast<const GpsGeofencingInterface*>(
+                        mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
+
+        if (gpsGeofencingIface == nullptr) {
+            ALOGE("%s GnssGeofencing interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
+        }
+    }
+
+    return mGnssGeofencingIface;
+}
+
+Return<sp<IAGnss>> MtkGnss::getExtensionAGnss()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mAGnssIface == nullptr) {
+        const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
+                mGnssIface->get_extension(AGPS_INTERFACE));
+        if (agpsIface == nullptr) {
+            ALOGE("%s AGnss interface not implemented by GNSS HAL", __func__);
+        } else {
+            mAGnssIface = new AGnss(agpsIface);
+        }
+    }
+    return mAGnssIface;
+}
+
+Return<sp<IGnssNi>> MtkGnss::getExtensionGnssNi()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssNi == nullptr) {
+        const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
+                mGnssIface->get_extension(GPS_NI_INTERFACE));
+        if (gpsNiIface == nullptr) {
+            ALOGE("%s GnssNi interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssNi = new GnssNi(gpsNiIface);
+        }
+    }
+    return mGnssNi;
+}
+
+Return<sp<IGnssMeasurement>> MtkGnss::getExtensionGnssMeasurement() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssMeasurement == nullptr) {
+        const GpsMeasurementInterface* gpsMeasurementIface =
+                static_cast<const GpsMeasurementInterface*>(
+                        mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
+
+        if (gpsMeasurementIface == nullptr) {
+            ALOGE("%s GnssMeasurement interface not implemented by GNSS HAL", __func__);
+        } else {
+            /// Mtk added to specify namespace
+            mGnssMeasurement = new implementation::GnssMeasurement(gpsMeasurementIface);
+        }
+    }
+    return mGnssMeasurement;
+}
+
+Return<sp<IGnssNavigationMessage>> MtkGnss::getExtensionGnssNavigationMessage() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssNavigationMessage == nullptr) {
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface =
+                static_cast<const GpsNavigationMessageInterface*>(
+                        mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
+
+        if (gpsNavigationMessageIface == nullptr) {
+            ALOGE("%s GnssNavigationMessage interface not implemented by GNSS HAL",
+                  __func__);
+        } else {
+            /// Mtk added to specify namespace
+            mGnssNavigationMessage = new implementation::GnssNavigationMessage(gpsNavigationMessageIface);
+        }
+    }
+
+    return mGnssNavigationMessage;
+}
+
+Return<sp<IGnssXtra>> MtkGnss::getExtensionXtra()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssXtraIface == nullptr) {
+        const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
+                mGnssIface->get_extension(GPS_XTRA_INTERFACE));
+
+        if (gpsXtraIface == nullptr) {
+            ALOGW("%s GnssXtra interface not implemented by HAL", __func__);
+        } else {
+            mGnssXtraIface = new GnssXtra(gpsXtraIface);
+        }
+    }
+
+    return mGnssXtraIface;
+}
+
+Return<sp<IGnssDebug>> MtkGnss::getExtensionGnssDebug()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssDebug == nullptr) {
+        const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
+                mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
+
+        if (gpsDebugIface == nullptr) {
+            ALOGW("%s: GnssDebug interface is not implemented by HAL", __func__);
+        } else {
+            mGnssDebug = new GnssDebug(gpsDebugIface);
+        }
+    }
+
+    return mGnssDebug;
+}
+
+Return<sp<IGnssBatching>> MtkGnss::getExtensionGnssBatching()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mGnssBatching == nullptr) {
+        hw_module_t* module;
+        const FlpLocationInterface* flpLocationIface = nullptr;
+        int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+        if (err != 0) {
+            ALOGE("gnss flp hw_get_module failed: %d", err);
+        } else if (module == nullptr) {
+            ALOGE("Fused Location hw_get_module returned null module");
+        } else if (module->methods == nullptr) {
+            ALOGE("Fused Location hw_get_module returned null methods");
+        } else {
+            hw_device_t* device;
+            err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
+            if (err != 0) {
+                ALOGE("flpDevice open failed: %d", err);
+            } else {
+                flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
+                flpLocationIface = flpDevice->get_flp_interface(flpDevice);
+            }
+        }
+
+        if (flpLocationIface == nullptr) {
+            ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
+        } else {
+            mGnssBatching = new GnssBatching(flpLocationIface);
+        }
+    }
+    return mGnssBatching;
+}
+
+void MtkGnss::handleHidlDeath() {
+    ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
+
+    /// M: move here! Do not callback to system_server to avoid gnss hidl service NE
+    /*
+     * This has died, so close it off in case (race condition) callbacks happen
+     * before HAL processes above messages.
+     */
+    sem_wait(&sSem);
+    sGnssCbIface = nullptr;
+    sem_post(&sSem);
+
+    // commands down to the HAL implementation
+    stop(); // stop ongoing GPS tracking
+    if (mGnssMeasurement != nullptr) {
+        mGnssMeasurement->close();
+    }
+    if (mGnssNavigationMessage != nullptr) {
+        mGnssNavigationMessage->close();
+    }
+    if (mGnssBatching != nullptr) {
+        mGnssBatching->stop();
+        mGnssBatching->cleanup();
+    }
+    cleanup();
+
+}
+
+
+Return<sp<IVzwDebug>> MtkGnss::getExtensionVzwDebug()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return nullptr;
+    }
+
+    if (mVzwDebug == nullptr) {
+        const VzwDebugInterface* vzwDebugIface = static_cast<const VzwDebugInterface*>(
+                mGnssIface->get_extension(VZW_DEBUG_INTERFACE));
+
+        if (vzwDebugIface == nullptr) {
+            ALOGE("%s: VzwDebug interface is not implemented by HAL", __func__);
+        } else {
+            mVzwDebug = new VzwDebug(vzwDebugIface);
+        }
+    }
+
+    return mVzwDebug;
+}
+
+
+IMtkGnss* HIDL_FETCH_IMtkGnss(const char* /* hal */) {
+    hw_module_t* module;
+    IMtkGnss* iface = nullptr;
+    int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+    if (err == 0) {
+        hw_device_t* device;
+        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            iface = new MtkGnss(reinterpret_cast<gps_device_t*>(device));
+        } else {
+            ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+        }
+    } else {
+      ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+    }
+    return iface;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace mediatek
+}  // namespace vendor
diff --git a/src/connectivity/gps/service/1.1/MtkGnss.h b/src/connectivity/gps/service/1.1/MtkGnss.h
new file mode 100644
index 0000000..bc211b4
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/MtkGnss.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VENDOR_MEDIATEK_HARDWARE_GNSS_V1_1_MTKGNSS_H
+#define VENDOR_MEDIATEK_HARDWARE_GNSS_V1_1_MTKGNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssDebug.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNavigationMessage.h>
+#include <GnssNi.h>
+#include <GnssXtra.h>
+
+#include <ThreadCreationWrapper.h>
+//#include <android/hardware/gnss/1.0/IGnss.h>
+#include <vendor/mediatek/hardware/gnss/1.1/IMtkGnss.h>
+#include <hardware/fused_location.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+#include <VzwDebug.h>
+#include <semaphore.h>
+
+namespace vendor {
+namespace mediatek {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+/// Mtk added to include more namespaces
+using namespace android::hardware::gnss::V1_0;
+using namespace android::hardware::gnss::V1_0::implementation;
+using ::vendor::mediatek::hardware::gnss::V1_1::IMtkGnss;
+using ::vendor::mediatek::hardware::gnss::V1_1::IVzwDebug;
+using ::android::wp;
+/// Mtk add end
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssSystemInfo = ::GnssSystemInfo;
+
+/*
+ * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
+ * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+class MtkGnss : public IMtkGnss {
+  public:
+    MtkGnss(gps_device_t* gnss_device);
+    ~MtkGnss();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+     * These declarations were generated from Gnss.hal.
+     */
+    Return<bool> setCallback(const sp<IGnssCallback>& callback)  override;
+    Return<bool> start()  override;
+    Return<bool> stop()  override;
+    Return<void> cleanup()  override;
+    Return<bool> injectLocation(double latitudeDegrees,
+                                double longitudeDegrees,
+                                float accuracyMeters)  override;
+    Return<bool> injectTime(int64_t timeMs,
+                            int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<void> deleteAidingData(IGnss::GnssAidingData aidingDataFlags)  override;
+    Return<bool> setPositionMode(IGnss::GnssPositionMode mode,
+                                 IGnss::GnssPositionRecurrence recurrence,
+                                 uint32_t minIntervalMs,
+                                 uint32_t preferredAccuracyMeters,
+                                 uint32_t preferredTimeMs)  override;
+    Return<sp<IAGnssRil>> getExtensionAGnssRil() override;
+    Return<sp<IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<IAGnss>> getExtensionAGnss() override;
+    Return<sp<IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+    Return<sp<IGnssXtra>> getExtensionXtra() override;
+    Return<sp<IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<IGnssDebug>> getExtensionGnssDebug() override;
+    Return<sp<IGnssBatching>> getExtensionGnssBatching() override;
+    ///M: add to get and wrap hal vzw debug interface
+    Return<sp<IVzwDebug>> getExtensionVzwDebug() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnss base class.
+     */
+    static void locationCb(GpsLocation* location);
+    static void statusCb(GpsStatus* gnss_status);
+    static void nmeaCb(GpsUtcTime timestamp, const char* nmea, int length);
+    static void setCapabilitiesCb(uint32_t capabilities);
+    static void acquireWakelockCb();
+    static void releaseWakelockCb();
+    static void requestUtcTimeCb();
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssSvStatusCb(GnssSvStatus* status);
+    /*
+     * Deprecated callback added for backward compatibility to devices that do
+     * not support GnssSvStatus.
+     */
+    static void gpsSvStatusCb(GpsSvStatus* status);
+    static void setSystemInfoCb(const LegacyGnssSystemInfo* info);
+
+    /*
+     * Wakelock consolidation, only needed for dual use of a gps.h & fused_location.h HAL
+     *
+     * Ensures that if the last call from either legacy .h was to acquire a wakelock, that a
+     * wakelock is held.  Otherwise releases it.
+     */
+    static void acquireWakelockFused();
+    static void releaseWakelockFused();
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsCallbacks sGnssCb;
+
+ private:
+    /*
+     * For handling system-server death while GNSS service lives on.
+     */
+    class GnssHidlDeathRecipient : public hidl_death_recipient {
+      public:
+        GnssHidlDeathRecipient(const sp<MtkGnss> gnss) : mGnss(gnss) {
+        }
+
+        virtual void serviceDied(uint64_t /*cookie*/,
+                const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+            mGnss->handleHidlDeath();
+        }
+      private:
+        sp<MtkGnss> mGnss;
+    };
+
+    // for wakelock consolidation, see above
+    static void acquireWakelockGnss();
+    static void releaseWakelockGnss();
+    static void updateWakelock();
+    static bool sWakelockHeldGnss;
+    static bool sWakelockHeldFused;
+
+    /*
+     * Cleanup for death notification
+     */
+    void handleHidlDeath();
+
+    sp<GnssXtra> mGnssXtraIface = nullptr;
+    sp<AGnssRil> mGnssRil = nullptr;
+    sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+    sp<AGnss> mAGnssIface = nullptr;
+    sp<GnssNi> mGnssNi = nullptr;
+    /// Mtk added to specify namespace
+    sp<implementation::GnssMeasurement> mGnssMeasurement = nullptr;
+    sp<implementation::GnssNavigationMessage> mGnssNavigationMessage = nullptr;
+    /// Mtk add end
+    sp<GnssDebug> mGnssDebug = nullptr;
+    sp<GnssConfiguration> mGnssConfig = nullptr;
+    sp<GnssBatching> mGnssBatching = nullptr;
+
+    ///M: add for vzw debug hidl imlementation instance
+    sp<VzwDebug> mVzwDebug = nullptr;
+    static sem_t sSem;
+
+    sp<GnssHidlDeathRecipient> mDeathRecipient;
+
+    const GpsInterface* mGnssIface = nullptr;
+    static sp<IGnssCallback> sGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+
+    // Values saved for resend
+    static uint32_t sCapabilitiesCached;
+    static uint16_t sYearOfHwCached;
+};
+
+extern "C" IMtkGnss* HIDL_FETCH_IMtkGnss(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace mediatek
+}  // namespace vendor
+
+#endif  // VENDOR_MEDIATEK_HARDWARE_GNSS_V1_1_MTKGNSS_H
diff --git a/src/connectivity/gps/service/1.1/NOTICE b/src/connectivity/gps/service/1.1/NOTICE
new file mode 100644
index 0000000..bf532e5
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/NOTICE
@@ -0,0 +1,182 @@
+
+Copyright (C) 2016 The Android Open Source Project
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
diff --git a/src/connectivity/gps/service/1.1/OWNERS b/src/connectivity/gps/service/1.1/OWNERS
new file mode 100644
index 0000000..6c25bd7
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/OWNERS
@@ -0,0 +1,3 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
diff --git a/src/connectivity/gps/service/1.1/ThreadCreationWrapper.cpp b/src/connectivity/gps/service/1.1/ThreadCreationWrapper.cpp
new file mode 100644
index 0000000..2a5638f
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/ThreadCreationWrapper.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ThreadCreationWrapper.h>
+
+void* threadFunc(void* arg) {
+    ThreadFuncArgs* threadArgs = reinterpret_cast<ThreadFuncArgs*>(arg);
+    threadArgs->fptr(threadArgs->args);
+    return nullptr;
+}
+
+pthread_t createPthread(const char* name,
+                        void (*start)(void*),
+                        void* arg, std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs) {
+    pthread_t threadId;
+    auto threadArgs = new ThreadFuncArgs(start, arg);
+    auto argPtr = std::unique_ptr<ThreadFuncArgs>(threadArgs);
+
+    listArgs->push_back(std::move(argPtr));
+
+    int ret = pthread_create(&threadId, nullptr, threadFunc, reinterpret_cast<void*>(
+            threadArgs));
+    if (ret != 0) {
+        ALOGE("pthread creation unsuccessful");
+    } else {
+        pthread_setname_np(threadId, name);
+    }
+    return threadId;
+}
diff --git a/src/connectivity/gps/service/1.1/ThreadCreationWrapper.h b/src/connectivity/gps/service/1.1/ThreadCreationWrapper.h
new file mode 100644
index 0000000..99c8670
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/ThreadCreationWrapper.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+#define ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+
+#include <pthread.h>
+#include <vector>
+#include <log/log.h>
+
+typedef void (*threadEntryFunc)(void* ret);
+
+/*
+ * This class facilitates createThreadCb methods in various GNSS interfaces to wrap
+ * pthread_create() from libc since its function signature differs from what is required by the
+ * conventional GNSS HAL. The arguments passed to pthread_create() need to be on heap and not on
+ * the stack of createThreadCb.
+ */
+struct ThreadFuncArgs {
+    ThreadFuncArgs(void (*start)(void*), void* arg) : fptr(start), args(arg) {}
+
+    /* pointer to the function of type void()(void*) that needs to be wrapped */
+    threadEntryFunc fptr;
+    /* argument for fptr to be called with */
+    void* args;
+};
+
+/*
+ * This method is simply a wrapper. It is required since pthread_create() requires an entry
+ * function pointer of type void*()(void*) and the GNSS hal requires as input a function pointer of
+ * type void()(void*).
+ */
+void* threadFunc(void* arg);
+
+/*
+ * This method is called by createThreadCb with a pointer to the vector that
+ * holds the pointers to the thread arguments. The arg and start parameters are
+ * first used to create a ThreadFuncArgs object which is then saved in the
+ * listArgs parameters. The created ThreadFuncArgs object is then used to invoke
+ * threadFunc() method which in-turn invokes pthread_create.
+ */
+pthread_t createPthread(const char* name, void (*start)(void*), void* arg,
+                        std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs);
+
+#endif
diff --git a/src/connectivity/gps/service/1.1/VzwDebug.cpp b/src/connectivity/gps/service/1.1/VzwDebug.cpp
new file mode 100644
index 0000000..24ae0c2
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/VzwDebug.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VzwDebugInterface"
+
+#include <log/log.h>
+
+#include "VzwDebug.h"
+
+namespace vendor {
+namespace mediatek {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+sp<IVzwDebugCallback> VzwDebug::sVzwDebugCbIface = nullptr;
+VzwDebugCallbacks VzwDebug::sHalVzwDeubgCb = {
+    .vzw_debug_cb = vzwDebugMessageCb,
+};
+
+
+VzwDebug::VzwDebug(const VzwDebugInterface* vzwDebugIface) : mHalVzwDebugIface(vzwDebugIface) {}
+
+
+// Methods from ::vendor::mediatek::hardware::gnss::V1_1::IVzwDebug follow.
+Return<bool> VzwDebug::init(const sp<IVzwDebugCallback>& callback)  {
+    ALOGE("%s: Vzw debug init, to set callback", __func__);
+    if (mHalVzwDebugIface == nullptr) {
+        ALOGE("%s: Vzw debug HAL interface is unavailable", __func__);
+        return false;
+    }
+
+    sVzwDebugCbIface = callback;
+
+    return (mHalVzwDebugIface->init(&sHalVzwDeubgCb) == 0);
+}
+
+
+void VzwDebug::vzwDebugMessageCb(VzwDebugData* vzw_message) {
+    if (sVzwDebugCbIface == nullptr) {
+        ALOGE("%s: Vzw Debug Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    IVzwDebugCallback::VzwDebugData* pMsg = new IVzwDebugCallback::VzwDebugData();
+    pMsg->size = strlen(vzw_message->vzw_msg_data);
+    if (pMsg->size >= VZW_DEBUG_STRING_MAXLEN) {
+        pMsg->size = VZW_DEBUG_STRING_MAXLEN - 1;
+    }
+
+    uint8_t *dst = reinterpret_cast<uint8_t *>(&pMsg->vzw_msg_data[0]);
+    const uint8_t *src = reinterpret_cast<uint8_t *>(&vzw_message->vzw_msg_data[0]);
+    memcpy(dst, src, pMsg->size + 1);
+
+    auto ret = sVzwDebugCbIface->vzwDebugCb(*pMsg);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+    delete pMsg;
+}
+
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+Return<void> VzwDebug::setVzwDebugScreen(bool enabled)  {
+    if (mHalVzwDebugIface == nullptr) {
+        ALOGE("%s: Vzw debug HAL interface is unavailable", __func__);
+        return Void();
+    }
+
+    mHalVzwDebugIface->set_vzw_debug_screen(enabled);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace mediatek
+}  // namespace vendor
diff --git a/src/connectivity/gps/service/1.1/VzwDebug.h b/src/connectivity/gps/service/1.1/VzwDebug.h
new file mode 100644
index 0000000..3a87081
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/VzwDebug.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VENDOR_MEDIATEK_HARDWARE_GNSS_V1_1_VZWDEBUG_H
+#define VENDOR_MEDIATEK_HARDWARE_GNSS_V1_1_VZWDEBUG_H
+
+#include <vendor/mediatek/hardware/gnss/1.1/IVzwDebug.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <hardware/gps_mtk.h>
+
+namespace vendor {
+namespace mediatek {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using ::vendor::mediatek::hardware::gnss::V1_1::IVzwDebug;
+using ::vendor::mediatek::hardware::gnss::V1_1::IVzwDebugCallback;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct VzwDebug : public IVzwDebug {
+    VzwDebug(const VzwDebugInterface* vzwDebugIface);
+
+    // Methods from ::vendor::mediatek::hardware::gnss::V1_1::IVzwDebug follow.
+    Return<bool> init(const sp<IVzwDebugCallback>& callback) override;
+    Return<void> setVzwDebugScreen(bool enabled) override;
+
+    static void vzwDebugMessageCb(VzwDebugData* vzw_message);
+
+    static VzwDebugCallbacks sHalVzwDeubgCb;           // local call back function
+
+ private:
+    const VzwDebugInterface* mHalVzwDebugIface = nullptr;   // HAL interface pointer
+    static sp<IVzwDebugCallback> sVzwDebugCbIface;   // framework JNI callback interface
+
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace mediatek
+}  // namespace vendor
+
+#endif  // VENDOR_MEDIATEK_HARDWARE_GNSS_V1_1_VZWDEBUG_H
diff --git a/src/connectivity/gps/service/1.1/android.hardware.gnss@1.1-service-mediatek.rc b/src/connectivity/gps/service/1.1/android.hardware.gnss@1.1-service-mediatek.rc
new file mode 100644
index 0000000..6486b6e
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/android.hardware.gnss@1.1-service-mediatek.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@1.1-service-mediatek
+    class hal
+    user system
+    group system gps
diff --git a/src/connectivity/gps/service/1.1/hardware/gps_mtk.h b/src/connectivity/gps/service/1.1/hardware/gps_mtk.h
new file mode 100644
index 0000000..b32199e
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/hardware/gps_mtk.h
@@ -0,0 +1,682 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+#define ANDROID_INCLUDE_HARDWARE_GPS_MTK_H
+
+#include <hardware/gps_internal.h>
+
+__BEGIN_DECLS
+
+// MTK extended GpsAidingData values.
+#define GPS_DELETE_HOT_STILL 0x2000
+#define GPS_DELETE_EPO      0x4000
+
+// ====================vzw debug screen API =================
+/**
+ * Name for the VZW debug interface.
+ */
+#define VZW_DEBUG_INTERFACE      "vzw-debug"
+
+#define VZW_DEBUG_STRING_MAXLEN      200
+
+/** Represents data of VzwDebugData. */
+typedef struct {
+    /** set to sizeof(VzwDebugData) */
+    size_t size;
+
+    char  vzw_msg_data[VZW_DEBUG_STRING_MAXLEN];
+} VzwDebugData;
+
+
+typedef void (* vzw_debug_callback)(VzwDebugData* vzw_message);
+
+/** Callback structure for the Vzw debug interface. */
+typedef struct {
+    vzw_debug_callback vzw_debug_cb;
+} VzwDebugCallbacks;
+
+
+/** Extended interface for VZW DEBUG support. */
+typedef struct {
+    /** set to sizeof(VzwDebugInterface) */
+    size_t          size;
+
+    /** Registers the callbacks for Vzw debug message. */
+    int  (*init)( VzwDebugCallbacks* callbacks );
+
+    /** Set Vzw debug screen enable/disable **/
+    void (*set_vzw_debug_screen)(bool enabled);
+} VzwDebugInterface;
+
+////////////////////// GNSS HIDL v1.0 ////////////////////////////
+
+/** Represents a location. */
+typedef struct {
+    GpsLocation legacyLocation;
+    /**
+    * Represents expected horizontal position accuracy, radial, in meters
+    * (68% confidence).
+    */
+    float           horizontalAccuracyMeters;
+
+    /**
+    * Represents expected vertical position accuracy in meters
+    * (68% confidence).
+    */
+    float           verticalAccuracyMeters;
+
+    /**
+    * Represents expected speed accuracy in meter per seconds
+    * (68% confidence).
+    */
+    float           speedAccuracyMetersPerSecond;
+
+    /**
+    * Represents expected bearing accuracy in degrees
+    * (68% confidence).
+    */
+    float           bearingAccuracyDegrees;
+
+} GpsLocation_ext;
+
+
+typedef struct {
+    GnssSvInfo legacySvInfo;
+
+    /// v1.0 ///
+    float carrier_frequency;
+
+} GnssSvInfo_ext;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+    /** set to sizeof(GnssSvStatus) */
+    size_t size;
+
+    /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+    int num_svs;
+    /**
+     * Pointer to an array of SVs information for all GNSS constellations,
+     * except GPS, which is reported using sv_list
+     */
+    GnssSvInfo_ext gnss_sv_list[GNSS_MAX_SVS];
+
+} GnssSvStatus_ext;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* gps_location_ext_callback)(GpsLocation_ext* location);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* gnss_sv_status_ext_callback)(GnssSvStatus_ext* sv_info);
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ *      geofence_id - The id associated with the add_geofence_area.
+ *      location    - The current GPS location.
+ *      transition  - Can be one of GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED,
+ *                    GPS_GEOFENCE_UNCERTAIN.
+ *      timestamp   - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*gps_geofence_transition_ext_callback) (int32_t geofence_id,
+        GpsLocation_ext* location, int32_t transition, GpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ *  status - GPS_GEOFENCE_UNAVAILABLE or GPS_GEOFENCE_AVAILABLE.
+ *  last_location - Last known location.
+ */
+typedef void (*gps_geofence_status_ext_callback) (int32_t status,
+        GpsLocation_ext* last_location);
+
+typedef struct {
+    gps_geofence_transition_ext_callback geofence_transition_callback;
+    gps_geofence_status_ext_callback geofence_status_callback;
+    gps_geofence_add_callback geofence_add_callback;
+    gps_geofence_remove_callback geofence_remove_callback;
+    gps_geofence_pause_callback geofence_pause_callback;
+    gps_geofence_resume_callback geofence_resume_callback;
+    gps_create_thread create_thread_cb;
+} GpsGeofenceCallbacks_ext;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+   /** set to sizeof(GpsGeofencingInterface) */
+   size_t          size;
+
+   /**
+    * Opens the geofence interface and provides the callback routines
+    * to the implementation of this interface.
+    */
+   void  (*init)( GpsGeofenceCallbacks_ext* callbacks );
+
+   /**
+    * Add a geofence area. This api currently supports circular geofences.
+    * Parameters:
+    *    geofence_id - The id for the geofence. If a geofence with this id
+    *       already exists, an error value (GPS_GEOFENCE_ERROR_ID_EXISTS)
+    *       should be returned.
+    *    latitude, longtitude, radius_meters - The lat, long and radius
+    *       (in meters) for the geofence
+    *    last_transition - The current state of the geofence. For example, if
+    *       the system already knows that the user is inside the geofence,
+    *       this will be set to GPS_GEOFENCE_ENTERED. In most cases, it
+    *       will be GPS_GEOFENCE_UNCERTAIN.
+    *    monitor_transition - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *    notification_responsiveness_ms - Defines the best-effort description
+    *       of how soon should the callback be called when the transition
+    *       associated with the Geofence is triggered. For instance, if set
+    *       to 1000 millseconds with GPS_GEOFENCE_ENTERED, the callback
+    *       should be called 1000 milliseconds within entering the geofence.
+    *       This parameter is defined in milliseconds.
+    *       NOTE: This is not to be confused with the rate that the GPS is
+    *       polled at. It is acceptable to dynamically vary the rate of
+    *       sampling the GPS for power-saving reasons; thus the rate of
+    *       sampling may be faster or slower than this.
+    *    unknown_timer_ms - The time limit after which the UNCERTAIN transition
+    *       should be triggered. This parameter is defined in milliseconds.
+    *       See above for a detailed explanation.
+    */
+   void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+       double radius_meters, int last_transition, int monitor_transitions,
+       int notification_responsiveness_ms, int unknown_timer_ms);
+
+   /**
+    * Pause monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*pause_geofence) (int32_t geofence_id);
+
+   /**
+    * Resume monitoring a particular geofence.
+    * Parameters:
+    *   geofence_id - The id for the geofence.
+    *   monitor_transitions - Which transitions to monitor. Bitwise OR of
+    *       GPS_GEOFENCE_ENTERED, GPS_GEOFENCE_EXITED and
+    *       GPS_GEOFENCE_UNCERTAIN.
+    *       This supersedes the value associated provided in the
+    *       add_geofence_area call.
+    */
+   void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+   /**
+    * Remove a geofence area. After the function returns, no notifications
+    * should be sent.
+    * Parameter:
+    *   geofence_id - The id for the geofence.
+    */
+   void (*remove_geofence_area) (int32_t geofence_id);
+} GpsGeofencingInterface_ext;
+
+typedef struct {
+    GnssMeasurement legacyMeasurement;
+
+    /**
+     * Automatic gain control (AGC) level. AGC acts as a variable gain
+     * amplifier adjusting the power of the incoming signal. The AGC level
+     * may be used to indicate potential interference. When AGC is at a
+     * nominal level, this value must be set as 0. Higher gain (and/or lower
+     * input power) must be output as a positive number. Hence in cases of
+     * strong jamming, in the band of this signal, this value must go more
+     * negative.
+     *
+     * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+     * other RF HW components) may also affect the typical output of of this
+     * value on any given hardware design in an open sky test - the
+     * important aspect of this output is that changes in this value are
+     * indicative of changes on input signal power in the frequency band for
+     * this measurement.
+     */
+    double agc_level_db;
+} GnssMeasurement_ext;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+    /** set to sizeof(GnssData) */
+    size_t size;
+
+    /** Number of measurements. */
+    size_t measurement_count;
+
+    /** The array of measurements. */
+    GnssMeasurement_ext measurements[GNSS_MAX_MEASUREMENT];
+
+    /** The GPS clock time reading. */
+    GnssClock clock;
+} GnssData_ext;
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ *    data - A data structure containing the measurements.
+ */
+typedef void (*gnss_measurement_ext_callback) (GnssData_ext* data);
+
+typedef struct {
+    /** set to sizeof(GpsMeasurementCallbacks) */
+    size_t size;
+    gps_measurement_callback measurement_callback;
+    gnss_measurement_ext_callback gnss_measurement_callback;
+} GpsMeasurementCallbacks_ext;
+
+
+/////// Gnss debug ////
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+typedef enum {
+    /** Ephemeris is known for this satellite. */
+    EPHEMERIS,
+    /**
+     * Ephemeris is not known, but Almanac (approximate location) is known.
+     */
+    ALMANAC_ONLY,
+    /**
+     * Both ephemeris & almanac are not known (e.g. during a cold start
+     * blind search.)
+     */
+    NOT_AVAILABLE
+} SatelliteEphemerisType;
+
+typedef enum {
+    /**
+     * The ephemeris (or almanac only) information was demodulated from the
+     * signal received on the device
+     */
+    DEMODULATED,
+    /**
+     * The ephemeris (or almanac only) information was received from a SUPL
+     * server.
+     */
+    SUPL_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * server.
+     */
+    OTHER_SERVER_PROVIDED,
+    /**
+     * The ephemeris (or almanac only) information was provided by another
+     * method, e.g. injected via a local debug tool, from build defaults
+     * (e.g. almanac), or is from a satellite
+     * with SatelliteEphemerisType::NOT_AVAILABLE.
+     */
+    OTHER
+} SatelliteEphemerisSource;
+
+typedef enum {
+    /** The ephemeris is known good. */
+    GOOD,
+    /** The ephemeris is known bad. */
+    BAD,
+    /** The ephemeris is unknown to be good or bad. */
+    UNKNOWN
+} SatelliteEphemerisHealth;
+
+/**
+ * Provides the current best known position from any
+ * source (GNSS or injected assistance).
+ */
+typedef struct {
+    /**
+     * Validity of the data in this struct. False only if no
+     * latitude/longitude information is known.
+     */
+    bool valid;
+    /** Latitude expressed in degrees */
+    double latitudeDegrees;
+    /** Longitude expressed in degrees */
+    double longitudeDegrees;
+    /** Altitude above ellipsoid expressed in meters */
+    float altitudeMeters;
+    /** Represents horizontal speed in meters per second. */
+    float speedMetersPerSec;
+    /** Represents heading in degrees. */
+    float bearingDegrees;
+    /**
+     * Estimated horizontal accuracy of position expressed in meters,
+     * radial, 68% confidence.
+     */
+    double horizontalAccuracyMeters;
+    /**
+     * Estimated vertical accuracy of position expressed in meters, with
+     * 68% confidence.
+     */
+    double verticalAccuracyMeters;
+    /**
+     * Estimated speed accuracy in meters per second with 68% confidence.
+     */
+    double speedAccuracyMetersPerSecond;
+    /**
+     * estimated bearing accuracy degrees with 68% confidence.
+     */
+    double bearingAccuracyDegrees;
+    /**
+     * Time duration before this report that this position information was
+     * valid.  This can, for example, be a previous injected location with
+     * an age potentially thousands of seconds old, or
+     * extrapolated to the current time (with appropriately increased
+     * accuracy estimates), with a (near) zero age.
+     */
+    float ageSeconds;
+} PositionDebug;
+
+/**
+ * Provides the current best known UTC time estimate.
+ * If no fresh information is available, e.g. after a delete all,
+ * then whatever the effective defaults are on the device must be
+ * provided (e.g. Jan. 1, 2017, with an uncertainty of 5 years) expressed
+ * in the specified units.
+ */
+typedef struct {
+    /** UTC time estimate. */
+    GnssUtcTime timeEstimate;
+    /** 68% error estimate in time. */
+    float timeUncertaintyNs;
+    /**
+     * 68% error estimate in local clock drift,
+     * in nanoseconds per second (also known as parts per billion - ppb.)
+     */
+    float frequencyUncertaintyNsPerSec;
+} TimeDebug;
+
+/**
+ * Provides a single satellite info that has decoded navigation data.
+ */
+typedef struct {
+    /** Satellite vehicle ID number */
+    int16_t svid;
+    /** Defines the constellation type of the given SV. */
+    GnssConstellationType constellation;
+
+    /**
+     * Defines the standard broadcast ephemeris or almanac availability for
+     * the satellite.  To report status of predicted orbit and clock
+     * information, see the serverPrediction fields below.
+     */
+    SatelliteEphemerisType ephemerisType;
+    /** Defines the ephemeris source of the satellite. */
+    SatelliteEphemerisSource ephemerisSource;
+    /**
+     * Defines whether the satellite is known healthy
+     * (safe for use in location calculation.)
+     */
+    SatelliteEphemerisHealth ephemerisHealth;
+    /**
+     * Time duration from this report (current time), minus the
+     * effective time of the ephemeris source (e.g. TOE, TOA.)
+     * Set to 0 when ephemerisType is NOT_AVAILABLE.
+     */
+    float ephemerisAgeSeconds;
+
+    /**
+     * True if a server has provided a predicted orbit and clock model for
+     * this satellite.
+     */
+    bool serverPredictionIsAvailable;
+    /**
+     * Time duration from this report (current time) minus the time of the
+     * start of the server predicted information.  For example, a 1 day
+     * old prediction would be reported as 86400 seconds here.
+     */
+    float serverPredictionAgeSeconds;
+} SatelliteData;
+
+/**
+ * Provides a set of debug information that is filled by the GNSS chipset
+ * when the method getDebugData() is invoked.
+ */
+typedef struct {
+    /** Current best known position. */
+    PositionDebug position;
+    /** Current best know time estimate */
+    TimeDebug time;
+    /**
+     * Provides a list of the available satellite data, for all
+     * satellites and constellations the device can track,
+     * including GnssConstellationType UNKNOWN.
+     */
+    SatelliteData satelliteDataArray[GNSS_MAX_SVS];
+} DebugData;
+
+
+/** Extended interface for DEBUG support. */
+typedef struct {
+    /** set to sizeof(GpsDebugInterface) */
+    size_t          size;
+
+    /**
+     * This function should return any information that the native
+     * implementation wishes to include in a bugreport.
+     */
+    // size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+    /// v1.0 ///
+    bool (*get_internal_state)(DebugData* debugData);
+} GpsDebugInterface_ext;
+
+
+////////////////////// GNSS HIDL v1.1 ////////////////////////////
+
+/**
+ * Callback for reporting driver name information.
+ */
+typedef void (* gnss_set_name_callback)(const char* name, int length);
+
+/**
+ * Callback for requesting framework NLP or Fused location injection.
+ */
+typedef void (* gnss_request_location_callback)(bool independentFromGnss);
+
+/** New GPS callback structure. */
+typedef struct {
+    /** set to sizeof(GpsCallbacks) */
+    size_t      size;
+    gps_location_ext_callback location_cb;
+    gps_status_callback status_cb;
+    gps_sv_status_callback sv_status_cb;
+    gps_nmea_callback nmea_cb;
+    gps_set_capabilities set_capabilities_cb;
+    gps_acquire_wakelock acquire_wakelock_cb;
+    gps_release_wakelock release_wakelock_cb;
+    gps_create_thread create_thread_cb;
+    gps_request_utc_time request_utc_time_cb;
+
+    gnss_set_system_info set_system_info_cb;
+    gnss_sv_status_ext_callback gnss_sv_status_cb;
+
+    /////v1.1////
+    gnss_set_name_callback set_name_cb;
+    gnss_request_location_callback request_location_cb;
+} GpsCallbacks_ext;
+
+
+/** Represents the standard GPS interface. */
+typedef struct {
+    /** set to sizeof(GpsInterface) */
+    size_t          size;
+    /**
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     */
+    /// v1.0 ///
+//    int   (*init)( GpsCallbacks* callbacks );
+    /// v1.1 ///
+    int   (*init)( GpsCallbacks_ext* callbacks );
+
+    /** Starts navigating. */
+    int   (*start)( void );
+
+    /** Stops navigating. */
+    int   (*stop)( void );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** Injects the current time. */
+    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
+                         int uncertainty);
+
+    /**
+     * Injects current location from another location provider (typically cell
+     * ID). Latitude and longitude are measured in degrees expected accuracy is
+     * measured in meters
+     */
+    int  (*inject_location)(double latitude, double longitude, float accuracy);
+
+    /**
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GPS_DELETE_ALL is passed for
+     * a cold start.
+     */
+    void  (*delete_aiding_data)(GpsAidingData flags);
+
+    /**
+     * min_interval represents the time between fixes in milliseconds.
+     * preferred_accuracy represents the requested fix accuracy in meters.
+     * preferred_time represents the requested time to first fix in milliseconds.
+     *
+     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
+     * or GPS_POSITION_MODE_STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+     * GPS_POSITION_MODE_MS_BASED is supported.
+     */
+     /// v1.0 ///
+//    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+//            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+    /// v1.1 ///
+    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
+            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time,
+            bool lowPowerMode);
+
+
+    /** Get a pointer to extension information. */
+    const void* (*get_extension)(const char* name);
+
+    /// v1.1 ///
+    int  (*inject_fused_location)(double latitude, double longitude, float accuracy);
+
+} GpsInterface_ext;
+
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+    /** Set to sizeof(GpsMeasurementInterface_ext) */
+    size_t size;
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+     *
+     * Status:
+     *    GPS_MEASUREMENT_OPERATION_SUCCESS
+     *    GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+     *              corresponding call to 'close'
+     *    GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+     *              will not generate any updates upon returning this error code.
+     */
+    /// v1.0 ///
+//    int (*init) (GpsMeasurementCallbacks* callbacks);
+    /// v1.1 ///
+    int (*init) (GpsMeasurementCallbacks_ext* callbacks, bool enableFullTracking);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to stop, the previously registered callbacks must be considered invalid by the
+     * HAL.
+     * If stop is invoked without a previous 'init', this function should perform no work.
+     */
+    void (*close) ();
+
+} GpsMeasurementInterface_ext;
+
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+    /** Set to sizeof(GnssConfigurationInterface) */
+    size_t size;
+
+    /**
+     * Deliver GNSS configuration contents to HAL.
+     * Parameters:
+     *     config_data - a pointer to a char array which holds what usually is expected from
+                         file(/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+     *     length - total number of UTF8 characters in configuraiton data.
+     *
+     * IMPORTANT:
+     *      GPS HAL should expect this function can be called multiple times. And it may be
+     *      called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+     *      should maintain the existing requests for various callback regardless the change
+     *      in configuration data.
+     */
+    void (*configuration_update) (const char* config_data, int32_t length);
+
+   //// v1.1 ////
+   void (*setBlacklist) (long long* blacklist, int32_t size);
+} GnssConfigurationInterface_ext;
+
+struct gps_device_t_ext {
+    struct hw_device_t common;
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * Returns: 0 on succes, error code on failure.
+     */
+    const GpsInterface_ext* (*get_gps_interface)(struct gps_device_t_ext* dev);
+};
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_HARDWARE_GPS_MTK_H */
+
diff --git a/src/connectivity/gps/service/1.1/service.cpp b/src/connectivity/gps/service/1.1/service.cpp
new file mode 100644
index 0000000..bdb84cb
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/service.cpp
@@ -0,0 +1,17 @@
+#define LOG_TAG "vendor.mediatek.hardware.gnss@1.1-service"
+
+#include <android/hardware/gnss/1.1/IGnss.h>
+
+#include <hidl/LegacySupport.h>
+
+#include <binder/ProcessState.h>
+
+using android::hardware::gnss::V1_1::IGnss;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    // The GNSS HAL may communicate to other vendor components via
+    // /dev/vndbinder
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    return defaultPassthroughServiceImplementation<IGnss>();
+}
diff --git a/src/connectivity/gps/service/1.1/vendor.mediatek.hardware.gnss@1.1-service.rc b/src/connectivity/gps/service/1.1/vendor.mediatek.hardware.gnss@1.1-service.rc
new file mode 100644
index 0000000..40547f9
--- /dev/null
+++ b/src/connectivity/gps/service/1.1/vendor.mediatek.hardware.gnss@1.1-service.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/vendor.mediatek.hardware.gnss@1.1-service
+    class main
+    user system
+    group system gps
diff --git a/src/connectivity/gps/service/Android.backup b/src/connectivity/gps/service/Android.backup
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/src/connectivity/gps/service/Android.backup
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/src/connectivity/gps/service/Android.bp b/src/connectivity/gps/service/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/src/connectivity/gps/service/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/src/connectivity/gps/service/Android.mk b/src/connectivity/gps/service/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/src/connectivity/gps/service/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)