T108: fix data_call

Change-Id: I48ac56b38bd7bbfaad8c310398bc3a1e7e2613d1
diff --git a/mbtk/include/mbtk/mbtk_info_api.h b/mbtk/include/mbtk/mbtk_info_api.h
index ecf2516..61e08bd 100755
--- a/mbtk/include/mbtk/mbtk_info_api.h
+++ b/mbtk/include/mbtk/mbtk_info_api.h
@@ -103,7 +103,11 @@
     pthread_cond_t cond;
     pthread_mutex_t mutex;
 
+#ifdef MBTK_SG_SUPPORT
+    int handle_state;
+#else
     pthread_mutex_t send_mutex;
+#endif
 
     // Temp response data.
     uint16 info_err;
@@ -318,7 +322,6 @@
     MBTK_DATA_CALL_START,       // Start data call.
     MBTK_DATA_CALL_STATE        // Get data call state
 } mbtk_data_call_type_enum;
-
 /*
 0: not registered, MT is not currently searching a new operator to register to
 1: registered, home network
@@ -490,6 +493,35 @@
 }mbtk_led_status;
 /**************led enum*********/
 
+/**************qser data_call*****************/
+typedef enum {
+    MBTK_APN_REQ_TYPE_SET = 0,   // set apn req
+    MBTK_APN_REQ_TYPE_ADD        // add apn req
+}mbtk_apn_req_type_enum;
+
+typedef enum {
+	MBTK_APN_AUTH_PROTO_DEFAULT = 0,
+	MBTK_APN_AUTH_PROTO_NONE,
+	MBTK_APN_AUTH_PROTO_PAP,
+	MBTK_APN_AUTH_PROTO_CHAP,
+	MBTK_APN_AUTH_PROTO_PAP_CHAP,
+} mbtk_apn_auth_proto_enum;
+
+typedef struct {
+	int cid;                /*!< UMTS/CDMA profile ID. range: 0 - 7*/
+	mbtk_ip_type_enum ip_type;               /*!< Packet Data Protocol (PDP) type specifies the type of data payload
+	                                             exchanged over the airlink when the packet data session is
+	                                             established with this profile. */ 
+	mbtk_apn_req_type_enum req_type;          /*!< apn req type*/
+	mbtk_apn_auth_proto_enum auth_proto;         /*!< Authentication Protocol. */
+	uint8 apn_name[150];        /*!< A string parameter that is a logical name used to select the GGSN
+	                                             and external packet data network. */ 
+	uint8 user_name[127];    /*!< Username used during data network authentication. */
+	uint8 user_pass[127];    /*!< Password to be used during data network authentication. */
+    uint8 apn_type[127];
+} mbtk_qser_apn_info_s;
+/**************qser data_call*****************/
+
 mbtk_info_handle_t* mbtk_info_handle_get();
 
 int mbtk_info_handle_free(mbtk_info_handle_t** handle);
