[Feature][API-751][GSW165/167/172/173][T8TSK-135][Data]RIL3.0 soceket broadcast optimistion,Data part

Change-Id: I298bc248cbfbad881b84dda5edd4eb28c3781f73
diff --git a/src/lynq/framework/lynq-ril-service/src/data/data.cpp b/src/lynq/framework/lynq-ril-service/src/data/data.cpp
index 9a06968..8d81825 100755
--- a/src/lynq/framework/lynq-ril-service/src/data/data.cpp
+++ b/src/lynq/framework/lynq-ril-service/src/data/data.cpp
@@ -805,7 +805,7 @@
                 writeStringToParcel(urc_p, apn_table[i].apn);
                 writeStringToParcel(urc_p, apn_table[i].apntype);
                 writeStringToParcel(urc_p, apn_table[i].ifaceName);
-                android::LYNQ_RIL_urcBroadcast(urc_p);
+                android::LYNQ_RIL_urcBroadcast(urc_p,LYNQ_URC_DATA_CALL_STATUS_IND);
                 RLOGD("apn:%s,apntype:%s",apn_table[i].apn,apn_table[i].apntype);
                 return -1;
             }
@@ -843,7 +843,7 @@
             writeStringToParcel(urc_p, apn_table[i].apn);
             writeStringToParcel(urc_p, apn_table[i].apntype);
             writeStringToParcel(urc_p, apn_table[i].ifaceName);
-            android::LYNQ_RIL_urcBroadcast(urc_p);
+            android::LYNQ_RIL_urcBroadcast(urc_p,LYNQ_URC_DATA_CALL_STATUS_IND);
             RLOGD("apn:%s,apntype:%s",apn_table[i].apn,apn_table[i].apntype);
             return -1;
         }
diff --git a/src/lynq/framework/lynq-ril-service/src/data/data_gdbus.cpp b/src/lynq/framework/lynq-ril-service/src/data/data_gdbus.cpp
index 7e8c6de..5facfcf 100755
--- a/src/lynq/framework/lynq-ril-service/src/data/data_gdbus.cpp
+++ b/src/lynq/framework/lynq-ril-service/src/data/data_gdbus.cpp
@@ -83,7 +83,7 @@
     p.writeInt32(lynq_request_id);
     p.writeInt32(0);
     writeStringToParcel(p,reason);
-    android::LYNQ_RIL_urcBroadcast(p);
+    android::LYNQ_RIL_urcBroadcast(p,lynq_request_id);
     return 0;
 }
 
@@ -132,7 +132,7 @@
                     p.writeInt32 (0);//temporary plan
                     p.writeInt32(PDN_DISCONNECTED);
                     writeStringToParcel(p,urc_response->apnType);
-                    android::LYNQ_RIL_urcBroadcast(p);
+                    android::LYNQ_RIL_urcBroadcast(p,LYNQ_URC_DATA_CALL_STATUS_IND);
                     RLOGD("removed apn:%s,apntype:%s",apn_table[i].apn,apn_table[i].apntype);
 #ifdef LED_SUPPORT
                     if(apn_count==0)
@@ -178,7 +178,7 @@
                 writeStringToParcel(p,urc_response->apnName);
                 writeStringToParcel(p,urc_response->apnType);
                 writeStringToParcel(p,urc_response->ifname);
-                android::LYNQ_RIL_urcBroadcast(p);
+                android::LYNQ_RIL_urcBroadcast(p,LYNQ_URC_DATA_CALL_STATUS_IND);
 #ifdef LED_SUPPORT
                 mbtk_netled_state_update(GPIO_NETLED_PPP_CONNECT); 
 #endif
@@ -220,7 +220,7 @@
                             writeStringToParcel(p,apn_t);
                             writeStringToParcel(p,apnType_t);
                             writeStringToParcel(p,iface_t);
-                            android::LYNQ_RIL_urcBroadcast(p);
+                            android::LYNQ_RIL_urcBroadcast(p,LYNQ_URC_DATA_CALL_STATUS_IND);
                         }
                         break;
                     }
@@ -260,7 +260,7 @@
                         writeStringToParcel(p,urc_response->apnName);
                         writeStringToParcel(p,urc_response->apnType);
                         writeStringToParcel(p,urc_response->ifname);
-                        android::LYNQ_RIL_urcBroadcast(p);
+                        android::LYNQ_RIL_urcBroadcast(p,LYNQ_URC_DATA_CALL_STATUS_IND);
                     }
                     else
                     {
@@ -315,7 +315,7 @@
                 writeStringToParcel(p,apn_t);
                 writeStringToParcel(p,apnType_t);
                 writeStringToParcel(p,iface_t);
-                android::LYNQ_RIL_urcBroadcast(p);
+                android::LYNQ_RIL_urcBroadcast(p,LYNQ_URC_DATA_CALL_STATUS_IND);
             }
         }
     }
diff --git a/src/lynq/framework/lynq-ril-service/src/ril.cpp b/src/lynq/framework/lynq-ril-service/src/ril.cpp
index c3824fa..099af44 100755
--- a/src/lynq/framework/lynq-ril-service/src/ril.cpp
+++ b/src/lynq/framework/lynq-ril-service/src/ril.cpp
@@ -6151,7 +6151,11 @@
         case RIL_UNSOL_CALL_INFO_INDICATION:
 #ifdef ECALL_SUPPORT
         case RIL_UNSOL_ECALL_INDICATIONS://9502        