@@ -607,6 +639,16 @@
 int mbtk_apn_get(mbtk_info_handle_t* handle, int *apn_num, mbtk_apn_info_t apns[]);
 
 /*
+* Set current QSER APN informations.
+*/
+int mbtk_qser_apn_set(mbtk_info_handle_t* handle, mbtk_qser_apn_info_s *apninfo, unsigned char *cid);
+
+/*
+* Set current QSER APN informations.
+*/
+int mbtk_qser_apn_get(mbtk_info_handle_t* handle, int *apn_num, mbtk_qser_apn_info_s apns[]);
+
+/*
 * Set current APN informations.
 */
 int mbtk_apn_set(mbtk_info_handle_t* handle, int cid, mbtk_ip_type_enum ip_type, const void* apn_name,
diff --git a/mbtk/liblynq_lib/src/lynq_data_call.c b/mbtk/liblynq_lib/src/lynq_data_call.c
index ee9e754..3d3cdda 100644
--- a/mbtk/liblynq_lib/src/lynq_data_call.c
+++ b/mbtk/liblynq_lib/src/lynq_data_call.c
@@ -39,139 +39,19 @@
 int qser_info_handle_num = 0;
 static bool inited = FALSE;
 static qser_data_call_evt_cb_t qser_net_status_cb = NULL;
-static qser_apn_info_s qser_apn_info[QSER_APN_NUM] = {0};
-static bool qser_apn_info_state[QSER_APN_NUM] = {0};
-static bool qser_idx_pdp_state[QSER_APN_NUM];
-static char qser_apn_add_save_state[QSER_APN_NUM + 1] = {0};
-static char qser_apn_auth_state[QSER_APN_NUM + 1] = {0};
-#if defined(MBTK_ALL_CID_SUPPORT)
-static int qser_apn_default_idx = -1;
-static int qser_default_pdp_idx = -1;
-#else
-static int qser_apn_default_idx = 0xFF;
-static int qser_default_pdp_idx = 0;
-#endif
 /****************************VARIABLE***************************************/
 
 /******************************FUNC*****************************************/
-#if defined(MBTK_ALL_CID_SUPPORT)
-static int qser_route_config(int profile_idx)
-{
-    char buf[1024] = {0};
-    char dns[128] = {0};
-    int offset = 0;
-    int fd = -1;
-    mbtk_ipv4_info_t ipv4;
-    mbtk_ipv6_info_t ipv6;
-    sprintf(buf, "route add default dev ccinet%d", profile_idx -1);
-    system(buf);
-
-    int ret = mbtk_data_call_state_get(qser_info_handle, profile_idx, &ipv4, &ipv6);
-    if(ret != 0)
-        return QSER_RESULT_FAIL;
-    else
-    {
-        memset(buf, 0x0, 1024);
-        memset(dns, 0x0, 128);
-        offset = sprintf(buf, "search lan\n");
-        if(ipv4.valid)
-        {
-            if(inet_ntop(AF_INET, &(ipv4.PrimaryDNS), dns, 32) == NULL) {
-                LOGE("[qser_data] PrimaryDNS error.");
-            } else {
-                LOGE("[qser_data] PrimaryDNS : %s", dns);
-            }
-            offset += sprintf(buf + offset, "nameserver %s\n", dns);
-            memset(dns, 0x0, 128);
-            if(inet_ntop(AF_INET, &(ipv4.SecondaryDNS), dns, 32) == NULL) {
-                LOGE("[qser_data] SecondaryDNS error.");
-            } else {
-                LOGE("[qser_data] SecondaryDNS : %s", dns);
-            }
-            offset += sprintf(buf + offset, "nameserver %s\n", dns);
-        }
-        if(ipv6.valid)
-        {
-            memset(dns, 0x0, 128);
-			if(ipv6_2_str(&(ipv6.PrimaryDNS), dns))
-            {
-				LOGE("[qser_data] PrimaryDNS error.");
-			} else {
-				LOGE("[qser_data] PrimaryDNS : %s", dns);
-			}
-            offset += sprintf(buf + offset, "nameserver %s\n", dns);
-            memset(dns, 0x0, 128);
-			if(ipv6_2_str(&(ipv6.SecondaryDNS), dns))
-            {
-				LOGE("[qser_data] SecondaryDNS error.");
-			} else {
-				LOGE("[qser_data] SecondaryDNS : %s", dns);
-			}
-            offset += sprintf(buf + offset, "nameserver %s\n", dns);
-        }
-
-        if(offset > 0)
-        {
-            fd = open("/tmp/resolv.conf", O_WRONLY | O_TRUNC);
-            if(fd < 0)
-            {
-                LOGE("[qser_data] mbtk_route_config : open fail.");
-                return QSER_RESULT_FAIL;
-            }
-
-            ret = write(fd, buf, offset);
-            if(ret < 0)
-            {
-                LOGE("[qser_data] mbtk_route_config : write fail.");
-            }
-
-            close(fd);
-        }
-    }
-
-    return 0;
-}
-#endif
-
-static char qser_get_apn_profile_idx(void)
-{
-    char i = 0;
-    for(i = QSER_PROFILE_IDX_MIN; i <= QSER_PROFILE_IDX_MAX; i++)
-    {
-        if(qser_apn_info_state[i] == FALSE)
-        {
-            return i;
-        }
-    }
-
-    return i;
-}
-
-static int qser_check_profile_idx(unsigned char profile_idx)
-{
-    if(profile_idx < QSER_PROFILE_IDX_MIN || profile_idx > QSER_PROFILE_IDX_MAX)
-    {
-        LOGE("[qser_data] IDX range error.");
-        return QSER_RESULT_FAIL;
-    }
-    
-    if(qser_apn_info_state[profile_idx] != TRUE)
-    {
-        LOGE("[qser_data] profile_idx is not exist.");
-        return QSER_RESULT_FAIL;
-    }
-
-    return QSER_RESULT_SUCCESS;
-}
-
-static int qser_apn_info_param_convert(int profile_idx, qser_apn_info_s *new_apn, mbtk_apn_info_t *old_apn)
+static int qser_apn_info_param_convert(int profile_idx, qser_apn_info_s *new_apn, mbtk_qser_apn_info_s *old_apn)
 {
     if(new_apn == NULL || old_apn == NULL)
     {
         LOGE("[qser_data] qser_apn_info_param_convert apn param is NULL.");
         return QSER_RESULT_FAIL;
     }
-    
+
+    memset(new_apn, 0x0, sizeof(qser_apn_info_s));
+    new_apn->profile_idx = old_apn->cid - 1;
     //get ip type
     if(old_apn->ip_type == MBTK_IP_TYPE_IPV4V6) // IPV4V6
     {
@@ -191,181 +71,61 @@
     }
 
     //get apn name
-    if(strlen(old_apn->apn)+1 > QSER_APN_NAME_SIZE)
+    if(strlen((char *)old_apn->apn_name) > QSER_APN_NAME_SIZE)
     {
         LOGE("[qser_data] apn_nmea length verylong.");
         return QSER_RESULT_FAIL;
     }
     else
     {
-        if(strlen(old_apn->apn) > 0)
+        if(strlen((char *)old_apn->apn_name) > 0)
         {
-            memcpy(new_apn->apn_name, old_apn->apn,strlen(old_apn->apn)+1);
-        }
-        else
-        {
-            memset(new_apn->apn_name, 0x0, QSER_APN_NAME_SIZE);
+            memcpy(new_apn->apn_name, old_apn->apn_name,strlen((char *)old_apn->apn_name));
         }
     }
 
     //get apn user
-    if(strlen(old_apn->user)+1 > QSER_APN_USERNAME_SIZE)
+    if(strlen((char *)old_apn->user_name) > QSER_APN_USERNAME_SIZE)
     {
         LOGE("[qser_data] apn_user length verylong.");
         return QSER_RESULT_FAIL;
     }
     else
     {
-        if(strlen(old_apn->user) > 0)
+        if(strlen((char *)old_apn->user_name) > 0)
         {
-            memcpy(new_apn->username, old_apn->user, strlen(old_apn->user)+1);
-        }
-        else
-        {
-            memset(new_apn->username , 0x0, QSER_APN_USERNAME_SIZE);
+            memcpy(new_apn->username, old_apn->user_name, strlen((char *)old_apn->user_name));
         }
     }
 
     //get apn password
-    if(strlen(old_apn->pass)+1 > QSER_APN_PASSWORD_SIZE)
+    if(strlen((char *)old_apn->user_pass) > QSER_APN_PASSWORD_SIZE)
     {
         LOGE("[qser_data] apn_password length verylong.");
         return QSER_RESULT_FAIL;
     }
     else
     {
-        if(strlen(old_apn->pass) > 0)
+        if(strlen((char *)old_apn->user_pass) > 0)
         {
-            memcpy(new_apn->password, old_apn->pass, strlen(old_apn->pass)+1);
-        }
-        else
-        {
-            memset(new_apn->username , 0x0, QSER_APN_PASSWORD_SIZE);
+            memcpy(new_apn->password, old_apn->user_pass, strlen((char *)old_apn->user_pass));
         }
     }
 
     //get apn proto
-    if(strlen(old_apn->auth) > 0)
-    {
-        if(strcmp(old_apn->auth, "NONE") == 0)
-        {
-            if(qser_apn_auth_state[profile_idx] == '1')
-            {
-                new_apn->auth_proto = QSER_APN_AUTH_PROTO_NONE;
-            }
-            else
-            {
-                new_apn->auth_proto = QSER_APN_AUTH_PROTO_DEFAULT;
-            }
-        }
-        else if(strcmp(old_apn->auth, "PAP") == 0)
-        {
-            new_apn->auth_proto = QSER_APN_AUTH_PROTO_PAP;
-        }
-        else if(strcmp(old_apn->auth, "CHAP") == 0)
-        {
-            new_apn->auth_proto = QSER_APN_AUTH_PROTO_CHAP;
-        }
-        else
-        {
-            LOGE("[qser_data] auth input error!");
-            return QSER_RESULT_FAIL;
-        }
-    }
+    new_apn->auth_proto = (qser_apn_auth_proto_e)old_apn->auth_proto;
 
     //get apn type
-    new_apn->profile_idx = profile_idx;
-    memset(new_apn->apn_type, 0x0, QSER_APN_NAME_SIZE);
-    if(strlen(qser_apn_info[profile_idx].apn_type) > 0)
+    if(strlen((char *)old_apn->apn_type) > QSER_APN_PASSWORD_SIZE)
     {
-        memcpy(new_apn->apn_type, qser_apn_info[profile_idx].apn_type, strlen(qser_apn_info[profile_idx].apn_type));
-    }
-
-    return QSER_RESULT_SUCCESS;
-}
-
-/*Check parameter*/
-static int qser_check_apn_name_type(qser_apn_info_s *apn)
-{
-    if(apn == NULL)
-    {
-        LOGE("[qser_data] qser_check_apn_type apn is NULL!");
+        LOGE("[qser_data] apn_type length verylong.");
         return QSER_RESULT_FAIL;
     }
-
-    //check default idx = 0
-    int apn_name_length = strlen(apn->apn_name);
-    //LOGE("[qser_data] qser_apn_info[0].apn_name: %s!", qser_apn_info[0].apn_name);
-    char *p = strstr(qser_apn_info[0].apn_name, "mnc");
-    if(p == NULL)
-    {
-        LOGE("[qser_data] qser_check_apn_type not find!");
-        //return QSER_RESULT_FAIL;
-    }
     else
     {
-        int default_apn_name_length = p - (qser_apn_info[0].apn_name) -1;
-        LOGE("[qser_data] qser_check_apn_type default_apn_name_length = [%d]!", default_apn_name_length);
-        if(default_apn_name_length == apn_name_length)
+        if(strlen((char *)old_apn->apn_type) > 0)
         {
-            int i = 0;
-            while(i < default_apn_name_length)
-            {
-                if(isalpha(qser_apn_info[0].apn_name[i]) && isalpha(apn->apn_name[i]))
-                {
-                    if(tolower(qser_apn_info[0].apn_name[i]) != tolower(apn->apn_name[i]))
-                    {
-                        break;
-                    }
-                }
-                else
-                {
-                    //LOGE("[qser_data] not char!");
-                    if(qser_apn_info[0].apn_name[i] != apn->apn_name[i])
-                    {
-                        break;
-                    }
-                }
-                
-                i++;
-            }
-
-            if(i == default_apn_name_length)
-            {
-                LOGE("[qser_data] apn_name is same!idx = [0]");
-                return QSER_RESULT_FAIL;
-            }
-        }
-    }
-    //check 1 -6
-    int pdp_type_tmp = 1;
-    for (;pdp_type_tmp < QSER_APN_NUM; pdp_type_tmp++)
-    {
-        if(pdp_type_tmp == apn->profile_idx)
-        {
-            continue;
-        }
-        if( (qser_apn_add_save_state[pdp_type_tmp] == '1') || (qser_apn_add_save_state[pdp_type_tmp] == '2') )
-        {
-            if(strcmp(qser_apn_info[pdp_type_tmp].apn_type, apn->apn_type) == 0)
-            {
-                LOGE("[qser_data] apn_type is same!idx = [%d]", pdp_type_tmp);
-                return QSER_RESULT_FAIL;
-            }
-            if (strcmp(qser_apn_info[pdp_type_tmp].apn_name, apn->apn_name) == 0)
-            {
-                if(qser_apn_info[pdp_type_tmp].pdp_type == QSER_APN_PDP_TYPE_IPV4V6 || apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6)
-                {
-                    LOGE("[qser_data] apn_name is same and pdp_type is IPV4V6!idx = [%d]", pdp_type_tmp);
-                    return QSER_RESULT_FAIL;
-                }
-
-                if(qser_apn_info[pdp_type_tmp].pdp_type == apn->pdp_type)
-                {
-                    LOGE("[qser_data] pdp_type is same and pdp_type is same!idx = [%d]", pdp_type_tmp);
-                    return QSER_RESULT_FAIL;
-                }
-            }
+            memcpy(new_apn->apn_type, old_apn->apn_type, strlen((char *)old_apn->apn_type));
         }
     }
 
@@ -411,12 +171,6 @@
             qser_state_init(&state);
             state.profile_idx = idx;
             state.state = QSER_DATA_CALL_DISCONNECTED;
-            if( idx == qser_default_pdp_idx )
-            {
-                qser_default_pdp_idx = -1;
-            }
-            qser_idx_pdp_state[idx] = false;
-
             if(qser_net_status_cb != NULL)
             {
                 qser_net_status_cb(&state);
@@ -528,69 +282,6 @@
     }
     qser_net_status_cb = evt_cb;
 
-    property_get("persist.qser.datacall.apn", qser_apn_add_save_state, "00000000");
-    LOGE("[qser_data] qser_apn_add_save_state = %s", qser_apn_add_save_state);
-    property_get("persist.qser.apn.auth", qser_apn_auth_state, "00000000");
-    mbtk_apn_info_t apns[10] = {0};
-    int apn_num = 10;
-    char qser_apn_type[32] = {0};
-    int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
-    if(ret != 0)
-    {
-        if(ret == MBTK_INFO_ERR_NO_APN)
-        {
-            return QSER_RESULT_SUCCESS;
-        }
-        LOGE("[qser_data] mbtk_apn_get fail. [ret = %d]",ret);
-        qser_data_call_destroy();
-        return QSER_RESULT_FAIL;
-    }
-    else
-    {
-        if(apn_num > 0 && apn_num <= QSER_APN_MAX_LIST)
-        {
-            int i = 0;
-            for(i = 0; i < apn_num; i++)
-            {
-                if(qser_apn_add_save_state[apns[i].cid - 1] == '0')
-                {
-                    //LOGE("[qser_data] idx no open.");
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-                    if(apns[i].cid - 1 == 0)
-                    {
-                        qser_apn_info_param_convert(apns[i].cid - 1, &qser_apn_info[apns[i].cid - 1], &apns[i]);
-                    }
-#endif
-                    continue;
-                }
-
-#if defined(MBTK_ALL_CID_SUPPORT)
-                if(qser_apn_add_save_state[apns[i].cid - 1] == '2')
-                {
-                    qser_apn_default_idx = apns[i].cid - 1;
-                }
-#endif
-
-                if(qser_apn_info_param_convert(apns[i].cid - 1, &qser_apn_info[apns[i].cid - 1], &apns[i]) != 0)
-                {
-                    LOGE("[qser_data] qser_apn_info_param_convert fail");
-                    return QSER_RESULT_FAIL;
-                }
-                else
-                {
-                    qser_apn_info_state[apns[i].cid - 1] = TRUE;
-                    sprintf(qser_apn_type, "persist.qser.apn.type%d", apns[i].cid - 1);
-                    property_get(qser_apn_type, qser_apn_info[apns[i].cid - 1].apn_type, NULL);
-                }
-            }
-        }
-    }
-
-    int idx = 0;
-    for(;idx < QSER_APN_NUM; idx++)
-    {
-        qser_idx_pdp_state[idx] = false;
-    }
     LOGE("[qser_data] mbtk_info_handle_get() success.");
     return QSER_RESULT_SUCCESS;
 }
@@ -648,31 +339,6 @@
         return QSER_RESULT_FAIL;
     }
 
-#if defined(MBTK_ALL_CID_SUPPORT)
-    if( ( (data_call->profile_idx == qser_apn_default_idx) || (data_call->profile_idx == 0) ) && (qser_default_pdp_idx >= 0) )
-    {
-        LOGE("[qser_data] default pdp exist.");
-        *err = QSER_DATA_CALL_ERROR_UNKNOWN;
-        return QSER_RESULT_FAIL;
-    }
-#endif
-
-    if(qser_check_profile_idx(data_call->profile_idx) < 0)
-    {
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-        if( data_call->profile_idx == 0 )
-        {
-            LOGE("[qser_data] profile_idx = 0.");
-        }
-        else
-#endif
-        {
-            LOGE("[qser_data] profile_idx is invalid.");
-            *err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
-            return QSER_RESULT_FAIL;
-        }
-    }
-
     int ret = -1;
     ret = mbtk_data_call_start(qser_info_handle, data_call->profile_idx + 1, 0, FALSE, 0);
     if(ret != 0)
@@ -693,25 +359,6 @@
         *err = QSER_DATA_CALL_ERROR_NONE;
     }
 
-#if defined(MBTK_ALL_CID_SUPPORT)
-    if(qser_apn_default_idx == data_call->profile_idx)
-    {
-        qser_route_config(qser_apn_default_idx + 1);
-        qser_default_pdp_idx = data_call->profile_idx;
-    }
-    else if(data_call->profile_idx == 0)
-    {
-        qser_route_config(1);
-        qser_default_pdp_idx = data_call->profile_idx;
-    }
-    else
-    {
-        //
-    }
-        
-#endif
-    qser_idx_pdp_state[data_call->profile_idx] = true;
-
     return QSER_RESULT_SUCCESS;
 }
 
@@ -736,32 +383,6 @@
         return QSER_RESULT_FAIL;
     }
 
-#if defined(MBTK_ALL_CID_SUPPORT)
-        if( ( (data_call->profile_idx == qser_apn_default_idx) || (data_call->profile_idx == 0) ) && (qser_default_pdp_idx >= 0) )
-        {
-            LOGE("[qser_data] default pdp exist.");
-            *err = QSER_DATA_CALL_ERROR_UNKNOWN;
-            return QSER_RESULT_FAIL;
-        }
-#endif
-
-    if(qser_check_profile_idx(data_call->profile_idx) < 0)
-    {
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-        if((data_call->profile_idx == 0) && (qser_default_pdp_idx < 0))
-        {
-            LOGE("[qser_data] profile_idx = 0 and not open default idx.");
-        }
-        else
-#endif
-        {
-            LOGE("[qser_data] profile_idx is invalid.");
-            *err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
-            return QSER_RESULT_FAIL;
-        }
-
-    }
-
     pthread_attr_t thread_attr;
     pthread_t data_call_thread_id;
     pthread_attr_init(&thread_attr);
@@ -802,22 +423,6 @@
         return QSER_RESULT_FAIL;
     }
 
-    if(qser_check_profile_idx(profile_idx) < 0)
-    {
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-        if(profile_idx == 0)
-        {
-            LOGE("[qser_data] profile_idx = 0.");
-        }
-        else
-#endif
-        {
-            LOGE("[qser_data] profile_idx is invalid.");
-            *err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
-            return QSER_RESULT_FAIL;
-        }
-    }
-
     int ret = -1;
     ret = mbtk_data_call_stop(qser_info_handle, profile_idx + 1, 15);
     if(ret != 0)
@@ -838,14 +443,6 @@
         *err = QSER_DATA_CALL_ERROR_NONE;
     }
 
-#if defined(MBTK_ALL_CID_SUPPORT)
-    if(qser_default_pdp_idx == profile_idx)
-    {
-        qser_default_pdp_idx = -1;
-    }
-#endif
-    qser_idx_pdp_state[profile_idx] = false;
-
     return QSER_RESULT_SUCCESS;
 }
 
@@ -874,22 +471,6 @@
         return QSER_RESULT_FAIL;
     }
 
-    if(qser_check_profile_idx(profile_idx) < 0)
-    {
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-        if(profile_idx == 0)
-        {
-            LOGE("[qser_data] profile_idx = 0.");
-        }
-        else
-#endif
-        {
-            LOGE("[qser_data] profile_idx is invalid.");
-            *err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
-            return QSER_RESULT_FAIL;
-        }
-    }
-
     int ret = -1;
     mbtk_ipv4_info_t ipv4;
     mbtk_ipv6_info_t ipv6;
@@ -1005,56 +586,26 @@
         return QSER_RESULT_FAIL;
     }
 
-    if(qser_check_profile_idx(apn->profile_idx) < 0)
-    {
-        LOGE("[qser_data] profile_idx is invalid.");
-        return QSER_RESULT_FAIL;
-    }
-
-    if(strlen(apn->apn_name) == 0)
-    {
-        LOGE("[qser_data] apn_name is NULL.");
-        return QSER_RESULT_FAIL;
-    }
-
-#if 0
-    if(memcmp(apn->apn_type, "iot_default", strlen("iot_default")) == 0)
-    {
-        if(qser_apn_default_idx > -1)
-        {
-            LOGE("[qser_data] iot_default is exist.");
-            return QSER_RESULT_FAIL;
-        }
-    }
-#endif
-
-    /*add name and type verify*/
-    if (qser_check_apn_name_type(apn) < 0)
-    {
-        LOGE("[qser_data] check param error.");
-        return QSER_RESULT_FAIL;
-    }
-
-    int ret = -1;
-    char mbtk_auth[32]={0};
-    char qser_apn_type[32] = {0};
-    mbtk_ip_type_enum pdp_type = MBTK_IP_TYPE_IPV4V6;
-
+    int ret = 0;
+    mbtk_qser_apn_info_s apninfo;
+    memset(&apninfo, 0x0, sizeof(mbtk_qser_apn_info_s));
+    apninfo.cid = apn->profile_idx + 1;
+    
     if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4)
     {
-        pdp_type = MBTK_IP_TYPE_IP;
+        apninfo.ip_type = MBTK_IP_TYPE_IP;
     }
     else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV6)
     {
-        pdp_type = MBTK_IP_TYPE_IPV6;
+        apninfo.ip_type = MBTK_IP_TYPE_IPV6;
     }
     else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6)
     {
-        pdp_type = MBTK_IP_TYPE_IPV4V6;
+        apninfo.ip_type = MBTK_IP_TYPE_IPV4V6;
     }
     else if(apn->pdp_type == QSER_APN_PDP_TYPE_PPP)
     {
-        pdp_type = MBTK_IP_TYPE_PPP;
+        apninfo.ip_type = MBTK_IP_TYPE_PPP;
     }
     else
     {
@@ -1062,72 +613,37 @@
         return QSER_RESULT_FAIL;
     }
 
-    if(apn->auth_proto == QSER_APN_AUTH_PROTO_NONE || apn->auth_proto == QSER_APN_AUTH_PROTO_DEFAULT)
-    {
-        memcpy(mbtk_auth,"NONE",strlen("NONE")+1);
-    }
-    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP)
-    {
-        memcpy(mbtk_auth,"PAP",strlen("PAP")+1);
-    }
-    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_CHAP)
-    {
-        memcpy(mbtk_auth,"CHAP",strlen("CHAP")+1);
-    }
-    #if 0
-    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP_CHAP)
-    {
-        //NOT SUPPORT
-    }
-    #endif
-    else
-    {
-        LOGE("[qser_data] auth input error!");
-        return QSER_RESULT_FAIL;
-    }
-
-    if(strlen(apn->username) > 0 && strlen(apn->password) > 0)
-    {
-        LOGE("[qser_data] setapn: %d, %d, %s, %s, %s, %s, %s.",apn->profile_idx, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth, apn->apn_type);
-    }
-    else
-    {
-        LOGE("[qser_data] setapn: %d, %d, %s, NULL, NULL, %s, %s.",apn->profile_idx, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth, apn->apn_type);
-    }
     
-    ret = mbtk_apn_set(qser_info_handle, apn->profile_idx + 1, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth);
-    if(ret < 0)
+    apninfo.req_type = MBTK_APN_REQ_TYPE_SET;
+    apninfo.auth_proto = (mbtk_apn_auth_proto_enum)apn->auth_proto;
+    if(strlen(apn->apn_name))
     {
-        LOGE("[qser_data] mbtk_apn_set fail!");
+        memcpy(apninfo.apn_name, apn->apn_name, strlen(apn->apn_name));
+    }
+    else
+    {
+        LOGE("[qser_data] apn_name is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+    if(strlen(apn->username))
+    {
+        memcpy(apninfo.user_name, apn->username, strlen(apn->username));
+    }
+    if(strlen(apn->password))
+    {
+        memcpy(apninfo.user_pass, apn->password, strlen(apn->password));
+    }
+    if(strlen(apn->apn_type))
+    {
+        memcpy(apninfo.apn_type, apn->apn_type, strlen(apn->apn_type));
+    }
+    ret = mbtk_qser_apn_set(qser_info_handle, &apninfo, NULL);
+    if(ret != 0)
+    {
+        LOGE("[qser_data] mbtk_qser_apn_set fail.");
         return QSER_RESULT_FAIL;
     }
 
-    sprintf(qser_apn_type, "persist.qser.apn.type%d", apn->profile_idx);
-    property_set(qser_apn_type, apn->apn_type);
-    if(apn->auth_proto == QSER_APN_AUTH_PROTO_NONE)
-    {
-        qser_apn_auth_state[apn->profile_idx] = '1';
-    }
-    else
-    {
-        qser_apn_auth_state[apn->profile_idx] = '0';
-    }
-    property_set("persist.qser.apn.auth", qser_apn_auth_state);
-    memcpy(&qser_apn_info[apn->profile_idx], apn, sizeof(qser_apn_info_s));
-
-#if defined(MBTK_ALL_CID_SUPPORT)
-    if(strcmp(apn->apn_type, "iot_default") == 0)
-    {
-        qser_apn_add_save_state[apn->profile_idx] = '2';
-        qser_apn_default_idx = apn->profile_idx;
-    }
-    else
-#endif
-    {
-        qser_apn_add_save_state[apn->profile_idx] = '1';
-    }
-
-    property_set("persist.qser.datacall.apn", qser_apn_add_save_state);
     return QSER_RESULT_SUCCESS;
 }
 
@@ -1147,21 +663,10 @@
         return QSER_RESULT_FAIL;
     }
 
-    if(qser_check_profile_idx(profile_idx) < 0)
-    {
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-        if(profile_idx != 0)
-#endif
-        {
-            LOGE("[qser_data] profile_idx is invalid.");
-            return QSER_RESULT_FAIL;
-        }
-    }
-
     //get apn info
-    mbtk_apn_info_t apns[10] = {0};
+    mbtk_qser_apn_info_s apns[10] = {0};
     int apn_num = 10;
-    int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
+    int ret = mbtk_qser_apn_get(qser_info_handle, &apn_num, apns);
     if(ret != 0)
     {
         LOGE("[qser_data] mbtk_apn_get fail. [ret = %d]",ret);
@@ -1204,56 +709,71 @@
         return QSER_RESULT_FAIL;
     }
     
-    if(apn == NULL)
+    if(apn == NULL || profile_idx == NULL)
     {
         LOGE("[qser_data] apn param is NULL.");
         return QSER_RESULT_FAIL;
     }
 