-#endif        
+#endif       
+       /*Data*/
+        case LYNQ_URC_DATA_CALL_STATUS_IND: 
+        case LYNQ_URC_MODIFY_APNDB:
+        case LYNQ_URC_RESET_APNDB:
             break;
         default:
             return false;
diff --git a/src/lynq/lib/liblynq-data/lynq_data.cpp b/src/lynq/lib/liblynq-data/lynq_data.cpp
index 5473fb2..c04a373 100755
--- a/src/lynq/lib/liblynq-data/lynq_data.cpp
+++ b/src/lynq/lib/liblynq-data/lynq_data.cpp
@@ -15,8 +15,10 @@
 #include <sys/time.h>
 #include <include/lynq_uci.h>
 #include <errno.h>
+#include <vector>
+#include "lynq_data_urc.h"
+
 #define LYNQ_SERVICE_PORT 8088
-#define LYNQ_URC_SERVICE_PORT 8086
 #define LYNQ_REC_BUF 8192
 #define LYNQ_REQUEST_PARAM_BUF 8192
 #define LYQN_SEDN_BUF 1024*8+sizeof(int)*3
@@ -24,9 +26,6 @@
 
 #define LYNQ_DATA_UCI_BUF 258
 
-
-
-
 using ::android::Parcel;
 typedef struct{
     int uToken;
@@ -56,16 +55,19 @@
 
 int lynq_client_sockfd = 0;
 int Global_uToken = 0;
-bool data_urc_recive_status = 1;
+
 int lynq_data_call_change_id = -1;
 pthread_t lynq_data_tid =-1;
 static pthread_mutex_t s_data_call_state_change_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t s_data_call_state_change_cond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t s_pdn_change_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t s_pdn_change_cond = PTHREAD_COND_INITIALIZER;
+
 static pthread_mutex_t s_lynq_apn_change_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t s_lynq_apn_change_cond = PTHREAD_COND_INITIALIZER;
 
+pthread_t data_list_urc_vector_tid = -1;
+int data_urc_vector_status = 0;
+static pthread_mutex_t s_lynq_urc_vector_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_lynq_urc_vector_cond = PTHREAD_COND_INITIALIZER;
 /**g_lynq_data_sendto_mutex
 * @brief mark data send request mutex
 */
@@ -82,6 +84,8 @@
 */
 char g_lynq_apn_result[1024] = {};
 
+static std::vector<int> s_data_urc_wait_list;
+
 typedef struct
 {
     char apn[LYNQ_APN_MAX_LEN];
@@ -93,16 +97,7 @@
 lynq_apn_t lynq_apn_table[LYNQ_APN_CHANNEL_MAX] = {};
 lynq_data_call_response_v11_t lynq_data_call_lists[LYNQ_APN_CHANNEL_MAX] = {};
 int lynq_data_call = 0;
-int millli_sleep_with_restart(int millisecond)
-{
-    int left = millisecond*1000;
-    while (left > 0) 
-    { 
-        left = usleep(left);
-    }
 
-    return 0;
-}
 int getLynqApnID(char apnType[])
 {
     int ret = 0;
@@ -115,6 +110,7 @@
     }
     return -1;
 }
+
 void updateApnTable(lynq_apn_t *apn_table,char apn[],char apntype[],char ifaceName[])
 {
     LYDBGLOG("[updateApnTable] apn:%s,apntype:%s,ifaceName:%s",apn,apntype,ifaceName);
@@ -130,6 +126,7 @@
     apn_table->hasUsed = 1;
     return;
 }
+
 void cleanOnceApnTable(int apnId)
 {
     LYDBGLOG("apn id:%d",apnId);
@@ -207,9 +204,9 @@
 int waitPdnChange()
 {
     int ret = 0;
-    pthread_mutex_lock(&s_pdn_change_mutex);
-    ret = pthread_cond_wait(&s_pdn_change_cond,&s_pdn_change_mutex);
-    pthread_mutex_unlock(&s_pdn_change_mutex);
+    pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+    ret = pthread_cond_wait(&s_lynq_urc_vector_cond,&s_lynq_urc_vector_mutex);
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
     return ret;
 }
 int waitDataCallstateChange(int mtime)
@@ -238,9 +235,9 @@
 }
 void sendSignalPdnChange()
 {
-    pthread_mutex_lock(&s_pdn_change_mutex);
-    pthread_cond_signal(&s_pdn_change_cond);
-    pthread_mutex_unlock(&s_pdn_change_mutex);
+    pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+    pthread_cond_signal(&s_lynq_urc_vector_cond);
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
     return;
 }
 
@@ -301,7 +298,6 @@
     return strndup16to8(s16, stringlen);
 }
 
-
 /*Warren add for T800 platform 2021/11/19 start*/
 int lynq_socket_client_start()
 {
@@ -335,144 +331,146 @@
     }
     return 0;
 }
-void *thread_urc_recv(void *parg)
+
+bool is_support_urc(int urc_id)
 {
-    int socket_fd = (int64_t)parg;
-    int len=0;
-    socklen_t addr_len=0;
-    uint8_t *dataLength = NULL;
-    char urc_data[LYNQ_REC_BUF];
+    switch(urc_id)
+    {
+        case LYNQ_URC_DATA_CALL_STATUS_IND:
+
+        case LYNQ_URC_MODIFY_APNDB:
+        case LYNQ_URC_RESET_APNDB:
+            return true;                
+        default:
+            return false;
+    }    
+}
+
+void urc_msg_process(Parcel *p)
+{
+    int len;
+    int resp_type;
+    int urcid;
+    int slot_id;
+
+    int pdnState = 0;
     char apn[LYNQ_APN_MAX_LEN];
     char apnType[LYNQ_APN_TYPE_MAX_LEN];
-    int pdnState = 0;
     char ifaceName[LYNQ_IFACE_NAME_MAX_LEN];
-    int slot_id = -1;
-    int resp_type = -1;
-    int urcid = -1;
     char *urc_msg = NULL;
-    Parcel *p = NULL;
-    struct sockaddr_in dest_addr;
-    LYINFLOG("thread_urc_recv in running....\n");
-    while(data_urc_recive_status)
+
+    int size = p->dataSize();
+    p->readInt32(&resp_type);
+    p->readInt32(&urcid);
+    p->readInt32(&slot_id);
+    LYINFLOG("data lib recv urc:resp_type=%d,urcid=%d,slot_id=%d,size=%d\n",resp_type,urcid,slot_id,size);
+    switch(urcid)
     {
-        bzero(urc_data,LYNQ_REC_BUF);
-        //get data msg
-        len = recvfrom(socket_fd,urc_data,LYNQ_REC_BUF,0,(struct sockaddr *)&dest_addr,&addr_len);
-        if(len <= 0)
-        {
-            perror("thread_urc_recv step2 fail:");
-            millli_sleep_with_restart(1);
-            break;
-        }
-        LYDBGLOG("=====>urc data len<=====:%d\n",len);
-        p = new Parcel();
-        if(p==NULL)
-        {
-            RLOGD("new parcel failure!!!");
-            break;
-        }
-        p->setData((uint8_t *)urc_data,len); // p.setData((uint8_t *) buffer, buflen);
-        p->setDataPosition(0);
-        if(p->dataAvail() > 0)
-        {
-            p->readInt32(&resp_type);
-            p->readInt32(&urcid);
-            p->readInt32(&slot_id);
-            //LYDBGLOG("*******Warren test*******:resp_type=%d,urcid=%d,slot_id=%d\n",resp_type,urcid,slot_id);
-            switch (urcid)
+        case LYNQ_URC_DATA_CALL_STATUS_IND:
+            p->readInt32(&pdnState);
+            bzero(apn,LYNQ_APN_MAX_LEN);
+            bzero(apnType,LYNQ_APN_TYPE_MAX_LEN);
+            bzero(ifaceName,LYNQ_IFACE_NAME_MAX_LEN);
+            if(pdnState!=4)//PDN_DISCONNECTED
             {
-                case 9003://LYNQ_URC_DATA_CALL_STATUS_IND
-                {
-                    LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d\n",resp_type,urcid,slot_id);
-                    p->readInt32(&pdnState);
-                    bzero(apn,LYNQ_APN_MAX_LEN);
-                    bzero(apnType,LYNQ_APN_TYPE_MAX_LEN);
-                    bzero(ifaceName,LYNQ_IFACE_NAME_MAX_LEN);
-                    if(pdnState!=4)//PDN_DISCONNECTED
-                    {
-                        urc_msg = strdupReadString_p(p);
-                        int len = strlen(urc_msg);
-                        if(len < LYNQ_APN_MAX_LEN-1)
-                        {
-                            memcpy(apn,urc_msg,len+1);
-                        }
-                        urc_msg = strdupReadString_p(p);
-                        len = strlen(urc_msg);
-                        if(len < LYNQ_APN_TYPE_MAX_LEN-1)
-                        {
-                            memcpy(apnType,urc_msg,len+1);
-                        }
-                        urc_msg = strdupReadString_p(p);
-                        len = strlen(urc_msg);
-                        if(len < LYNQ_IFACE_NAME_MAX_LEN-1)
-                        {
-                            memcpy(ifaceName,urc_msg,strlen(urc_msg)+1);
-                        }
-                        //sendSignalDataCallStateChange();
-                        int apnId = getLynqApnID(apnType);
-                        if(apnId >= 0)
-                        {
-                            if(lynq_apn_table[apnId].hasTimeout==1)
-                            {
-                                LYERRLOG("apn:%s has time out",lynq_apn_table[apnId].apn);
-                                lynq_deactive_data_call(&apnId);
-                                continue;
-                            }
-                            updateApnTable(&lynq_apn_table[apnId], apn,apnType,ifaceName);
-                        }
-                        lynq_data_call_change_id = apnId;
-                        sendSignalPdnChange();
-                        LYDBGLOG("data call state:%d",lynq_data_call);
-                        if(lynq_data_call==1)
-                        {
-                            sendSignalDataCallStateChange();
-                            lynq_data_call = 0;
-                        }
-                    }
-                    else
-                    {
-                        urc_msg = strdupReadString_p(p);
-                        len = strlen(urc_msg);
-                        if(len < LYNQ_APN_TYPE_MAX_LEN-1)
-                        {
-                            memcpy(apnType,urc_msg,len+1);
-                        }
-                        LYDBGLOG("[data thread_urc_recv] apntype:%s",apnType);
-                        int apnId = getLynqApnID(apnType);
-                        if(apnId >= 0)
-                        {
-                            lynq_data_call_change_id = apnId;
-                            bzero(lynq_apn_table[apnId].apnType,LYNQ_APN_TYPE_MAX_LEN);//async clean
-                        }
-                        sendSignalPdnChange();
-                        LYDBGLOG("data call state:%d",lynq_data_call);
-                        if(lynq_data_call==1)
-                        {
-                            sendSignalDataCallStateChange();
-                            lynq_data_call = 0;
-                        }
-                    }
-                    break;
-                }
-            case 9004:
-            {
-                LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d\n",resp_type,urcid,slot_id);
                 urc_msg = strdupReadString_p(p);
-                if (NULL == urc_msg)
+                int len = strlen(urc_msg);
+                if(len < LYNQ_APN_MAX_LEN-1)
                 {
-                    LYERRLOG("error apn msg");
+                    memcpy(apn,urc_msg,len+1);
                 }
+                urc_msg = strdupReadString_p(p);
+                len = strlen(urc_msg);
+                if(len < LYNQ_APN_TYPE_MAX_LEN-1)
+                {
+                    memcpy(apnType,urc_msg,len+1);
+                }
+                urc_msg = strdupReadString_p(p);
+                len = strlen(urc_msg);
+                if(len < LYNQ_IFACE_NAME_MAX_LEN-1)
+                {
+                    memcpy(ifaceName,urc_msg,strlen(urc_msg)+1);
+                }
+                //sendSignalDataCallStateChange();
+                int apnId = getLynqApnID(apnType);
+                if(apnId >= 0)
+                {
+                    if(lynq_apn_table[apnId].hasTimeout==1)
+                    {
+                        LYERRLOG("apn:%s has time out,deacive this apn",lynq_apn_table[apnId].apn);
+                        if (NULL != lynq_apn_table[apnId].apn && NULL != NULL != lynq_apn_table[apnId].apnType)
+                        {
+                            LYERRLOG("deactive this time out APN");
+                            lynq_deactive_data_call(&apnId);
+                        }
+                        else 
+                        {
+                            LYERRLOG("this table is invalid");
+                        }
+                        break;
+                    }
+                    //updateApnTable(&lynq_apn_table[apnId],apn,apnType,ifaceName);
+                }
+                /*To be completed*/
                 else
                 {
-                    bzero(g_lynq_apn_result, 1024);
-                    strcpy(g_lynq_apn_result, urc_msg);
-                    sendSignalApnChange();
+                    LYERRLOG("invalid apnId");
+                    break;
                 }
-                break;
+                pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+                s_data_urc_wait_list.push_back(apnId);
+                pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
+                lynq_data_call_change_id = apnId;
+                //sendSignalPdnChange();
+                LYDBGLOG("data call state:%d",lynq_data_call);
+                if(lynq_data_call==1)
+                {
+                    sendSignalDataCallStateChange();
+                    lynq_data_call = 0;
+                }
             }
-            case 9005:
+            else
             {
-                LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d\n",resp_type,urcid,slot_id);
+                urc_msg = strdupReadString_p(p);
+                len = strlen(urc_msg);
+                if(len < LYNQ_APN_TYPE_MAX_LEN-1)
+                {
+                    memcpy(apnType,urc_msg,len+1);
+                }
+                LYDBGLOG("[data thread_urc_recv] apntype:%s",apnType);
+                int apnId = getLynqApnID(apnType);
+                if(apnId >= 0)
+                {
+                    lynq_data_call_change_id = apnId;
+                    bzero(lynq_apn_table[apnId].apnType,LYNQ_APN_TYPE_MAX_LEN);//async clean
+                }
+                pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+                s_data_urc_wait_list.push_back(apnId);
+                pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
+                //sendSignalPdnChange();
+                LYDBGLOG("data call state:%d",lynq_data_call);
+                if(lynq_data_call==1)
+                {
+                    sendSignalDataCallStateChange();
+                    lynq_data_call = 0;
+                }
+            }
+            break;
+        case LYNQ_URC_MODIFY_APNDB:
+            urc_msg = strdupReadString_p(p);
+            if (NULL == urc_msg)
+            {
+                LYERRLOG("error apn msg");
+            }
+            else
+            {
+                bzero(g_lynq_apn_result, 1024);
+                strcpy(g_lynq_apn_result, urc_msg);
+                sendSignalApnChange();
+            }
+            break;
+        case LYNQ_URC_RESET_APNDB:
+            {
                 urc_msg = strdupReadString_p(p);
                 if (NULL == urc_msg)
                 {
@@ -485,56 +483,75 @@
                     sendSignalApnChange();
                 }
             }
-                default:
-                    break;
-            }
-        }
-        delete p;
-        p = NULL;
+        default:
+            break;
     }
-    close(socket_fd);
+    
 }