-#if 0
-    if(memcmp(apn->apn_type, "iot_default", strlen("iot_default")) == 0)
-    {
-        if(qser_apn_default_idx > -1)
-        {
-            LOGE("[qser_data] iot_default is exist.");
-            return QSER_RESULT_FAIL;
-        }
-    }
-    /*add name and type verify*/
-    if (qser_check_apn_name_type(apn) < 0)
-    {
-        LOGE("[qser_data] check param error.");
-        return QSER_RESULT_FAIL;
-    }
-#endif
-
     int ret = 0;
-    char idx = qser_get_apn_profile_idx();
-    if(idx > QSER_PROFILE_IDX_MAX)
+    unsigned char idx[2] = {0};
+    mbtk_qser_apn_info_s apninfo;
+    memset(&apninfo, 0x0, sizeof(mbtk_qser_apn_info_s));
+    apninfo.cid = 0;
+    
+    if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4)
     {
-        LOGE("[qser_data] idx is full.");
-        return QSER_RESULT_FAIL;
+        apninfo.ip_type = MBTK_IP_TYPE_IP;
+    }
+    else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV6)
+    {
+        apninfo.ip_type = MBTK_IP_TYPE_IPV6;
+    }
+    else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6)
+    {
+        apninfo.ip_type = MBTK_IP_TYPE_IPV4V6;
+    }
+    else if(apn->pdp_type == QSER_APN_PDP_TYPE_PPP)
+    {
+        apninfo.ip_type = MBTK_IP_TYPE_PPP;
     }
     else
     {
-        qser_apn_info_state[idx] = TRUE;
-        qser_apn_info_s set_apn;
-        set_apn.profile_idx = idx;
-        set_apn.pdp_type = apn->pdp_type;
-        set_apn.auth_proto = apn->auth_proto;
-        memcpy(set_apn.apn_name, apn->apn_name, QSER_APN_NAME_SIZE);
-        memcpy(set_apn.username, apn->username, QSER_APN_USERNAME_SIZE);
-        memcpy(set_apn.password, apn->password, QSER_APN_PASSWORD_SIZE);
-        memcpy(set_apn.apn_type, apn->apn_type, QSER_APN_NAME_SIZE);
-        ret = qser_apn_set(&set_apn);
-        if(ret != 0)
-        {
-            LOGE("[qser_data] qser_apn_set fail.");
-            qser_apn_info_state[idx] = FALSE;
-            return QSER_RESULT_FAIL;
-        }
-        *profile_idx = idx;
+        LOGE("[qser_data] pdp_type error.");
+        return QSER_RESULT_FAIL;
     }
+
+    
+    apninfo.req_type = MBTK_APN_REQ_TYPE_ADD;
+    apninfo.auth_proto = (mbtk_apn_auth_proto_enum)apn->auth_proto;
+    if(strlen(apn->apn_name))
+    {
+        memcpy(apninfo.apn_name, apn->apn_name, strlen(apn->apn_name));
+    }
+    else
+    {
+        LOGE("[qser_data] apn_name is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+    if(strlen(apn->username))
+    {
+        memcpy(apninfo.user_name, apn->username, strlen(apn->username));
+    }
+    if(strlen(apn->password))
+    {
+        memcpy(apninfo.user_pass, apn->password, strlen(apn->password));
+    }
+    if(strlen(apn->apn_type))
+    {
+        memcpy(apninfo.apn_type, apn->apn_type, strlen(apn->apn_type));
+    }
+    ret = mbtk_qser_apn_set(qser_info_handle, &apninfo, idx);
+    if(ret != 0)
+    {
+        LOGE("[qser_data] mbtk_qser_apn_set fail.");
+        return QSER_RESULT_FAIL;
+    }
+    *profile_idx = idx[0] - 1;
     return QSER_RESULT_SUCCESS;
 }
 
@@ -1267,38 +787,13 @@
         LOGE("[qser_data] handle is NULL.");
         return QSER_RESULT_FAIL;
     }
-    
-    if(qser_idx_pdp_state[profile_idx] == true)
-    {
-        LOGE("[qser_data] profile_idx[%d] open pdp.", profile_idx);
-        return QSER_RESULT_FAIL;
-    }
-
-    if(qser_check_profile_idx(profile_idx) < 0)
-    {
-        LOGE("[qser_data] profile_idx is invalid.");
-        return QSER_RESULT_FAIL;
-    }
 
     ret = mbtk_apn_del(qser_info_handle, profile_idx);
-
     if(ret < 0)
     {
         LOGE("[qser_data] mbtk_apn_del fail!");
         return QSER_RESULT_FAIL;
     }
-
-    qser_apn_info_state[profile_idx] = FALSE;
-    qser_apn_add_save_state[profile_idx] = '0';
-    
-#if defined(MBTK_ALL_CID_SUPPORT)
-    if(profile_idx == qser_apn_default_idx)
-    {
-        qser_apn_default_idx = -1;
-    }
-#endif
-    
-    property_set("persist.qser.datacall.apn", qser_apn_add_save_state);
     return QSER_RESULT_SUCCESS;
 }
 
@@ -1318,11 +813,9 @@
         return QSER_RESULT_FAIL;
     }
 
-    property_get("persist.qser.datacall.apn", qser_apn_add_save_state, "00000000");
-    LOGE("[qser_data] qser_apn_add_save_state = %s", qser_apn_add_save_state);
-    mbtk_apn_info_t apns[10] = {0};
+    mbtk_qser_apn_info_s apns[10] = {0};
     int apn_num = 10;
-    int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
+    int ret = mbtk_qser_apn_get(qser_info_handle, &apn_num, apns);
     if(ret != 0)
     {
         if(ret == MBTK_INFO_ERR_NO_APN)
@@ -1341,16 +834,6 @@
             apn_list->cnt = 0;
             for(i = 0; i < apn_num; i++)
             {
-                if(qser_apn_add_save_state[apns[i].cid - 1] == '0')
-                {
-#if defined(MBTK_ALL_CID_SUPPORT) && !defined(MBTK_SG_SUPPORT)
-                    if((apns[i].cid - 1) != 0)
-#endif
-                    {
-                        LOGE("[qser_data] idx no open.");
-                        continue;
-                    }
-                }
                 if(qser_apn_info_param_convert(apns[i].cid - 1, &apn_list->apn[apn_list->cnt], &apns[i]) != 0)
                 {
                     LOGE("[qser_data] qser_apn_info_param_convert fail");
diff --git a/mbtk/libmbtk_ril/mbtk_info.c b/mbtk/libmbtk_ril/mbtk_info.c
index d7ea54f..c8ac3c1 100755
--- a/mbtk/libmbtk_ril/mbtk_info.c
+++ b/mbtk/libmbtk_ril/mbtk_info.c
@@ -274,6 +274,9 @@
         case MBTK_INFO_ID_NET_APN_REQ:
         case MBTK_INFO_ID_NET_APN_RSP:
             return "APN";
+        case MBTK_INFO_ID_NET_QSER_APN_REQ:
+        case MBTK_INFO_ID_NET_QSER_APN_RSP:
+            return "QSER_APN";
         // Lock net/cell/frequency
         case MBTK_INFO_ID_NET_CELL_REQ:
         case MBTK_INFO_ID_NET_CELL_RSP:
diff --git a/mbtk/libmbtk_ril/mbtk_info.h b/mbtk/libmbtk_ril/mbtk_info.h
index d8bef07..9d90690 100755
--- a/mbtk/libmbtk_ril/mbtk_info.h
+++ b/mbtk/libmbtk_ril/mbtk_info.h
@@ -125,6 +125,9 @@
     // mbtk_apn_info_t
     MBTK_INFO_ID_NET_APN_REQ,
     MBTK_INFO_ID_NET_APN_RSP,
+    // mbtk_qser_apn_info_t
+    MBTK_INFO_ID_NET_QSER_APN_REQ,
+    MBTK_INFO_ID_NET_QSER_APN_RSP,
     // mbtk_apn_del
     MBTK_INFO_ID_NET_APN_DEL_REQ,
     MBTK_INFO_ID_NET_APN_DEL_RSP,
diff --git a/mbtk/libmbtk_ril/mbtk_info_api.c b/mbtk/libmbtk_ril/mbtk_info_api.c
index a78fbfa..ce9cc9c 100644
--- a/mbtk/libmbtk_ril/mbtk_info_api.c
+++ b/mbtk/libmbtk_ril/mbtk_info_api.c
@@ -394,6 +394,14 @@
         return -1;
     }
 
+#ifdef MBTK_SG_SUPPORT
+    if(handle->handle_state)
+    {
+        LOG("hangdle BUSY.");
+        return -2;
+    }
+#endif
+
     mbtk_info_pack_t* pack = mbtk_info_pack_creat(id);
     if(pack == NULL) {
         return -1;
@@ -405,8 +413,13 @@
         pack->data = (const uint8*)send_buff;
     }
 
+#ifndef MBTK_SG_SUPPORT
     pthread_mutex_lock(&handle->send_mutex);
+#endif
     pthread_mutex_lock(&handle->mutex);
+#ifdef MBTK_SG_SUPPORT
+    handle->handle_state = 1;
+#endif
     handle->is_waitting = true;
 
     mbtk_info_pack_send(handle->client_fd, pack);
@@ -414,12 +427,10 @@
 
     if(recv_buff != NULL)
         handle->data = recv_buff;
-
     // Wait for server response.
     pthread_cond_wait(&handle->cond, &handle->mutex);
     handle->is_waitting = false;
     pthread_mutex_unlock(&handle->mutex);
-
     if(handle->info_err == MBTK_INFO_ERR_SUCCESS)
     {
         LOG("REQ %s success.", id2str(id));
@@ -429,11 +440,21 @@
             handle->data_len = 0;
             handle->data = NULL;
         }
+#ifdef MBTK_SG_SUPPORT
+        handle->handle_state = 0;
+#else
         pthread_mutex_unlock(&handle->send_mutex);
+#endif
+        
         return recv_len;
     } else {
         LOG("REQ %s fail : %s", id2str(id), err2str(handle->info_err));
-        pthread_mutex_unlock(&handle->send_mutex);
+#ifdef MBTK_SG_SUPPORT
+                handle->handle_state = 0;
+#else
+                pthread_mutex_unlock(&handle->send_mutex);
+#endif
+
         return -1;
     }
 }
@@ -508,7 +529,9 @@
 #endif
 
     pthread_mutex_init(&handle->mutex, NULL);
+#ifndef MBTK_SG_SUPPORT
     pthread_mutex_init(&handle->send_mutex, NULL);
+#endif
     pthread_cond_init(&handle->cond, NULL);
     handle->is_waitting = false;
 
@@ -1158,6 +1181,161 @@
 }
 
 /*
+* Get all APN informations.
+*/
+int mbtk_qser_apn_get(mbtk_info_handle_t* handle, int *apn_num, mbtk_qser_apn_info_s apns[])
+{
+    int len;
+    if(handle == NULL || apn_num == NULL || apns == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    uint8 data[SOCK_MSG_LEN_MAX];
+    if((len = info_item_process(handle, MBTK_INFO_ID_NET_QSER_APN_REQ, NULL, 0, data)) > 0) {
+        /*
+        <apn_num[1]><cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth[1]><apn_type_len[2]><apn_type_len>...
+                    <cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth[1]><apn_type_len[2]><apn_type_len>
+        */
+        uint8* ptr = data;
+        if(apn_num == NULL || apns == NULL || *apn_num < *ptr) {
+            *apn_num = 0;
+            LOGE("APN array size to not enough.");
+            return -1;
+        }
+        *apn_num = *ptr++;
+        LOGD("APN Number : %d", *apn_num);
+        int i = 0;
+        while(i < *apn_num) {
+            memset(&(apns[i]), 0x0 ,sizeof(mbtk_qser_apn_info_s));
+            apns[i].cid = *ptr++;
+            apns[i].ip_type = (mbtk_ip_type_enum)(*ptr++);
+
+            // apn
+            len = byte_2_uint16(ptr, false);
+            ptr += sizeof(uint16);
+            if(len > 0) { // Has APN
+                memcpy(apns[i].apn_name, ptr, len);
+                ptr += len;
+            }
+            // user
+            len = byte_2_uint16(ptr, false);
+            ptr += sizeof(uint16);
+            if(len > 0) { // Has APN
+                memcpy(apns[i].user_name, ptr, len);
+                ptr += len;
+            }
+
+            // pass
+            len = byte_2_uint16(ptr, false);
+            ptr += sizeof(uint16);
+            if(len > 0) { // Has APN
+                memcpy(apns[i].user_pass, ptr, len);
+                ptr += len;
+            }
+            // auth
+            apns[i].auth_proto = (mbtk_apn_auth_proto_enum)(*ptr++);
+
+            //apn_type
+            len = byte_2_uint16(ptr, false);
+            ptr += sizeof(uint16);
+            if(len > 0) { // Has APN
+                memcpy(apns[i].apn_type, ptr, len);
+                ptr += len;
+            }
+
+            i++;
+        }
+    } 
+    else if(len == 0)
+    {
+        LOGD("get data len : 0.");
+        *apn_num = 0;
+        return 0;
+    }
+    else
+    {
+        return handle->info_err;
+    }
+
+    return 0;
+}
+
+/*
+* qser Set current APN informations.
+*/
+int mbtk_qser_apn_set(mbtk_info_handle_t* handle, mbtk_qser_apn_info_s *apninfo, unsigned char *cid)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    
+    uint8 data[SOCK_MSG_LEN_MAX];
+    memset(data, 0, SOCK_MSG_LEN_MAX);
+    // cid : 2 - 7
+    if(apninfo->req_type != MBTK_APN_REQ_TYPE_ADD && (apninfo->cid < MBTK_APN_CID_MIN || apninfo->cid > MBTK_APN_CID_MAX)) {
+        LOGE("CID error.");
+        return -1;
+    }
+
+    uint8* ptr = data;
+    // <cid[1]><ip_type[1]><req_type[1]><auth[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth_len[2]><apn_type[2]>
+    *ptr++ = (uint8)apninfo->cid;
+    *ptr++ = (uint8)apninfo->ip_type;
+    *ptr++ = (uint8)apninfo->req_type;
+    *ptr++ = (uint8)apninfo->auth_proto;
+    if(str_empty(apninfo->apn_name)) {
+        uint16_2_byte((uint16)0, ptr, false);
+        ptr += sizeof(uint16);
+    } else {
+        uint16_2_byte((uint16)strlen((char *)apninfo->apn_name), ptr, false);
+        ptr += sizeof(uint16);
+        memcpy(ptr, apninfo->apn_name, strlen((char *)apninfo->apn_name));
+        ptr += strlen((char *)apninfo->apn_name);
+    }
+    if(str_empty(apninfo->user_name)) {
+        uint16_2_byte((uint16)0, ptr, false);
+        ptr += sizeof(uint16);
+    } else {
+        uint16_2_byte((uint16)strlen((char *)apninfo->user_name), ptr, false);
+        ptr += sizeof(uint16);
+        memcpy(ptr, apninfo->user_name, strlen((char *)apninfo->user_name));
+        ptr += strlen((char *)apninfo->user_name);
+    }
+
+    if(str_empty(apninfo->user_pass)) {
+        uint16_2_byte((uint16)0, ptr, false);
+        ptr += sizeof(uint16);
+    } else {
+        uint16_2_byte((uint16)strlen((char *)apninfo->user_pass), ptr, false);
+        ptr += sizeof(uint16);
+        memcpy(ptr, apninfo->user_pass, strlen((char *)apninfo->user_pass));
+        ptr += strlen((char *)apninfo->user_pass);
+    }
+
+    if(str_empty(apninfo->apn_type)) {
+        uint16_2_byte((uint16)0, ptr, false);
+        ptr += sizeof(uint16);
+    }
+    else
+    {
+        uint16_2_byte((uint16)strlen((char *)apninfo->apn_type), ptr, false);
+        ptr += sizeof(uint16);
+        memcpy(ptr, apninfo->apn_type, strlen((char *)apninfo->apn_type));
+        ptr += strlen((char *)apninfo->apn_type);
+    }
+
+    if(info_item_process(handle, MBTK_INFO_ID_NET_QSER_APN_REQ, data, ptr - data, (void *)cid) < 0)
+    {
+        return handle->info_err;
+    }
+
+    return 0;
+}
+
+/*
 * Set current APN informations.
 */
 int mbtk_apn_set(mbtk_info_handle_t* handle, int cid, mbtk_ip_type_enum ip_type, const void* apn_name,
diff --git a/mbtk/mbtk_rild/inc/info_data.h b/mbtk/mbtk_rild/inc/info_data.h
index aa67acc..02aff62 100755
--- a/mbtk/mbtk_rild/inc/info_data.h
+++ b/mbtk/mbtk_rild/inc/info_data.h
@@ -62,5 +62,5 @@
     int data_len;
 } info_urc_msg_t;
 
-
+int mbtk_get_apn_send_pack(void);
 #endif /* _info_data_H */