-int lynq_socket_urc_start()
+
+void cleanup_urc_vector_mutex(void *arg)
 {
-    int socket_fd=0;
-    int rt=0;
-    int len=0;
-    int on=1;
-    struct sockaddr_in urc_local_addr;
-    pthread_attr_t attr;
-    socket_fd = socket(AF_INET,SOCK_DGRAM,0);
-    if(socket_fd < 0)
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
+}
+
+void *thread_urc_vector()
+{
+    pthread_cleanup_push(cleanup_urc_vector_mutex, NULL);
+    while (data_urc_vector_status)
     {
-        perror("creaet socket for udp fail");
+        while (!s_data_urc_wait_list.empty())
+        {
+            sendSignalPdnChange();
+            usleep(10);
+        }
+    }
+    pthread_cleanup_pop(0);
+}
+
+void cancel_urc_vector_signal_thread()
+{
+    int ret;
+
+    pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+    if (data_list_urc_vector_tid != -1)
+    {
+        ret = pthread_cancel(data_list_urc_vector_tid);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+    }
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
+
+    if (data_list_urc_vector_tid != -1)
+    {
+        ret = pthread_join(data_list_urc_vector_tid,NULL);
+        LYDBGLOG("pthread join ret = %d",ret);
+        data_list_urc_vector_tid = -1;
+    }
+    pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+    s_data_urc_wait_list.clear();
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
+    data_urc_vector_status = 0;
+}
+
+int create_urc_vector_signal_thread()
+{
+    int ret;
+
+    data_urc_vector_status = 1;
+    pthread_mutex_init(&s_lynq_urc_vector_mutex,NULL);
+    ret = pthread_create(&data_list_urc_vector_tid,NULL,thread_urc_vector,NULL);
+    if (ret < 0)
+    {
+        LYERRLOG("urc vector signal pthread create error");
+        lynq_deinit_data_urc_thread();
+        data_urc_vector_status = 0;
         return -1;
     }
-    urc_local_addr.sin_family = AF_INET;
-    urc_local_addr.sin_port = htons(LYNQ_URC_SERVICE_PORT);
-    urc_local_addr.sin_addr.s_addr = htons(INADDR_ANY);
-    /* Set socket to allow reuse of address and port, SO_REUSEADDR value is 2*/
-    rt = setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on);
-    if(rt<0)
-    {
-        perror("SO_REUSEADDR fail\n");
-        return -1;
-    }
-    rt = bind(socket_fd ,(struct sockaddr*)&urc_local_addr, sizeof(urc_local_addr));
-    if (rt == -1)
-    {
-        perror("bind failed");
-        return -1;
-    }
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    rt = pthread_create(&lynq_data_tid,&attr,thread_urc_recv,(void *)socket_fd);
-    if(rt < 0)
-    {
-        LYERRLOG("urc loop failure!!!\n");
-        return -1;
-    }
-    LYDBGLOG("urc loop success!!!\n");
+    pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+    s_data_urc_wait_list.clear();
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
     return 0;
 }