diff --git a/mbtk/mbtk_rild/inc/mbtk_data_call.h b/mbtk/mbtk_rild/inc/mbtk_data_call.h
new file mode 100644
index 0000000..e2338ee
--- /dev/null
+++ b/mbtk/mbtk_rild/inc/mbtk_data_call.h
@@ -0,0 +1,35 @@
+#ifndef __MBTK_DATA_CALL_H__
+#define __MBTK_DATA_CALL_H__
+#include <string.h>
+#include <stdlib.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "mbtk_list.h"
+#include "mbtk_utils.h"
+#include "mbtk_info_api.h"
+#include "info_data.h"
+#include "mbtk_str.h"
+
+#define MBTK_QSER_APN_NAME_SIZE 150
+#define DATA_CALL_APN_GET_FD 0x5f6f7f8f
+//#define MBTK_QSER_DATA_CONFIG_FILE "/etc/config/mbtk_data_call_config"
+
+void mbtk_set_default_pdp_state(bool state, int cid);
+int mbtk_check_cid(int cid);
+int mbtk_check_default_pdp_state(int cid);
+int mbtk_qser_route_config(int cid, mbtk_ipv4_info_t *ipv4, mbtk_ipv6_info_t *ipv6);
+int mbtk_qser_apn_del(int cid);
+int mbtk_qser_req_apn_get(void *data, int *data_len, int *cme_err);
+int mbtk_qser_apn_save(mbtk_apn_info_t apn, const uint8 *apn_type, bool state_save);
+int mbtk_strdata_to_apn(const uint8 *str, mbtk_apn_info_t *apn, uint8 *apn_type, mbtk_apn_req_type_enum *req_type);
+void mbtk_qser_apn_init(void);
+#endif
diff --git a/mbtk/mbtk_rild/src/mbtk_data_call.c b/mbtk/mbtk_rild/src/mbtk_data_call.c
new file mode 100644
index 0000000..3da0154
--- /dev/null
+++ b/mbtk/mbtk_rild/src/mbtk_data_call.c
@@ -0,0 +1,788 @@
+#if 1
+#include "mbtk_data_call.h"
+
+#define MBTK_RESULT_FAIL     -1
+#define MBTK_RESULT_SUCCESS  0
+
+#define MBTK_BUFF_SIZE         10
+#define MBTK_BUFF_STATE_INIT   "000000000"
+#define MBTK_BUFF_STATE_INIT_1 "010000000"
+#define MBTK_APN_STATE         "persist.qser.apn.state"
+#define MBTK_APN_AUTH_TYPE     "persist.qser.apn.auth"
+#define MBTK_APN_TYPE          "persist.qser.apn.type"
+
+#if (defined(MBTK_SG_SUPPORT) && defined(MBTK_ALL_CID_SUPPORT))
+//Setting apn parameters starts from channel 1
+#define MBTK_SET_APN_CID_MIN 1
+#else
+//Setting apn parameters starts from channel 2
+#define MBTK_SET_APN_CID_MIN 2
+#endif
+#define MBTK_SET_APN_CID_MAX 7
+
+/*cid 1 - 7*/
+mbtk_qser_apn_info_s apninfo_s[9];
+char apn_set_state[MBTK_BUFF_SIZE] = MBTK_BUFF_STATE_INIT;
+char apn_auth_type[MBTK_BUFF_SIZE] = MBTK_BUFF_STATE_INIT;
+mbtk_apn_auth_proto_enum apn_auth[9];
+int default_apn_cid = -1;
+bool default_pdp_state = false;
+bool apn_init_flag = false;
+
+int mbtk_get_default_apn_cid(void)
+{
+    return default_apn_cid;
+}
+
+void mbtk_set_default_apn_cid(int cid)
+{
+    default_apn_cid = cid;
+}
+
+bool mbtk_get_default_pdp_state(void)
+{
+    return default_pdp_state;
+}
+
+void mbtk_set_default_pdp_state(bool state, int cid)
+{
+    int default_cid = mbtk_get_default_apn_cid();
+#ifndef MBTK_SG_SUPPORT
+    if(default_cid == cid || cid == 1)
+#else
+    if(default_cid == cid)
+#endif
+    {
+        default_pdp_state = state;
+    }
+}
+
+
+int mbtk_check_default_pdp_state(int cid)
+{
+#ifdef MBTK_ALL_CID_SUPPORT
+    int default_cid = mbtk_get_default_apn_cid();
+#ifndef MBTK_SG_SUPPORT
+    if((default_cid == cid || cid == 1) && mbtk_get_default_pdp_state())
+#else
+    if(default_cid == cid && mbtk_get_default_pdp_state())
+#endif
+    {
+        LOGE("default pdp already open.default_cid [%d] cid [%d]", default_cid, cid);
+        return MBTK_RESULT_FAIL;
+    }
+#endif
+    return MBTK_RESULT_SUCCESS;
+}
+
+static int mbtk_get_cid(void)
+{
+    int i = 0;
+    for(i = MBTK_SET_APN_CID_MIN; i <= MBTK_SET_APN_CID_MAX; i++)
+    {
+        if(apn_set_state[i] == '0')
+        {
+            return i;
+        }
+    }
+
+    return MBTK_RESULT_FAIL;
+}
+
+
+int mbtk_check_cid(int cid)
+{
+    if(cid < MBTK_APN_CID_MIN || cid > MBTK_APN_CID_MAX)
+    {
+        LOGE("cid range error.");
+        return MBTK_RESULT_FAIL;
+    }
+
+#ifdef MBTK_ALL_CID_SUPPORT
+    if(apn_set_state[cid] != '1' && apn_set_state[cid] != '2')
+    {
+        LOGE("cid [%d] is not exist.", cid);
+        return MBTK_RESULT_FAIL;
+    }
+#endif
+    return MBTK_RESULT_SUCCESS;
+}
+
+int mbtk_qser_route_config(int cid, mbtk_ipv4_info_t *ipv4, mbtk_ipv6_info_t *ipv6)
+{
+    if(ipv4 == NULL || ipv6 == NULL)
+    {
+        LOGE("ip param is NULL.");
+        return MBTK_RESULT_FAIL;
+    }
+
+#ifdef MBTK_ALL_CID_SUPPORT
+    int default_cid = mbtk_get_default_apn_cid();
+#ifndef MBTK_SG_SUPPORT
+    if(default_cid != cid || cid != 1)
+#else
+    if(default_cid != cid)
+#endif
+#endif
+    {
+        LOGE("cid [%d] is default cid.", cid);
+        return MBTK_RESULT_FAIL;
+    }
+
+    char buf[1024] = {0};
+    char dns[128] = {0};
+    int offset = 0;
+    int fd = -1;
+    sprintf(buf, "route add default dev ccinet%d", cid -1);
+    system(buf);
+
+    memset(buf, 0x0, 1024);
+    memset(dns, 0x0, 128);
+    offset = sprintf(buf, "search lan\n");
+    if(ipv4->valid)
+    {
+        if(inet_ntop(AF_INET, &(ipv4->PrimaryDNS), dns, 32) == NULL) {
+            LOGE("[qser_data] PrimaryDNS error.");
+        } else {
+            LOGE("[qser_data] PrimaryDNS : %s", dns);
+        }
+        offset += sprintf(buf + offset, "nameserver %s\n", dns);
+        memset(dns, 0x0, 128);
+        if(inet_ntop(AF_INET, &(ipv4->SecondaryDNS), dns, 32) == NULL) {
+            LOGE("[qser_data] SecondaryDNS error.");
+        } else {
+            LOGE("[qser_data] SecondaryDNS : %s", dns);
+        }
+        offset += sprintf(buf + offset, "nameserver %s\n", dns);
+    }
+    if(ipv6->valid)
+    {
+        memset(dns, 0x0, 128);
+		if(ipv6_2_str(&(ipv6->PrimaryDNS), dns))
+        {
+			LOGE("[qser_data] PrimaryDNS error.");
+		} else {
+			LOGE("[qser_data] PrimaryDNS : %s", dns);
+		}
+        offset += sprintf(buf + offset, "nameserver %s\n", dns);
+        memset(dns, 0x0, 128);
+		if(ipv6_2_str(&(ipv6->SecondaryDNS), dns))
+        {
+			LOGE("[qser_data] SecondaryDNS error.");
+		} else {
+			LOGE("[qser_data] SecondaryDNS : %s", dns);
+		}
+        offset += sprintf(buf + offset, "nameserver %s\n", dns);
+    }
+
+    if(offset > 0)
+    {
+        fd = open("/tmp/resolv.conf", O_WRONLY | O_TRUNC);
+        if(fd < 0)
+        {
+            LOGE("[qser_data] mbtk_route_config : open fail.");
+            return MBTK_RESULT_FAIL;
+        }
+
+        int ret = write(fd, buf, offset);
+        if(ret < 0)
+        {
+            LOGE("[qser_data] mbtk_route_config : write fail.");
+        }
+
+        close(fd);
+    }
+
+    return MBTK_RESULT_SUCCESS;
+}
+
+
+static int mbtk_apn_check_num1(const uint8 *apn_type, const uint8 *apn_name, int cid)
+{
+    if(apn_type == NULL || apn_name == NULL)
+    {
+        LOGE("paran is NULL.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    if(cid == 1)
+    {
+        LOGE("no need check.");
+        return MBTK_RESULT_SUCCESS;
+    }
+
+    int apn_name_length = strlen((char *)apn_name);
+    //LOGD("qser_apn_info[0].apn_name: %s!", qser_apn_info[0].apn_name);
+    char *p = strstr((char *)apninfo_s[1].apn_name, "mnc");
+    if(p == NULL)
+    {
+        LOGE("not find !");
+    }
+    else
+    {
+        int default_apn_name_length = p - ((char *)apninfo_s[1].apn_name) -1;
+        LOGD("[qser_data] qser_check_apn_type default_apn_name_length = [%d]!", default_apn_name_length);
+        if(default_apn_name_length == apn_name_length)
+        {
+            int i = 0;
+            while(i < default_apn_name_length)
+            {
+                if(isalpha(apninfo_s[1].apn_name[i]) && isalpha(apn_name[i]))
+                {
+                    if(tolower(apninfo_s[1].apn_name[i]) != tolower(apn_name[i]))
+                    {
+                        break;
+                    }
+                }
+                else
+                {
+                    //LOGE("[qser_data] not char!");
+                    if(apninfo_s[1].apn_name[i] != apn_name[i])
+                    {
+                        break;
+                    }
+                }
+                
+                i++;
+            }
+
+            if(i == default_apn_name_length)
+            {
+                LOGE("apn_name is same!cid = [1].");
+                return MBTK_RESULT_FAIL;
+            }
+        }
+    }
+
+    return MBTK_RESULT_SUCCESS;
+}
+
+static int mbtk_apn_check_num2_7(const uint8 *apn_type, const uint8 *apn_name, mbtk_ip_type_enum ip_type,  int cid)
+{
+    if(apn_type == NULL || apn_name == NULL)
+    {
+        LOGE("paran is NULL.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    //check 2 - 7
+    int pdp_type_tmp = 1;
+    for (;pdp_type_tmp <= MBTK_APN_CID_MAX; pdp_type_tmp++)
+    {
+        if(pdp_type_tmp == cid)
+        {
+            continue;
+        }
+        if( (apn_set_state[pdp_type_tmp] == '1') || (apn_set_state[pdp_type_tmp] == '2') )
+        {
+            if(strcmp((char *)apninfo_s[pdp_type_tmp].apn_type, (char *)apn_type) == 0)
+            {
+                LOGE("apn_type is same!idx = [%d]", pdp_type_tmp);
+                return MBTK_RESULT_FAIL;
+            }
+            if (strcmp((char *)apninfo_s[pdp_type_tmp].apn_name, (char *)apn_name) == 0)
+            {
+                if(apninfo_s[pdp_type_tmp].ip_type == MBTK_IP_TYPE_IPV4V6 || ip_type == MBTK_IP_TYPE_IPV4V6)
+                {
+                    LOGE("[qser_data] apn_name is same and pdp_type is IPV4V6!idx = [%d]", pdp_type_tmp);
+                    return MBTK_RESULT_FAIL;
+                }
+
+                if(apninfo_s[pdp_type_tmp].ip_type == ip_type)
+                {
+                    LOGE("pdp_type is same and pdp_type is same!idx = [%d]", pdp_type_tmp);
+                    return MBTK_RESULT_FAIL;
+                }
+            }
+        }
+    }
+
+    return MBTK_RESULT_SUCCESS;
+}
+
+static int get_apn_user_pass_by_cid(mbtk_apn_info_t *apn)
+{
+    char prop_name[20] = {0};
+    char prop_data[300] = {0};
+    char local_ip[2] = {0};
+    char local_apn_name[128] = {0};
+    char local_apn_user[128] = {0};
+    char local_apn_pass[128] = {0};
+    char local_apn_auth[128] = {0};
+    sprintf(prop_name, "%s_%d",MBTK_APN_PROP,apn->cid);
+    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data))
+    {
+        int i = 0;
+        int data_len = strlen(prop_data);
+        for(; i < data_len; i++)
+        {
+            if(prop_data[i] == ',')
+            {
+                prop_data[i] = ' ';
+            }
+        }
+        //LOGD("prop_data [%s].", prop_data);
+        int ret = sscanf(prop_data, " %s %s %s %s %s ", local_ip, local_apn_name, local_apn_user, local_apn_pass, local_apn_auth);
+        if(ret != 5)
+        {
+            LOGE("get user pass fail!ret [%d].", ret);
+            return MBTK_RESULT_FAIL;
+        }
+        
+        mbtk_ip_type_enum local_ip_type = (mbtk_ip_type_enum)atoi(&local_ip[0]);
+
+        if(apn->ip_type != local_ip_type || strcmp((char *)apn->apn, local_apn_name))
+        {
+            LOGE("APN Changed, not get user/pass/auth.");
+            return MBTK_RESULT_FAIL;
+        }
+
+        if(memcmp(local_apn_user, "NULL", 4))
+        { // Not "NULL"
+            memcpy(apn->user, local_apn_user, strlen(local_apn_user)); // user
+        }
+
+        if(memcmp(local_apn_pass, "NULL", 4))
+        { // Not "NULL"
+            memcpy(apn->pass, local_apn_pass, strlen(local_apn_pass)); // pass
+        }
+
+        return MBTK_RESULT_SUCCESS;
+    }
+    return MBTK_RESULT_FAIL;
+}
+
+
+int mbtk_qser_apn_del(int cid)
+{
+    char buff[32] = {0};
+    int ret = mbtk_check_cid(cid);
+    if(ret < 0)
+    {
+        LOGE("cid is exist");
+        return MBTK_RESULT_FAIL;
+    }
+
+    apn_auth_type[cid] = '0';
+    property_set(MBTK_APN_AUTH_TYPE, (char *)apn_auth_type);
+
+    if(apn_set_state[cid] == '2')
+    {
+        mbtk_set_default_apn_cid(-1);
+    }
+    apn_set_state[cid] = '0';
+    property_set(MBTK_APN_STATE, (char *)apn_set_state);
+
+    sprintf(buff, "%s%d", MBTK_APN_TYPE, cid);
+    property_set(buff, "NULL");
+    
+    memset(&apninfo_s[cid], 0x0, sizeof(mbtk_qser_apn_info_s));
+    return MBTK_RESULT_SUCCESS;
+}
+/*
+AT+CGDCONT?
++CGDCONT: 1,"IPV4V6","cmnet.MNC000.MCC460.GPRS","10.131.67.146 254.128.0.0.0.0.0.0.0.1.0.2.200.2.158.0",0,0,,,,
+
++CGDCONT: 8,"IPV4V6","IMS","254.128.0.0.0.0.0.0.0.1.0.2.200.2.160.160",0,0,0,2,1,1
+
+OK
+*/
+
+int mbtk_qser_req_apn_get(void *data, int *data_len, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_multiline("AT+CGDCONT?", "+CGDCONT:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    int tmp_int;
+    char *tmp_str = NULL;
+    char buff[32] = {0};
+    uint8 apn_type[128] = {0};
+    /*
+        <apn_num[1]><cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth[1]><apn_type_len[2]><apn_type_len>...
+                    <cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth[1]><apn_type_len[2]><apn_type_len>
+    */
+    uint8* apn_num = (uint8*)data;
+    uint8* data_ptr = (uint8*)((uint8*)data + sizeof(uint8)); // Jump apn_num[1]
+    mbtk_apn_info_t apn;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int); // cid
+        if (err < 0)
+        {
+            goto exit;
+        }
+        // Only get CID 1-7
+        if(apn_set_state[tmp_int] != '0')
+        {
+            memset(&apn, 0x0, sizeof(mbtk_apn_info_t));
+            apn.cid = tmp_int;
+            *data_ptr++ = (uint8)tmp_int; // cid
+
+            err = at_tok_nextstr(&line, &tmp_str);// ip type
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(!strcasecmp(tmp_str, "IP")) {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_IP;
+                apn.ip_type = MBTK_IP_TYPE_IP;
+            } else if(!strcasecmp(tmp_str, "IPV6")) {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_IPV6;
+                apn.ip_type = MBTK_IP_TYPE_IPV6;
+            } else if(!strcasecmp(tmp_str, "IPV4V6")) {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_IPV4V6;
+                apn.ip_type = MBTK_IP_TYPE_IPV4V6;
+            } else {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_PPP;
+                apn.ip_type = MBTK_IP_TYPE_PPP;
+            }
+
+            err = at_tok_nextstr(&line, &tmp_str); // apn
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(str_empty(tmp_str)) {
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+            } else {
+                uint16_2_byte((uint16)strlen(tmp_str), data_ptr, false);
+                data_ptr += sizeof(uint16);
+                memcpy(data_ptr, tmp_str, strlen(tmp_str));
+                data_ptr += strlen(tmp_str);
+                memcpy(apn.apn, tmp_str, strlen(tmp_str));
+            }
+
+            if(get_apn_user_pass_by_cid(&apn)) {
+                // user
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+
+                // pass
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+
+                // auth
+                *data_ptr++ = (uint8)MBTK_APN_AUTH_PROTO_DEFAULT;
+            } else {
+                // user
+                if(str_empty(apn.user)) {
+                    uint16_2_byte((uint16)0, data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                } else {
+                    uint16_2_byte((uint16)strlen((char *)apn.user), data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                    memcpy(data_ptr, apn.user, strlen((char *)apn.user));
+                    data_ptr += strlen((char *)apn.user);
+                }
+
+                // pass
+                if(str_empty(apn.pass)) {
+                    uint16_2_byte((uint16)0, data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                } else {
+                    uint16_2_byte((uint16)strlen((char *)apn.pass), data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                    memcpy(data_ptr, apn.pass, strlen((char *)apn.pass));
+                    data_ptr += strlen((char *)apn.pass);
+                }
+
+                // auth
+                switch(apn_auth_type[apn.cid])
+                {
+                    case '0':
+                    {
+                        *data_ptr++ = (uint8)MBTK_APN_AUTH_PROTO_DEFAULT;
+                        break;
+                    }
+                    case '1':
+                    {
+                        *data_ptr++ = (uint8)MBTK_APN_AUTH_PROTO_NONE;
+                        break;
+                    }
+                    case '2':
+                    {
+                        *data_ptr++ = (uint8)MBTK_APN_AUTH_PROTO_PAP;
+                        break;
+                    }
+                    case '3':
+                    {
+                        *data_ptr++ = (uint8)MBTK_APN_AUTH_PROTO_CHAP;
+                        break;
+                    }
+                    default:
+                    {
+                        *data_ptr++ = (uint8)MBTK_APN_AUTH_PROTO_DEFAULT;
+                        break;
+                    }
+                }
+            }
+
+            //apn_type
+            memset(buff, 0x0, 32);
+            sprintf(buff, "%s%d", MBTK_APN_TYPE, apn.cid);
+            property_get(buff, (char *)apn_type, "");
+            if(str_empty(apn_type))
+            {
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+            } else
+            {
+                uint16_2_byte((uint16)strlen((char *)apn_type), data_ptr, false);
+                data_ptr += sizeof(uint16);
+                memcpy(data_ptr, apn_type, strlen((char *)apn_type));
+                data_ptr += strlen((char *)apn_type);
+            }
+
+            if(apn_init_flag)
+            {
+                apn_init_flag = false;
+                mbtk_qser_apn_save(apn, apn_type, false);
+            }
+            (*apn_num)++;
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    *data_len = data_ptr - (uint8*)data;
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+int mbtk_qser_apn_save(mbtk_apn_info_t apn, const uint8 *apn_type, bool state_save)
+{
+    if(apn_type == NULL)
+    {
+        LOGE("param is error.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    char buff[32] = {0};
+    int cid = apn.cid;
+    
+    memset(&apninfo_s[cid], 0x0, sizeof(mbtk_qser_apn_info_s));
+    apninfo_s[cid].cid = apn.cid;
+    apninfo_s[cid].ip_type = apn.ip_type;
+    apninfo_s[cid].auth_proto = apn_auth[cid];
+    if(strlen((char *)apn.apn))
+    {
+        memcpy(apninfo_s[cid].apn_name, apn.apn, strlen((char *)apn.apn));
+    }
+    if(strlen((char *)apn.user))
+    {
+        memcpy(apninfo_s[cid].user_name, apn.user, strlen((char *)apn.user));
+    }
+    if(strlen((char *)apn.pass))
+    {
+        memcpy(apninfo_s[cid].user_pass, apn.pass, strlen((char *)apn.pass));
+    }
+    if(strlen((char *)apn_type))
+    {
+        memcpy(apninfo_s[cid].apn_type, apn_type, strlen((char *)apn_type));
+        if(state_save)
+        {
+            sprintf(buff, "%s%d", MBTK_APN_TYPE, apn.cid);
+            property_set(buff, (char *)apn_type);
+        }
+    }
+
+    if(state_save)
+    {
+        if(strcmp((char *)apn_type, "iot_default") == 0)
+        {
+            apn_set_state[cid] = '2';
+            mbtk_set_default_apn_cid(cid);
+        }
+        else
+        {
+            apn_set_state[cid] = '1';
+        }
+        property_set(MBTK_APN_STATE, (char *)apn_set_state);
+
+        apn_auth_type[cid] = (char)apn_auth[cid] + '0';
+        property_set(MBTK_APN_AUTH_TYPE, (char *)apn_auth_type);
+    }
+    return MBTK_RESULT_SUCCESS;
+}
+
+int mbtk_strdata_to_apn(const uint8 *str, mbtk_apn_info_t *apn, uint8 *apn_type, mbtk_apn_req_type_enum *req_type)
+{
+    if(str == NULL || apn == NULL || apn_type == NULL)
+    {
+        LOGE("param is error.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    // <cid[1]><ip_type[1]><req_type[1]><auth[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth_len[2]><apn_type[2]>
+    int len = 0;
+    int ret = -1;
+    memset(apn, 0x0, sizeof(mbtk_apn_info_t));
+    
+    // cid
+    apn->cid = (int)*str++;
+
+    // ip_type
+    apn->ip_type = (mbtk_ip_type_enum)(*str++);
+
+    //req_type
+    *req_type = (mbtk_apn_req_type_enum)(*str++);
+    if((*req_type) == MBTK_APN_REQ_TYPE_ADD)
+    {
+        apn->cid = mbtk_get_cid();
+        if(apn->cid < 0)
+        {
+            LOGE("no enough cid.");
+            return MBTK_RESULT_FAIL;
+        }
+    }
+    else
+    {
+        ret = mbtk_check_cid(apn->cid);
+        if(ret < 0)
+        {
+            LOGE("cid is error.");
+            return MBTK_RESULT_FAIL;
+        }
+        
+#ifndef MBTK_SG_SUPPORT
+        if(apn->cid == 1)
+        {
+            LOGE("cid 1 no support set.");
+            return MBTK_RESULT_FAIL;
+        }
+#endif
+    }
+
+    // auth
+    apn_auth[apn->cid] = (mbtk_apn_auth_proto_enum)(*str++);
+    if(apn_auth[apn->cid] == MBTK_APN_AUTH_PROTO_NONE || apn_auth[apn->cid] == MBTK_APN_AUTH_PROTO_DEFAULT)
+    {
+        memcpy(apn->auth,"NONE",strlen("NONE")+1);
+    }
+    else if(apn_auth[apn->cid] == MBTK_APN_AUTH_PROTO_PAP)
+    {
+        memcpy(apn->auth,"PAP",strlen("PAP")+1);
+    }
+    else if(apn_auth[apn->cid] == MBTK_APN_AUTH_PROTO_CHAP)
+    {
+        memcpy(apn->auth,"CHAP",strlen("CHAP")+1);
+    }
+    #if 0
+    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP_CHAP)
+    {
+        //NOT SUPPORT
+    }
+    #endif
+    else
+    {
+        LOGE("auth input error!");
+        return MBTK_RESULT_FAIL;
+    }
+    
+    // apn
+    len = byte_2_uint16(str, false);
+    str += sizeof(uint16);
+    if(len > 0)
+    {
+        memcpy(apn->apn, str, len);
+        str += len;
+    }
+
+    // user
+    len = byte_2_uint16(str, false);
+    str += sizeof(uint16);
+    if(len > 0)
+    {
+        memcpy(apn->user, str, len);
+        str += len;
+    }
+
+    // pass
+    len = byte_2_uint16(str, false);
+    str += sizeof(uint16);
+    if(len > 0)
+    {
+        memcpy(apn->pass, str, len);
+        str += len;
+    }
+
+    // auth_type
+    len = byte_2_uint16(str, false);
+    str += sizeof(uint16);
+    if(len > 0)
+    {
+        memcpy(apn_type, str, len);
+        str += len;
+    }
+
+    ret = mbtk_apn_check_num1(apn_type, apn->apn, apn->cid);
+    if(ret < 0)
+    {
+        LOGE("num1 check error!");
+        return MBTK_RESULT_FAIL;
+    }
+
+    ret = mbtk_apn_check_num2_7(apn_type, apn->apn, apn->ip_type, apn->cid);
+    if(ret < 0)
+    {
+        LOGE("num2_7 check error!");
+        return MBTK_RESULT_FAIL;
+    }
+
+    LOGD("APN : %d, %d, %s, %s, %s, %s.", apn->cid,
+                                        apn->ip_type,
+                                        (str_empty(apn->apn) ? "NULL" : apn->apn),
+                                        (str_empty(apn->user) ? "NULL" : apn->user),
+                                        (str_empty(apn->pass) ? "NULL" : apn->pass),
+                                        (str_empty(apn->auth) ? "NULL" : apn->auth),
+                                        (str_empty(apn_type) ? "NULL" : apn_type));
+    return MBTK_RESULT_SUCCESS;
+}
+
+void mbtk_qser_apn_init(void)
+{
+    LOGD("enter mbtk_qser_apn_init.");
+    apn_init_flag = true;
+#ifdef MBTK_SG_SUPPORT
+    property_get(MBTK_APN_STATE, (char *)apn_set_state, MBTK_BUFF_STATE_INIT);
+#else
+    property_get(MBTK_APN_STATE, (char *)apn_set_state, MBTK_BUFF_STATE_INIT_1);
+#endif
+    LOGD("get apn_set_state[%s].", apn_set_state);
+
+    int i = 0;
+    for(; i < MBTK_BUFF_SIZE; i++)
+    {
+        if(apn_set_state[i] == '2')
+        {
+            mbtk_set_default_apn_cid(i);
+            break;
+        }
+    }
+
+    property_get(MBTK_APN_AUTH_TYPE, (char *)apn_auth_type, MBTK_BUFF_STATE_INIT);
+    LOGD("get apn_auth_type[%s].", apn_auth_type);
+
+    mbtk_get_apn_send_pack();
+}
+#endif
diff --git a/mbtk/mbtk_rild/src/mbtk_info_server.c b/mbtk/mbtk_rild/src/mbtk_info_server.c
index c253439..bc43cd4 100755
--- a/mbtk/mbtk_rild/src/mbtk_info_server.c
+++ b/mbtk/mbtk_rild/src/mbtk_info_server.c
@@ -22,6 +22,7 @@
 #include "mbtk_led.h"
 #include "cust_info.h"
 #include "mbtk_device.h"
+#include "mbtk_data_call.h"
 
 typedef struct {
     uint32 band_gsm;
@@ -5026,6 +5027,69 @@
                 }
                 break;
             }
+            case MBTK_INFO_ID_NET_QSER_APN_REQ:
+            {
+                if(pack->data_len == 0 || pack->data == NULL)
+                {
+                    uint8 buff[SOCK_MSG_LEN_MAX];
+                    memset(buff, 0, SOCK_MSG_LEN_MAX);
+                    int data_len = 0;
+                    if(mbtk_qser_req_apn_get(buff, &data_len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOGE("Get APN fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_APN_RSP, buff, data_len);
+                    }
+                }
+                else
+                {
+                    const uint8* ptr = pack->data;
+                    mbtk_apn_info_t apn;
+                    mbtk_apn_req_type_enum req_type = MBTK_APN_REQ_TYPE_SET;
+                    uint8 apn_type[MBTK_QSER_APN_NAME_SIZE] = {0};
+                    int ret = mbtk_strdata_to_apn(pack->data, &apn, apn_type, &req_type);
+                    if(ret < 0)
+                    {
+                        LOGE("mbtk_strdata_to_apn fail. ret = [%d]", ret);
+                        err = MBTK_INFO_ERR_REQ_PARAMETER;
+                    }
+                    else
+                    {
+                        if(req_apn_set(&apn, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                        {
+                            if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                err = MBTK_INFO_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_INFO_ERR_UNKNOWN;
+                            }
+                            LOGE("Set APN fail.");
+                        }
+                        else
+                        {
+                            // Save apn.
+                            apn_prop_set(&apn);
+                            mbtk_qser_apn_save(apn, apn_type, true);
+                            if(req_type == MBTK_APN_REQ_TYPE_ADD)
+                            {
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_QSER_APN_RSP, (void *)&apn.cid, 1);
+                            }
+                            else
+                            {
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_QSER_APN_RSP, NULL, 0);
+                            }
+                        }
+                    }
+                }
+
+                break;
+            }
             case MBTK_INFO_ID_NET_APN_DEL_REQ:
             {
                 if(pack->data_len == 0 || pack->data == NULL)
@@ -5036,18 +5100,31 @@
                 else
                 {
                     int profile = pack->data[0];
-                    if(req_apn_del(profile, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    if(cid_active[profile] == 1)
                     {
-                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
-                            err = MBTK_INFO_ERR_CME + cme_err;
-                        } else {
-                            err = MBTK_INFO_ERR_UNKNOWN;
-                        }
-                        LOG("Delete apn fail.");
+                        LOGD("cid pdp already open.");
+                        err = MBTK_INFO_ERR_CID_EXIST;
+                    }
+                    if(mbtk_qser_apn_del(profile) < 0)
+                    {
+                        LOGD("del error.");
+                        err = MBTK_INFO_ERR_REQ_PARAMETER;
                     }
                     else
                     {
-                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_APN_DEL_RSP, NULL, 0);
+                        if(req_apn_del(profile, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                        {
+                            if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                err = MBTK_INFO_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_INFO_ERR_UNKNOWN;
+                            }
+                            LOG("Delete apn fail.");
+                        }
+                        else
+                        {
+                            pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_APN_DEL_RSP, NULL, 0);
+                        }
                     }
                 }
                 break;
@@ -5069,10 +5146,17 @@
                     int cid = pack->data[1];
                     int reconn = 0;
 
+#if 0
                     if(cid < MBTK_APN_CID_MIN || cid > MBTK_APN_CID_MAX) {
                         err = MBTK_INFO_ERR_CID;
                         break;
                     }
+#endif
+                    if(mbtk_check_cid(cid) < 0)
+                    {
+                        err = MBTK_INFO_ERR_CID;
+                        break;
+                    }
 
                     LOG("cid_active[%d] = %d", cid, cid_active[cid]);
                     memset(&cgact_wait, 0, sizeof(info_cgact_wait_t));
@@ -5096,6 +5180,12 @@
                                 break;
                             }
 
+                            if(mbtk_check_default_pdp_state(cid))
+                            {
+                                err = MBTK_INFO_ERR_UNSUPPORTED;
+                                break;
+                            }
+
                             data_call_reconn:
                             //mbtk wyq for data_call_ex add end
                             cgact_wait.waitting = true;
@@ -5240,6 +5330,8 @@
                                     }
 
                                     cid_active[cid] = 1;
+                                    mbtk_set_default_pdp_state(true, cid);
+                                    mbtk_qser_route_config(cid, &ipv4, &ipv6);
                                     if(cli_info->fd != DATA_CALL_BOOTCONN_FD)
                                     {
                                         pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_DATA_CALL_RSP, NULL, 0);
@@ -5280,6 +5372,7 @@
                                     LOGD("Config %s IPv4 0 success.", dev);
                                 }
                                 cid_active[cid] = 0;
+                                mbtk_set_default_pdp_state(false, cid);
                                 pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_DATA_CALL_RSP, NULL, 0);
                                 break;
                             }
@@ -5321,6 +5414,7 @@
                                 }
 #endif
                                 cid_active[cid] = 0;
+                                mbtk_set_default_pdp_state(false, cid);
                                 pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_DATA_CALL_RSP, NULL, 0);
                             }
                             break;
@@ -6253,10 +6347,12 @@
     if(act)
     {
         cid_active[cid] = 1;
+        mbtk_set_default_pdp_state(true, cid);
     }
     else
     {
         cid_active[cid] = 0;
+        mbtk_set_default_pdp_state(false, cid);
     }
     char dev[20] = {0};
     sprintf(dev, "ccinet%d", cid - 1);
@@ -6536,8 +6632,14 @@
                     }
                     else
                     {
-                        free(pack->data);
-                        free(item->cli_info);
+                        if(pack->data != NULL)
+                        {
+                            free(pack->data);
+                        }
+                        if(item->cli_info)
+                        {
+                            free(item->cli_info);
+                        }
                     }
                 }
                 at_process = false;
@@ -6945,6 +7047,29 @@
     }
 }
 
+int mbtk_get_apn_send_pack(void)
+{
+    sock_client_info_t *info = (sock_client_info_t*)malloc(sizeof(sock_client_info_t));
+    if(info == NULL)
+    {
+        LOG("clinent_info  malloc() fail.");
+        return -1;
+    }
+    memset(info, 0, sizeof(sock_client_info_t));
+    info->fd = DATA_CALL_APN_GET_FD;
+
+    mbtk_info_pack_t* pack = mbtk_info_pack_creat(MBTK_INFO_ID_NET_QSER_APN_REQ);
+    if(pack == NULL)
+    {
+        free(info);
+        LOG("Packet malloc() fail.");
+        return -1;
+    }
+
+    send_pack_to_queue(info, pack);
+    return 0;
+}
+
 int mbtk_info_server_start()
 {
     signal(SIGPIPE, SIG_IGN);
@@ -7063,6 +7188,8 @@
 
     pthread_attr_destroy(&thread_attr);
 
+    mbtk_qser_apn_init();
+
     LOG("MBTK Information Server Start...");
 
     return 0;