+
 int lynq_init_data(int uToken)
 {
     if (g_lynq_data_init_flag == 1)
@@ -545,7 +562,6 @@
     g_lynq_data_init_flag = 1;
     int result = 0;
     Global_uToken = uToken;
-    data_urc_recive_status = 1;
     LYLOGSET(LOG_INFO);
     LYLOGEINIT(USER_LOG_TAG);
     result = lynq_socket_client_start();
@@ -555,7 +571,14 @@
         LYERRLOG("init socket client fail!!!");
         return -1;
     }
-    result = lynq_socket_urc_start();
+    result = lynq_init_data_urc_thread();
+    if(result!=0)
+    {
+        LYERRLOG("init socket urc fail!!!");
+        return -1;
+    }
+
+    result = create_urc_vector_signal_thread();
     if(result!=0)
     {
         LYERRLOG("init socket urc fail!!!");
@@ -586,14 +609,12 @@
     {
         close(lynq_client_sockfd);
     }
-    data_urc_recive_status = 0;
-    if (lynq_data_tid > 0)
+    ret = lynq_deinit_data_urc_thread();
     {
-        ret = pthread_cancel(lynq_data_tid);
-        LYDBGLOG("pthread cancel ret = %d",ret);
-        ret = pthread_join(lynq_data_tid,NULL);
-        LYDBGLOG("pthread join ret = %d",ret);
+        LYERRLOG("lynq_deinit_data_urc_thread fail");
+        return ret;
     }
+    cancel_urc_vector_signal_thread();
     return 0;
 }
 int lynq_setup_data_call(int *handle)
@@ -604,7 +625,6 @@
     int request = -1;
     int slot_id = -1;
     int error = -1;
-    char iface = NULL;
     int lynq_data_call_id = 0;
     if(handle==NULL)
     {
@@ -642,6 +662,7 @@
     }
     return error;
 }
+
 int lynq_deactive_data_call(int *handle)
 {
     Parcel p;
@@ -700,7 +721,6 @@
     int request = -1;
     int slot_id = -1;
     int error = -1;
-    char iface = NULL;
     int lynq_data_call_id = -1;
     char *argv[10] = {};
     if(handle==NULL||apn==NULL||apnType==NULL)
@@ -769,7 +789,7 @@
     lynq_data_call = 1;
     if(error==0)
     {
-        if(waitDataCallstateChange(20000)==ETIMEDOUT)//20s
+        if(waitDataCallstateChange(60000)==ETIMEDOUT)//60s
         {
             error = LYNQ_E_TIME_OUT;
             LYERRLOG("timeout:wait data Call state fail!!!");
@@ -823,7 +843,6 @@
     int error = -1;
     int version =0;
     int num = 0;
-    int temp_int =0;
     char *temp_char = NULL;
     if(dataCallList==NULL)
     {
@@ -924,8 +943,16 @@
 }
 int lynq_wait_data_call_state_change(int *handle)
 {
+    
+    std::vector<int>::iterator iter;
     waitPdnChange();
-    *handle = lynq_data_call_change_id;
+
+    pthread_mutex_lock(&s_lynq_urc_vector_mutex);
+    iter = s_data_urc_wait_list.begin();
+    handle = (*iter);
+    s_data_urc_wait_list.erase(iter);
+    pthread_mutex_unlock(&s_lynq_urc_vector_mutex);
+    
     LYINFLOG("lynq data call id:%d",lynq_data_call_change_id);
     return 0;
 }
@@ -1214,7 +1241,6 @@
     }
     lynq_client_t client;
     char argc[512];
-    char recvline[LYNQ_REC_BUF];
     int res = 0;
     Parcel p;
     if (cmd == 0) // insert apn db
diff --git a/src/lynq/lib/liblynq-data/lynq_data_urc.cpp b/src/lynq/lib/liblynq-data/lynq_data_urc.cpp
new file mode 100755
index 0000000..aa38f0d
--- /dev/null
+++ b/src/lynq/lib/liblynq-data/lynq_data_urc.cpp
@@ -0,0 +1,327 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+#include <binder/Parcel.h>
+#include <log/log.h>
+#include <cutils/jstring.h>
+#include <pthread.h>
+#include <list>
+#include "lynq_data.h"
+#include "lynq_data_urc.h"
+#include "liblog/lynq_deflog.h"
+#include "lynq_shm.h"
+
+#define LYNQ_REC_BUF 8192
+
+static std::list<Parcel*> s_urc_recv_parcel_list;
+
+int lynq_len_urc_addr_serv;
+struct sockaddr_in urc_local_addr;
+static int lynq_urc_sockfd = -1;
+bool data_urc_recive_status = 1;
+static pthread_mutex_t s_lynq_urc_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_lynq_urc_cond = PTHREAD_COND_INITIALIZER;
+
+/*recv*/
+pthread_t data_urc_recv_tid = -1;
+static pthread_mutex_t s_lynq_urc_recv_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_lynq_urc_recv_cond = PTHREAD_COND_INITIALIZER;
+
+/*process*/
+pthread_t data_urc_process_tid = -1;
+bool data_urc_process_status = 1;
+static pthread_mutex_t s_lynq_urc_process_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_lynq_urc_process_cond = PTHREAD_COND_INITIALIZER;
+
+#define SHM_BUFFER_INDEX_OFFSET 1
+#define SHM_BUFFER_SIZE_OFFSET 16
+#define SHM_BUFFER_INDEX_MASK 0x0000007F
+#define SHM_BUFFER_SIZE_MASK 0x0000FFFF
+
+bool urc_data_is_in_shm_data(int responseType,int& level, int& index, int& size)
+{
+    int shm_index=((responseType>>SHM_BUFFER_INDEX_OFFSET)&SHM_BUFFER_INDEX_MASK);
+    if (shm_index>0)
+    {
+        index=shm_index-1;    
+        size=((responseType>>SHM_BUFFER_SIZE_OFFSET)&SHM_BUFFER_SIZE_MASK);
+        if(size>=sizeof(int32_t)*3 && get_shem_buffer_level(size,&level))
+        {
+            LYINFLOG("urc_data_is_in_shm_data level is %d, index is %d size is %d",level,index,size);
+            return true;                            
+        }        
+    }
+    LYINFLOG("urc_data_is_in_shm_data return false, responseType is %d",responseType);
+    return false;
+}
+
+void cleanup_urc_process_mutex(void *arg)
+{
+    pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+}
+
+void *thread_urc_recv()
+{
+    Parcel *urc_p =NULL;
+    char urc_data[LYNQ_REC_BUF];    
+    int res = 0;
+    lynq_head_t* phead;
+   
+    LYINFLOG("urc recv thread is running");
+    while(data_urc_recive_status)
+    {
+        bzero(urc_data,LYNQ_REC_BUF);
+        res = recvfrom(lynq_urc_sockfd,urc_data,sizeof(urc_data),0,(struct sockaddr *)&urc_local_addr,(socklen_t*)&lynq_len_urc_addr_serv);
+        
+        if(res<sizeof(int32_t)*2)
+        {
+            LYERRLOG("thread_urc_recv step2 fail: res is %d",res);
+            continue;
+        }
+
+        phead=(lynq_head_t*) urc_data;
+        if(is_support_urc(phead->urcid)==false)
+        {
+            continue;
+        }
+        urc_p = new Parcel();
+        if(urc_p == NULL)
+        {
+            LYERRLOG("new parcel failure!!!");
+            continue;
+        }
+        int level,index,size;
+        if(urc_data_is_in_shm_data(phead->resp_type,level,index,size))
+        {
+            urc_p->setData((uint8_t *)get_shem_buffer(level,index),size); // p.setData((uint8_t *) buffer, buflen);                        
+        }
+        else if(res>=sizeof(int32_t)*3)
+        {
+            urc_p->setData((uint8_t *)urc_data,res); // p.setData((uint8_t *) buffer, buflen);            
+        }
+        else 
+        {
+            LYERRLOG("res %d error!!!", res);
+            delete urc_p;
+            urc_p = NULL;
+            continue;
+        }
+        urc_p->setDataPosition(0);
+        if(urc_p->dataAvail()>0)
+        {
+            pthread_mutex_lock(&s_lynq_urc_process_mutex);
+            s_urc_recv_parcel_list.push_back(urc_p);
+            pthread_cond_broadcast(&s_lynq_urc_process_cond);
+            pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+        }
+        else 
+        {
+            delete urc_p;
+            urc_p = NULL;
+        }        
+    }
+    LYINFLOG("urc recv thread ended");
+    return NULL;
+}
+
+void *thread_urc_process()
+{
+    Parcel *urc_p =NULL;
+    std::list<Parcel*>::iterator iter;
+
+    LYINFLOG("urc process thread is running");
+    pthread_cleanup_push(cleanup_urc_process_mutex, NULL); // thread cleanup handler
+    while (data_urc_process_status)
+    {
+        pthread_mutex_lock(&s_lynq_urc_process_mutex);
+        while(s_urc_recv_parcel_list.empty())
+        {
+            pthread_cond_wait(&s_lynq_urc_process_cond,&s_lynq_urc_process_mutex);
+        }
+        iter=s_urc_recv_parcel_list.begin();
+        urc_p = (*iter);
+        s_urc_recv_parcel_list.erase(iter);
+        pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+        urc_p->setDataPosition(0);
+        if(urc_p->dataAvail()>0)
+        {
+            pthread_mutex_lock(&s_lynq_urc_mutex);
+            urc_msg_process(urc_p);
+            pthread_mutex_unlock(&s_lynq_urc_mutex);
+        }
+        delete urc_p;
+        urc_p = NULL;
+    }
+    pthread_cleanup_pop(0);
+    LYINFLOG("urc process thread ended");
+    return NULL;
+}
+
+int lynq_socket_recv_start()
+{
+    int rt=0;
+    int on=1;
+    struct sockaddr_in urc_local_addr;
+    pthread_attr_t attr;
+    lynq_urc_sockfd = socket(AF_INET,SOCK_DGRAM,0);
+    if(lynq_urc_sockfd < 0)
+    {
+        perror("creaet socket for udp fail");
+        return -1;
+    }
+    urc_local_addr.sin_family = AF_INET;
+    urc_local_addr.sin_port = htons(LYNQ_URC_SERVICE_PORT);
+    urc_local_addr.sin_addr.s_addr = htons(INADDR_ANY);
+    /* Set socket to allow reuse of address and port, SO_REUSEADDR value is 2*/
+    rt = setsockopt(lynq_urc_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on);
+    if(rt<0)
+    {
+        perror("SO_REUSEADDR fail\n");
+        close(lynq_urc_sockfd);
+        lynq_urc_sockfd = -1;
+        return -1;
+    }
+    rt = bind(lynq_urc_sockfd ,(struct sockaddr*)&urc_local_addr, sizeof(urc_local_addr));
+    if (rt == -1)
+    {
+        perror("bind failed");
+        close(lynq_urc_sockfd);
+        lynq_urc_sockfd = -1;
+        return -1;
+    }
+    return 0;
+}
+
+int lynq_socket_recv_stop()
+{
+    if (lynq_urc_sockfd >=0)
+    {
+        close(lynq_urc_sockfd);
+        lynq_urc_sockfd = -1;
+    }
+    return 0;
+}
+
+void lynq_urc_recv_thread_stop()
+{
+    int ret;
+
+    pthread_mutex_lock(&s_lynq_urc_process_mutex);
+    data_urc_recive_status = 0;
+    if (data_urc_recv_tid != -1)
+    {
+        ret = pthread_cancel(data_urc_recv_tid);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+    }
+    pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+
+    if (data_urc_recv_tid != -1)
+    {
+        ret = pthread_join(data_urc_recv_tid,NULL);
+        LYDBGLOG("pthread join ret = %d",ret);
+        data_urc_recv_tid = -1;
+    }
+}
+
+void lynq_urc_process_thread_stop()
+{
+    int ret;
+
+    pthread_mutex_lock(&s_lynq_urc_process_mutex);
+    pthread_mutex_lock(&s_lynq_urc_mutex);
+
+    data_urc_process_status = 0;
+    if (data_urc_process_tid != -1)
+    {
+        ret = pthread_cancel(data_urc_process_tid);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+    }
+    pthread_mutex_unlock(&s_lynq_urc_mutex);
+    pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+
+    if (data_urc_process_tid != -1)
+    {
+        ret = pthread_join(data_urc_process_tid,NULL);
+        LYDBGLOG("pthread join ret = %d",ret);
+        data_urc_process_tid = -1;
+    }
+}
+
+
+int lynq_init_data_urc_thread()
+{
+    int ret = 0;
+    if(ril_init_mem()!=0)
+    {
+        LYERRLOG("ril_init_mem fail");
+        return -1;
+    }
+
+    ret = lynq_socket_recv_start();
+    if (ret != 0)
+    {
+        LYERRLOG("lynq_socket_recv_start fail");
+        ril_deinit_mem();
+        return -1;
+    }
+
+    pthread_mutex_init(&s_lynq_urc_process_mutex,NULL);
+    pthread_mutex_init(&s_lynq_urc_recv_mutex,NULL);
+
+    pthread_mutex_lock(&s_lynq_urc_process_mutex);
+    std::list<Parcel*>::iterator iter;
+    for (iter=s_urc_recv_parcel_list.begin();iter!=s_urc_recv_parcel_list.end();++iter)
+    {
+        delete(*iter);
+    }
+    s_urc_recv_parcel_list.clear(); 
+    pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+
+    pthread_mutex_init(&s_lynq_urc_mutex,NULL);
+    data_urc_recive_status = 1;
+
+    ret = pthread_create(&data_urc_recv_tid,NULL,thread_urc_recv,NULL);
+    if (ret < 0)
+    {
+        LYERRLOG("urc recv pthread create error");
+        data_urc_recive_status = 0;
+        lynq_socket_recv_stop();
+        ril_deinit_mem();
+        return -1;
+    }
+
+    data_urc_process_status = 1;
+    ret = pthread_create(&data_urc_process_tid,NULL,thread_urc_process,NULL);
+    if (ret < 0)
+    {
+        LYERRLOG("urc recv pthread create error");
+
+        data_urc_process_status = 0;
+        lynq_socket_recv_stop();
+        lynq_urc_recv_thread_stop();
+
+        return -1;
+    }
+    return 0;
+}
+
+int lynq_deinit_data_urc_thread()
+{
+    lynq_socket_recv_stop();
+    lynq_urc_recv_thread_stop();
+    lynq_urc_process_thread_stop();
+
+    pthread_mutex_lock(&s_lynq_urc_process_mutex);
+    std::list<Parcel*>::iterator iter;
+    for (iter=s_urc_recv_parcel_list.begin();iter!=s_urc_recv_parcel_list.end();++iter)
+    {
+        delete(*iter);
+    }
+    s_urc_recv_parcel_list.clear(); 
+    pthread_mutex_unlock(&s_lynq_urc_process_mutex);
+
+    ril_deinit_mem();
+}
\ No newline at end of file
diff --git a/src/lynq/lib/liblynq-data/lynq_data_urc.h b/src/lynq/lib/liblynq-data/lynq_data_urc.h
new file mode 100755
index 0000000..7ac4f75
--- /dev/null
+++ b/src/lynq/lib/liblynq-data/lynq_data_urc.h
@@ -0,0 +1,30 @@
+#ifndef LYNQ_DATA_URC_H
+#define LYNQ_DATA_URC_H
+
+using ::android::Parcel;
+
+#define LYNQ_URC_SERVICE_PORT 8086
+
+/*the same with lynq_interface.h begin*/
+#define LYNQ_REQUEST_VENDOR_BASE 8000
+#define LYNQ_URC_VENDOR_BASE 9000
+#define LYNQ_AT_SNED (LYNQ_REQUEST_VENDOR_BASE +1)
+#define LYNQ_URC_CALL_STATUS_IND (LYNQ_URC_VENDOR_BASE+1)
+#define LYNQ_URC_DATA_STATUS_IND (LYNQ_URC_VENDOR_BASE+2)
+#define LYNQ_URC_DATA_CALL_STATUS_IND (LYNQ_URC_VENDOR_BASE+3)
+#define LYNQ_AUTO_ANSWER_CALL (LYNQ_REQUEST_VENDOR_BASE +2)
+#define LYNQ_REQUEST_SET_DTMF_VOLUME (LYNQ_REQUEST_VENDOR_BASE +3)
+#define LYNQ_URC_MODIFY_APNDB (LYNQ_URC_VENDOR_BASE+4)
+#define LYNQ_URC_RESET_APNDB (LYNQ_URC_VENDOR_BASE+5)
+
+typedef struct{
+    int resp_type;
+    int urcid;   
+}lynq_head_t;
+
+int lynq_init_data_urc_thread();
+int lynq_deinit_data_urc_thread();
+bool is_support_urc(int urc_id);
+void urc_msg_process(Parcel *p);
+
+#endif
\ No newline at end of file
diff --git a/src/lynq/lib/liblynq-data/makefile b/src/lynq/lib/liblynq-data/makefile
index 183ebaa..53ed1d4 100755
--- a/src/lynq/lib/liblynq-data/makefile
+++ b/src/lynq/lib/liblynq-data/makefile
@@ -20,6 +20,7 @@
 LOCAL_C_INCLUDES = \
   -I. \
   -I$(LOCAL_PATH)/include/libdata \
+  -I$(ROOT)$(includedir)/lynq_shm \
   -I$(ROOT)$(includedir)/logger \
   -I$(ROOT)$(includedir)/liblog \
 
@@ -35,6 +36,7 @@
     -lpthread \
     -llynq-log \
     -llynq-uci \
+    -llynq-shm \
 
 
 SOURCES = $(wildcard *.cpp)