[feature] ecall add abnormal process and cs call handle changed from index to call id

Change-Id: Iffc5ae14b06fa96c3ad3b6a1c77f9784654dce04
diff --git a/src/lynq/framework/lynq-ril-service/src/ecall/eCall.cpp b/src/lynq/framework/lynq-ril-service/src/ecall/eCall.cpp
old mode 100644
new mode 100755
index da55466..fbb33e3
--- a/src/lynq/framework/lynq-ril-service/src/ecall/eCall.cpp
+++ b/src/lynq/framework/lynq-ril-service/src/ecall/eCall.cpp
@@ -45,6 +45,7 @@
 #include <pthread.h>
 #include <string.h>
 #include <memory>
+#include <binder/Parcel.h>
 
 #include "util/utils.h"
 #include "cc.h"
@@ -55,6 +56,7 @@
 #include "./gost/sslp/SslpManager.h"
 #include "./gost/sslp/ecall/EcallUtils.h"
 #include "network.h"
+#include "lynq_interface.h"
 
 #undef LOG_TAG
 #define LOG_TAG "DEMO_ECALL"
@@ -81,8 +83,8 @@
     REDIAL_UNKNOWN = 4,
 }ecall_redial_status;
 
-int act_fecall_socid = -1;
-int act_feCall_Id = -1;
+static int act_fecall_socid = -1;
+static int act_feCall_Id = -1;
 static ecall_redial_status redial_tag = REDIAL_UNKNOWN;
 static bool normal_ecall_tag = false;
 
@@ -153,6 +155,9 @@
 static int gost_resend_msd_value = 11;
 static int gost_deregistration_value = 12;
 
+static int g_ecall_test=0;
+static int g_reset_timer =6;
+
 bool isEcallAudioPath() {
     RLOGD("%s , is_ecall_audio_path: %d", __FUNCTION__, is_ecall_audio_path);
     return is_ecall_audio_path;
@@ -221,28 +226,175 @@
 //    setMute(2, argv, id, NULL);
 }
 
-void ecall_timer_handler(sigval_t sig) {
-    RLOGD("ecall_timer_handler, sig_value: %d", sig.sival_int);
+int ecall_setRadioPower (int enable) {
+    
+    RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_RADIO_POWER, UDP, RIL_SOCKET_ID(act_fecall_socid));
+    char* id = const_cast<char*>(std::to_string(enable).c_str());
+    char* argv[2] = { "RIL_REQUEST_RADIO_POWER", "" };
+    argv[1] = id;
+    setRadioPower(2, argv, RIL_SOCKET_ID(act_fecall_socid), pRI);
+
+    return 0;
+}
+
+int lynq_is_msd_suc(int lynqIncomingEcallIndication)
+{
+    if(RIL_UNSOL_ECALL_ALACK_POSITIVE_RECEIVED == lynqIncomingEcallIndication ||
+       RIL_UNSOL_ECALL_LLACK_RECEIVED == lynqIncomingEcallIndication ||
+       RIL_UNSOL_ECALL_ALACK_CLEARDOWN_RECEIVED == lynqIncomingEcallIndication ||
+       RIL_UNSOL_ECALL_T5_TIMER_OUT  == lynqIncomingEcallIndication ||
+       RIL_UNSOL_ECALL_T6_TIMER_OUT  == lynqIncomingEcallIndication ||
+       RIL_UNSOL_ECALL_T7_TIMER_OUT  == lynqIncomingEcallIndication)
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+void ecall_test_sub_set(int eCall_Indication)
+{
+    if(g_ecall_test==1 && eCall_Indication == RIL_UNSOL_ECALL_ACTIVE)
+    {
+        ecall_setRadioPower(0);
+    }
+    else if(g_ecall_test==2 && lynq_is_msd_suc(eCall_Indication))
+    {
+        ecall_setRadioPower(0);
+    }
+    else if(g_ecall_test==3 && eCall_Indication == RIL_UNSOL_ECALL_PSAP_CALLBACK_START)
+    {
+        ecall_setRadioPower(0);
+    }
+    else if(g_ecall_test==4 && eCall_Indication == RIL_UNSOL_ECALL_SENDING_START)
+    {
+        ecall_setRadioPower(0);
+    }      
+    else if(g_ecall_test==5 && eCall_Indication == RIL_UNSOL_ECALL_SENDING_MSD)
+    {
+        ecall_setRadioPower(0);
+    }      
+}
+
+void ecall_test_sub_recover()
+{
+    if(g_ecall_test!=0)
+    {
+        g_ecall_test=0;
+        ecall_setRadioPower(1);
+        sleep(g_reset_timer);
+    }    
+}
+
+void SendEcallTimerOutIndication(int sival_int, int soc_id, int call_id)
+{
+     android::Parcel p;
+     int timer_out_id;
+  
+     if(sival_int==sT2_sig_value)
+     {
+         timer_out_id=RIL_UNSOL_ECALL_T2_TIMER_OUT;
+     }
+     else if(sival_int == sT5_sig_value)
+     {
+         timer_out_id=RIL_UNSOL_ECALL_T5_TIMER_OUT;
+     }
+     else if(sival_int == sT6_sig_value)
+     {
+         timer_out_id=RIL_UNSOL_ECALL_T6_TIMER_OUT;
+     }
+     else if(sival_int == sT7_sig_value)
+     {
+         timer_out_id=RIL_UNSOL_ECALL_T7_TIMER_OUT;
+     }
+     else if(sival_int == redial_sig_value)
+     {
+         timer_out_id=RIL_UNSOL_ECALL_REDIAL_TIMER_OUT; 
+     }
+     else {
+         return;
+     }
+
+     p.writeInt32(RESPONSE_UNSOLICITED);
+     p.writeInt32(RIL_UNSOL_ECALL_INDICATIONS);
+     p.writeInt32(soc_id);
+     p.writeInt32(timer_out_id);
+     p.writeInt32(call_id);
+
+     android::LYNQ_RIL_urcBroadcast(p);
+
+     ecall_test_sub_set(timer_out_id);
+
+    return;
+}
+
+void start_ecll_timer(timer_t timer, int signal_value, int milliseconds) {
+    RLOGD("start_ecll_timer(), timer_id=%ld, signal_value=%d, time=%d",(long)timer, signal_value, milliseconds);
+
+    struct itimerspec expire;
+    expire.it_interval.tv_sec = 0;
+    expire.it_interval.tv_nsec = 0;
+    expire.it_value.tv_sec = milliseconds/1000;
+    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
+    if (timer_settime(timer, 0, &expire, NULL) == -1) {
+        RLOGE("timer_settime  failed reason=[%s]", strerror(errno));
+    }
+}
+
+void stop_ecall_timer(timer_t timer, int signal_value) {
+    RLOGD("stop_ecall_timer(), timer_id=%ld, signal_value=%d", (long)timer, signal_value);
+    struct itimerspec timespec;
+    if(timer_gettime(timer, &timespec) == -1) {
+        RLOGD("stop_ecall_timer(), get time fail(%s)", strerror(errno));
+        return;
+    }
+    RLOGD("stop_ecall_timer(), tv_sec=%ld, tv_nsec=%ld",timespec.it_value.tv_sec, timespec.it_value.tv_nsec);
+    if((timespec.it_value.tv_sec == 0)  && (timespec.it_value.tv_nsec == 0) ) {
+        RLOGD("stop_ecall_timer(), timer_id(%ld) had stopped, just return", (long)timer);
+        return;
+    } else {
+        start_ecll_timer(timer, signal_value, 0);
+    }
+}
+
+void ecall_timer_handler(sigval_t sig) {    
+    RLOGD("ecall_timer_handler, sig_value: %d, soc id : %d, call id %d", sig.sival_int,act_fecall_socid,act_feCall_Id);
     int s;
+    int soc_id;
+    int call_id;
     s = pthread_mutex_lock(&mtx);
     if(s != 0) {
         RLOGE("ecall_timer_handler, pthead_mutex_lock fail");
     }
+    soc_id = act_fecall_socid;
+    call_id = act_feCall_Id;
     if(sig.sival_int == sT2_sig_value) {
         RLOGD("T2 timeout, call_Id=%d, socket_id=%d", act_feCall_Id, act_fecall_socid);
         if(act_feCall_Id == -1 || act_fecall_socid == -1) {
+            act_fecall_socid = -1;
+            act_feCall_Id = -1;
             goto done;
         }
+        stop_ecall_timer(sT5,sT5_sig_value);
+        stop_ecall_timer(sT6,sT6_sig_value);
+        stop_ecall_timer(sT7,sT7_sig_value);
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+
+        redial_tag = REDIAL_SUCCESS;
         RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_HANGUP, UDP, RIL_SOCKET_ID(act_fecall_socid));
         char* id = const_cast<char*>(std::to_string(act_feCall_Id).c_str());
         char* argv[2] = { "RIL_REQUEST_HANGUP", "" };
         argv[1] = id;
         hangupConnection(2, argv, RIL_SOCKET_ID(act_fecall_socid), pRI);
+
         act_fecall_socid = -1;
         act_feCall_Id = -1;
-    } else if(sig.sival_int == sT5_sig_value
+    } 
+    else if(sig.sival_int == sT5_sig_value
             || sig.sival_int == sT6_sig_value
             || sig.sival_int == sT7_sig_value) {
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+        redial_tag = REDIAL_SUCCESS;
         normal_ecall_tag = false;
         resetEcallIVSandAudio(UDP, RIL_SOCKET_ID(fast_ecall_socket_id));
         if(0 != T7GostEcallSmsMsd(sig))
@@ -258,6 +410,23 @@
         resetIVS(0, NULL, RIL_SOCKET_ID(fast_ecall_socket_id), pRI);
         fast_argc = 0;
         fast_argv.clear();
+     
+        stop_ecall_timer(sT2,sT2_sig_value);
+        stop_ecall_timer(sT5,sT5_sig_value);
+        stop_ecall_timer(sT6,sT6_sig_value);
+        stop_ecall_timer(sT7,sT7_sig_value);
+        if(act_feCall_Id!=-1 &&  act_fecall_socid != -1)
+        {
+              RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_HANGUP, UDP, RIL_SOCKET_ID(act_fecall_socid));
+              char* id = const_cast<char*>(std::to_string(act_feCall_Id).c_str());
+              char* argv[2] = { "RIL_REQUEST_HANGUP", "" };
+              argv[1] = id;
+              hangupConnection(2, argv, RIL_SOCKET_ID(act_fecall_socid), pRI);           
+        }
+
+        act_fecall_socid = -1;
+        act_feCall_Id = -1;
+
         start_ecll_timer(sAutoAnsTimer, autoAns_sig_value, AUTOANS_TIMEOUT);
         autoAnswerEcall(true);
     } else if(sig.sival_int == autoAns_sig_value) {
@@ -293,7 +462,8 @@
     else {
         RLOGE("ecall_timer_handler, sig_value is invalid!");
     }
-done:
+done:       
+    SendEcallTimerOutIndication(sig.sival_int,soc_id,call_id);
     s = pthread_mutex_unlock(&mtx);
     if(s != 0) {
         RLOGE("ecall_timer_handler, pthread_mutex_unlock fail");
@@ -327,35 +497,6 @@
     init_ecall_timer(&gostDeregistrationTimer, gost_deregistration_value);
 }
 
-void start_ecll_timer(timer_t timer, int signal_value, int milliseconds) {
-    RLOGD("start_ecll_timer(), timer_id=%ld, signal_value=%d, time=%d",(long)timer, signal_value, milliseconds);
-
-    struct itimerspec expire;
-    expire.it_interval.tv_sec = 0;
-    expire.it_interval.tv_nsec = 0;
-    expire.it_value.tv_sec = milliseconds/1000;
-    expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
-    if (timer_settime(timer, 0, &expire, NULL) == -1) {
-        RLOGE("timer_settime  failed reason=[%s]", strerror(errno));
-    }
-}
-
-void stop_ecall_timer(timer_t timer, int signal_value) {
-    RLOGD("stop_ecall_timer(), timer_id=%ld, signal_value=%d", (long)timer, signal_value);
-    struct itimerspec timespec;
-    if(timer_gettime(timer, &timespec) == -1) {
-        RLOGD("stop_ecall_timer(), get time fail(%s)", strerror(errno));
-        return;
-    }
-    RLOGD("stop_ecall_timer(), tv_sec=%ld, tv_nsec=%ld",timespec.it_value.tv_sec, timespec.it_value.tv_nsec);
-    if((timespec.it_value.tv_sec == 0)  && (timespec.it_value.tv_nsec == 0) ) {
-        RLOGD("stop_ecall_timer(), timer_id(%ld) had stopped, just return", (long)timer);
-        return;
-    } else {
-        start_ecll_timer(timer, signal_value, 0);
-    }
-}
-
 void saveEcallRecord(RIL_ECall_Indication ind) {
     std::string str;
     if(ind == RIL_UNSOL_ECALL_ALACK_POSITIVE_RECEIVED) {
@@ -435,6 +576,8 @@
         } else {
             stop_ecall_timer(sT5, sT5_sig_value);
         }
+        act_fecall_socid = soc_id;
+        act_feCall_Id = p_cur->call_id;
         break;
     }
     case RIL_UNSOL_ECALL_SENDING_MSD: // = 2,
@@ -448,8 +591,12 @@
     {
         fast_argc = 0;
         fast_argv.clear();
+        stop_ecall_timer(sT5,sT5_sig_value);
         stop_ecall_timer(sT7, sT7_sig_value);
         start_ecll_timer(sT6, sT6_sig_value, T6_TIMEOUT);
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+     
+        redial_tag = REDIAL_SUCCESS;
         act_fecall_socid = soc_id;
         act_feCall_Id = p_cur->call_id;
         normal_ecall_tag = false;
@@ -457,17 +604,31 @@
     }
     case RIL_UNSOL_ECALL_ALACK_POSITIVE_RECEIVED: // = 4,
     {
-        stop_ecall_timer(sT6, sT6_sig_value);
+        stop_ecall_timer(sT5,sT5_sig_value);
+        stop_ecall_timer(sT6,sT6_sig_value);
+        stop_ecall_timer(sT7,sT7_sig_value);
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+		
+        redial_tag = REDIAL_SUCCESS;
         resetEcallIVSandAudio(RSPD, soc_id);
         saveEcallRecord(p_cur->ind);
+
+        act_fecall_socid = soc_id;
+        act_feCall_Id = p_cur->call_id;
         break;
     }
     case RIL_UNSOL_ECALL_ALACK_CLEARDOWN_RECEIVED: // = 5,
     {
-        stop_ecall_timer(sT6, sT6_sig_value);
-        stop_ecall_timer(sT2, sT2_sig_value);
+        stop_ecall_timer(sT2,sT2_sig_value);
+        stop_ecall_timer(sT5,sT5_sig_value);
+        stop_ecall_timer(sT6,sT6_sig_value);
+        stop_ecall_timer(sT7,sT7_sig_value);
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+
+        redial_tag = REDIAL_SUCCESS;
         resetEcallIVSandAudio(RSPD, soc_id);
         saveEcallRecord(p_cur->ind);
+       
         RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_HANGUP, RSPD, soc_id);
         char* id = const_cast<char*>(std::to_string(p_cur->call_id).c_str());
         char* argv[2] = { "RIL_REQUEST_HANGUP", "" };
@@ -477,50 +638,74 @@
     }
     case RIL_UNSOL_ECALL_ACTIVE: // = 11,
     {
-        if(redial_tag == REDIAL_DOING) {
-            redial_tag = REDIAL_SUCCESS;
-            stop_ecall_timer(sRedialTimer, redial_sig_value);
-        }
         stop_ecall_timer(sAutoAnsTimer, autoAns_sig_value);
         stop_ecall_timer(sAutoAnsTimer_ims, autoAns_sig_value_ims);
         autoAnswerEcall(false);
         start_ecll_timer(sT2, sT2_sig_value,T2_TIMEOUT);
+
         // Start T5 only when need send inband MSD.
         if (fast_argc)
             start_ecll_timer(sT5,sT5_sig_value, T5_TIMEOUT);
+        else {            
+            stop_ecall_timer(sRedialTimer, redial_sig_value);
+            redial_tag = REDIAL_SUCCESS;
+        }
+
+        act_fecall_socid = soc_id;
+        act_feCall_Id = p_cur->call_id;       
         break;
     }
     case RIL_UNSOL_ECALL_DISCONNECTED: // = 12
     {
         start_ecll_timer(sAutoAnsTimer,autoAns_sig_value, AUTOANS_TIMEOUT);
         autoAnswerEcall(true);
-        stop_ecall_timer(sT2, sT2_sig_value);
+       
+        stop_ecall_timer(sT2,sT2_sig_value);
+        stop_ecall_timer(sT5,sT5_sig_value);
+        stop_ecall_timer(sT6,sT6_sig_value);
+        stop_ecall_timer(sT7,sT7_sig_value);
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+        redial_tag = REDIAL_SUCCESS;
+
+        act_fecall_socid = -1;
+        act_feCall_Id = -1;
         if(isGostEcall())
         {
             //start deregistration time
             start_ecll_timer(gostDeregistrationTimer, gost_deregistration_value, gostStartDeregisterTimer());
-        }
+        }        
 
         break;
     }
     case RIL_UNSOL_ECALL_ABNORMAL_HANGUP: //=15,
     {
-        RLOGD(" make fast ecall redial start,  redial_tag: %d", redial_tag);
-        if(redial_tag != REDIAL_DOING) {
+        RLOGD(" make fast ecall redial start,  redial_tag: %d", redial_tag);         
+        
+        if(redial_tag == REDIAL_DOING || redial_tag == REDIAL_UNKNOWN){
+            if(redial_tag == REDIAL_UNKNOWN) {                
+                int32_t timer = utils::mtk_property_get_int32(PROP_ECALL_REDIAL_TIMER, 120);
+                RLOGD(" make fast ecall redial start,  vendor.ecall.redial.timer: %d", timer);
+                start_ecll_timer(sRedialTimer, redial_sig_value, timer*1000);
+                redial_tag = REDIAL_DOING;
+            }      
             stop_ecall_timer(sT2, sT2_sig_value);
             stop_ecall_timer(sT5,sT5_sig_value);
             stop_ecall_timer(sT6,sT6_sig_value);
             stop_ecall_timer(sT7,sT7_sig_value);
-            int32_t timer = utils::mtk_property_get_int32(PROP_ECALL_REDIAL_TIMER, 120);
-            RLOGD(" make fast ecall redial start,  vendor.ecall.redial.timer: %d", timer);
-            start_ecll_timer(sRedialTimer, redial_sig_value, timer*1000);
-        }
-        if(redial_tag != REDIAL_SUCCESS || redial_tag != REDIAL_EXPIRES){
-            redial_tag = REDIAL_DOING;
+            ecall_test_sub_recover();
             RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_RESET_IVS, UDP, soc_id);
             resetIVS(0, NULL, soc_id, pRI);
             redialFastEcall(soc_id);
         }
+        else {   /* redial_tag == REDIAL_SUCCESS || redial_tag == REDIAL_EXPIRES */
+            /*same as RIL_UNSOL_ECALL_DISCONNECTED*/
+            stop_ecall_timer(sT2,sT2_sig_value);
+            stop_ecall_timer(sT5,sT5_sig_value);
+            stop_ecall_timer(sT6,sT6_sig_value);
+            stop_ecall_timer(sT7,sT7_sig_value);
+            start_ecll_timer(sAutoAnsTimer,autoAns_sig_value, AUTOANS_TIMEOUT);
+            autoAnswerEcall(true);           
+        }
         break;
     }
 #if defined(TARGET_PLATFORM_MT2735)
@@ -578,14 +763,24 @@
     case RIL_UNSOL_ECALL_PSAP_CALLBACK_START: // 40
     {
         // Similar to receive 11 + 1
-        if(redial_tag == REDIAL_DOING) {
-            redial_tag = REDIAL_SUCCESS;
-            stop_ecall_timer(sRedialTimer, redial_sig_value);
-        }
+        redial_tag = REDIAL_SUCCESS;
+        
         stop_ecall_timer(sAutoAnsTimer, autoAns_sig_value);
-        stop_ecall_timer(sAutoAnsTimer_ims, autoAns_sig_value_ims);
-        autoAnswerEcall(false);
-        start_ecll_timer(sT2, sT2_sig_value,T2_TIMEOUT);
+        stop_ecall_timer(sAutoAnsTimer_ims, autoAns_sig_value_ims);		
+        autoAnswerEcall(false);  
+
+        fast_argc = 0;
+        fast_argv.clear();
+     
+        stop_ecall_timer(sT2,sT2_sig_value);
+        stop_ecall_timer(sT5,sT5_sig_value);
+        stop_ecall_timer(sT6,sT6_sig_value);
+        stop_ecall_timer(sT7,sT7_sig_value);
+        stop_ecall_timer(sRedialTimer, redial_sig_value);
+        
+        act_fecall_socid = soc_id;
+        act_feCall_Id = p_cur->call_id;
+        start_ecll_timer(sT2, sT2_sig_value,T2_TIMEOUT);            
 
         RLOGD("msd_data: %s", msd_data==NULL ? "":msd_data);
         if(msd_data != NULL) {
@@ -617,17 +812,36 @@
         }
         break;
     }
-#endif
+#endif    
     default:
         RLOGD("handleEcallIndication don't handle the value(%d)", p_cur->ind);
         break;
     }
+    
+    ecall_test_sub_set(p_cur->ind);
+        
 }
 
 //RIL_REQUEST_ECALL_SET_IVS
 int setIVS(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
   android::Parcel p;
   size_t pos = p.dataPosition();
+  int enable = atoi(argv[1]);
+  if(enable<0 && enable> -100)
+  {
+     g_ecall_test=-enable;
+     android::lynqAssemblyParcelheader(p,socket_id,RIL_REQUEST_ECALL_SET_IVS,0,0);
+     android::LYNQ_RIL_respSocket_sp(p,pRI);
+     free(pRI);
+     return 0;
+  }
+  else if(enable <=-100){
+     g_reset_timer=-enable-100;
+     android::lynqAssemblyParcelheader(p,socket_id,RIL_REQUEST_ECALL_SET_IVS,0,0);
+     android::LYNQ_RIL_respSocket_sp(p,pRI);
+     free(pRI);
+     return 0;
+  }
 
   if (getSpeechStatus() == SPEECH_OFF) {
     if (get_audio_path() == 0) {
@@ -924,6 +1138,8 @@
     p.setDataPosition(pos);
     normal_ecall_tag = true;
     setEcallAudioPathOn(true);
+    act_fecall_socid = -1;
+    act_feCall_Id = -1;
     pRI->pCI->dispatchFunction(p, pRI);
 
     return 0;
@@ -1427,4 +1643,9 @@
     }
     return 0;
 }
+
+void init_redial_flag()
+{
+    redial_tag = REDIAL_UNKNOWN;
+}
 #endif /*ECALL_SUPPORT*/
diff --git a/src/lynq/framework/lynq-ril-service/src/ecall/eCall.h b/src/lynq/framework/lynq-ril-service/src/ecall/eCall.h
index f04c020..7c5e668 100755
--- a/src/lynq/framework/lynq-ril-service/src/ecall/eCall.h
+++ b/src/lynq/framework/lynq-ril-service/src/ecall/eCall.h
@@ -97,5 +97,6 @@
 void gostFastEcallFlgSet(bool flags);
 bool isEcallAudioPath();
 void setEcallAudioPathOn(bool on);
+void init_redial_flag();
 #endif /*ECALL_SUPPORT*/
 #endif
diff --git a/src/lynq/framework/lynq-ril-service/src/lynq_interface.h b/src/lynq/framework/lynq-ril-service/src/lynq_interface.h
index 6b121c7..144e7aa 100755
--- a/src/lynq/framework/lynq-ril-service/src/lynq_interface.h
+++ b/src/lynq/framework/lynq-ril-service/src/lynq_interface.h
@@ -20,6 +20,14 @@
 #define LYNQ_REQUEST_GET_SPEECH_VOLUME (LYNQ_REQUEST_VENDOR_BASE +10)
 #define LYNQ_REQUEST_RECORD  (LYNQ_REQUEST_VENDOR_BASE +11)
 
+#ifdef ECALL_SUPPORT
+#define RIL_UNSOL_ECALL_T2_TIMER_OUT  9000
+#define RIL_UNSOL_ECALL_T5_TIMER_OUT  9001
+#define RIL_UNSOL_ECALL_T6_TIMER_OUT  9002
+#define RIL_UNSOL_ECALL_T7_TIMER_OUT  9003
+#define RIL_UNSOL_ECALL_REDIAL_TIMER_OUT 9004
+#endif
+
 typedef struct{
     int request;
     int waitTime;
diff --git a/src/lynq/framework/lynq-ril-service/src/ril.cpp b/src/lynq/framework/lynq-ril-service/src/ril.cpp
index 12801dd..d60b89e 100755
--- a/src/lynq/framework/lynq-ril-service/src/ril.cpp
+++ b/src/lynq/framework/lynq-ril-service/src/ril.cpp
@@ -5895,6 +5895,12 @@
                 {
                     speciaRequest_wait();
                 }
+#ifdef ECALL_SUPPORT
+                else if(request == RIL_REQUEST_ECALL_FAST_MAKE_ECALL)
+                {
+                    init_redial_flag();
+                }
+#endif
                 memset(Time_buf,0,sizeof(Time_buf));
                 GetTimeString(Time_buf);
                 //FUNCTION_CALLED(Time_buf,requestToString(request));
diff --git a/src/lynq/lib/liblynq-call/include/libcall/lynq_call.h b/src/lynq/lib/liblynq-call/include/libcall/lynq_call.h
index d0bc663..e157667 100755
--- a/src/lynq/lib/liblynq-call/include/libcall/lynq_call.h
+++ b/src/lynq/lib/liblynq-call/include/libcall/lynq_call.h
@@ -95,6 +95,11 @@
     LYNQ_ECALL_MAY_DEREGISTER = 32,

     LYNQ_ECALL_PSAP_CALLBACK_START = 40,

     LYNQ_ECALL_PSAP_CALLBACK_IMS_UPDATE_MSD = 41,

+    LYNQ_ECALL_T2_TIMER_OUT = 9000,

+    LYNQ_ECALL_T5_TIMER_OUT = 9001,

+    LYNQ_ECALL_T6_TIMER_OUT = 9002,

+    LYNQ_ECALL_T7_TIMER_OUT = 9003,

+    LYNQ_ECALL_REDIAL_TIMER_OUT = 9004,    

     LYNQ_ECALL_UNSPECIFIED = 0xffff,

 }LYNQ_ECall_Indication;

 

diff --git a/src/lynq/lib/liblynq-call/lynq_call.cpp b/src/lynq/lib/liblynq-call/lynq_call.cpp
index 48266b8..fd07b15 100755
--- a/src/lynq/lib/liblynq-call/lynq_call.cpp
+++ b/src/lynq/lib/liblynq-call/lynq_call.cpp
@@ -25,6 +25,7 @@
 #define LYNQ_REC_BUF 8192

 #define LYNQ_REQUEST_PARAM_BUF 8192

 #define LYQN_SEDN_BUF 1024*8+sizeof(int)*3

+#define INVALID_ID (-1)

 #define USER_LOG_TAG "LYNQ_CALL"

 

 using ::android::Parcel;

@@ -54,7 +55,6 @@
     int toa;

     int direction;/*0: MO call,1:MT call*/

     char addr[LYNQ_PHONE_NUMBER_MAX];

-    int hasTimeout;

 }lynq_call_list_e_t;

 typedef struct

 {

@@ -106,7 +106,13 @@
     /* The logic conflict*/

     LYNQ_E_CONFLICT=9000,

     /*Null anomaly*/

-    LYNQ_E_NULL_ANONALY=9001

+    LYNQ_E_NULL_ANONALY=9001,

+     /*Invalid id anomaly*/

+    LYNQ_E_INVALID_ID_ANONALY=9002,

+#ifdef ECALL_SUPPORT

+    LYNQ_E_ECALL_BEING_RUNNING =9003,

+    LYNQ_E_ECALL_MSD_LENGTH_ERROR =9004,

+#endif

 }LYNQ_E;

 typedef enum{

     LYNQ_E_VOLUMN_SET_DTMF,

@@ -124,6 +130,9 @@
 int lynqIncomingCallId = 0;

 

 #ifdef ECALL_SUPPORT

+int lynq_set_common_request(int request_id, int argc, const char* format,...);

+int is_ecall_dial = 0;

+int g_ecallId = INVALID_ID;

 typedef enum{        

     LYNQ_ECALL_TYPE_TEST = 0,     /* Test eCall */

     LYNQ_ECALL_TYPE_RECONFIG = 1,    /*    Reconfiguration eCall */    

@@ -131,22 +140,41 @@
     LYNQ_ECALL_TYPE_AUTO_EMERGENCY = 3,   /* Automatic Emergency eCall */\

 }LYNQ_ECall_Type;

 

-char e_call_addr[LYNQ_ECALL_VAR_MAX][LYNQ_PHONE_NUMBER_MAX]={"","null","112"};

-

-

+char e_call_addr[LYNQ_ECALL_VAR_MAX][LYNQ_PHONE_NUMBER_MAX]={"test_ecall","emergency_ecall","reconf_ecall"};

 

 static pthread_mutex_t s_incoming_e_call_mutex = PTHREAD_MUTEX_INITIALIZER;

 static pthread_cond_t s_incoming_e_call_cond = PTHREAD_COND_INITIALIZER;

 

-LYNQ_ECall_Indication lynqIncomingEcallIndication;

-int lynqEcallId;

+LYNQ_ECall_Indication g_lynqIncomingEcallIndication;

 

 void sendSignalIncomingECallEvent()

 {

+    LYINFLOG("send incoming ecall event signal");;

     pthread_mutex_lock(&s_incoming_e_call_mutex);

     pthread_cond_signal(&s_incoming_e_call_cond);

     pthread_mutex_unlock(&s_incoming_e_call_mutex);

 }

+

+int lynq_is_msd_suc(LYNQ_ECall_Indication lynqIncomingEcallIndication)

+{

+    if(LYNQ_ECALL_LLACK_RECEIVED == lynqIncomingEcallIndication ||

+       LYNQ_ECALL_ALACK_POSITIVE_RECEIVED == lynqIncomingEcallIndication ||

+       LYNQ_ECALL_ALACK_CLEARDOWN_RECEIVED == lynqIncomingEcallIndication ||

+       LYNQ_ECALL_T5_TIMER_OUT  == lynqIncomingEcallIndication ||

+       LYNQ_ECALL_T6_TIMER_OUT  == lynqIncomingEcallIndication ||

+       LYNQ_ECALL_T7_TIMER_OUT  == lynqIncomingEcallIndication)

+    {

+           return 1;

+    }

+

+    return 0;

+}

+

+int lynq_ecall_is_running()

+{

+    return (is_ecall_dial!=0) || (g_ecallId !=INVALID_ID);

+}

+

 #endif

 

 /**

@@ -177,7 +205,7 @@
     ret = sendto(sockfd, client_tmp, client_size, 0, (struct sockaddr *)&addr_serv, len_addr_serv);

     if(ret==-1)

     {

-        LYERRLOG("sendto error\n");

+        LYERRLOG("sendto error");

         return -1;

     }

     return 0;

@@ -192,7 +220,7 @@
     len = recvfrom(sockfd,recvline,LYNQ_REC_BUF, 0, (struct sockaddr *)&addr_serv,(socklen_t*)&len_addr_serv);

     if(len == -1)

     {

-        LYERRLOG("recvfrom error\n");

+        LYERRLOG("recvfrom error");

         return -1;

     }

     if (recvline != NULL) {

@@ -225,7 +253,7 @@
     client.request = 9;//RIL_REQUEST_GET_CURRENT_CALLS

     client.paramLen = 0;

     bzero(client.param,LYNQ_REQUEST_PARAM_BUF);

-    LYDBGLOG("uToken=%d,request=%d,paralen=%d,param=%s\n",client.uToken,client.request,client.paramLen,client.param);

+    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

@@ -245,7 +273,7 @@
             return 0;

         }

         lynq_call_state = CALL_ON;

-        LYINFLOG("lynq_call_state:%d",lynq_call_state);

+        LYINFLOG("lynq_call_state:%d, call num is %d ",lynq_call_state,call_num);

         for(int i = 0;i < call_num;i++)

         {

             p.readInt32(&temp);

@@ -281,12 +309,12 @@
 

 void cleanCallList(int lynq_call_id)

 {

+    LYINFLOG("cleanCall local idx is %d, id is %d",lynq_call_id,lynq_call_lists[lynq_call_id].call_id);

     lynq_call_lists[lynq_call_id].call_id = 0;

     lynq_call_lists[lynq_call_id].call_state = (int)LYNQ_CALL_END;

     lynq_call_lists[lynq_call_id].toa = 0;

     lynq_call_lists[lynq_call_id].direction = 0;

     lynq_call_lists[lynq_call_id].used = 0;

-    lynq_call_lists[lynq_call_id].hasTimeout = 0;

     memset(lynq_call_lists[lynq_call_id].addr,0,sizeof(lynq_call_lists[lynq_call_id].addr));

 }

 int getUnusedElement()

@@ -300,23 +328,22 @@
     }

     return -1;

 }

-int updateAddr(char addr[])

+int addAddr(char addr[])

 {

     int ret = 0;

     ret = getUnusedElement();

     memcpy(lynq_call_lists[ret].addr,addr,strlen(addr)+1);

     lynq_call_lists[ret].used = 1;

+    LYINFLOG("add local idx is %d addr is %s",ret,addr);

     return ret;

 }

 void updateCallList(lynq_call_list_e_t *callList,    int call_id,int call_state,int toa,int direction)

 {

-    LYINFLOG("Update Call List");

+    LYINFLOG("Update original local id is %d, new local id is %d",callList->call_id,call_id);

     callList->call_id = call_id;

     callList->call_state = call_state;

     callList->toa = toa;

-    callList->direction = direction;

-    callList->used = 1;

-    callList->hasTimeout = 0;

+    callList->direction = direction;   

     return;

 }

 int waitCallstateChange(int mtime)

@@ -348,28 +375,43 @@
 }

 int checkHasCall(char addr[])

 {

-    LYINFLOG("check has call");

     for(int i = 0;i<LYNQ_CALL_MAX;i++)

     {

         if(strcmp(lynq_call_lists[i].addr,addr)==0)

         {

+            LYINFLOG("checkHasCall addr is %s idx is %d id is %d",addr,i,lynq_call_lists[i].call_id);

             return 1;

         }

     }

+    LYINFLOG("checkHasCall addr is %s , no idx is found",addr);

     return 0;

 }

 int find_call_id_with_addr(char *addr)

 {

-    LYINFLOG("find call id with addr!!!");

     for(int id = 0; id < LYNQ_CALL_MAX; id++)

     {

-        if(strcmp(lynq_call_lists[id].addr,addr) == 0)

+        if(lynq_call_lists[id].used && (strcmp(lynq_call_lists[id].addr,addr) == 0))

         {

+            LYINFLOG("find addr  %s in local list, local idx is %d id is %d",addr,id,lynq_call_lists[id].call_id);

             return id;

         }

     }

+    LYINFLOG("find addr  %s in local list , not found",addr);

     return -1;

 }

+int find_call_id_with_call_id(int call_id)

+{

+    for(int id = 0; id < LYNQ_CALL_MAX; id++)

+    {

+        if(lynq_call_lists[id].used && (lynq_call_lists[id].call_id == call_id))

+        {

+            LYINFLOG("find id  %d in local list, local idx is %d, addr is %s",call_id,id,lynq_call_lists[id].addr);

+            return id;

+        }

+    }

+    LYINFLOG("find id  %d in local list , not found",call_id);

+    return INVALID_ID;

+}

 void sendSignalToWaitCallStateChange()

 {

     LYINFLOG("send Signal To Wait Call State Change");

@@ -393,7 +435,6 @@
     callList->direction = direction;

     memcpy(callList->addr,addr,strlen(addr)+1);

     callList->used = 1;

-    callList->hasTimeout = 0;

     return;

 }

 

@@ -401,120 +442,173 @@
 {

     int ret=0;

     bool call_end;

-    call_end = 0;//0:this call end,1:call on

     lynq_call_list_t call_list[LYNQ_CALL_MAX];

     int update=0;

+    int cnt;

+    int i,n;

+    

     while(call_list_loop)

     {

         update=0;

         pthread_mutex_lock(&s_urc_call_state_change_mutex);

         pthread_cond_wait(&s_urc_call_state_change_cond, &s_urc_call_state_change_mutex);

-        LYDBGLOG("triggerGetCallList event!!!\n");

+        LYDBGLOG("triggerGetCallList event!!!");

         memset(call_list,0,sizeof(call_list));

         ret = lynq_get_current_call_list(call_list);

         if(ret != 0)

         {

-            LYDBGLOG("get current call list failure!!!\n");

+            LYDBGLOG("get current call list failure!!!");

             continue;

         }

         LYINFLOG("++++++++++++++triggerGetCallList++++++++++++++");

-        for(int i = 0;i < LYNQ_CALL_MAX;i++)

+        LYINFLOG("clear local index begin");

+        cnt=0;

+        for(i = 0;i < LYNQ_CALL_MAX;i++)

         {

-            if(strlen(lynq_call_lists[i].addr) != 0)

+            if(lynq_call_lists[i].used ==0)

+            {

+                continue;

+            }

+            cnt++;

+            LYINFLOG("local idx is %d id is %d addr is %s state is %d direction is %d",i,lynq_call_lists[i].call_id,lynq_call_lists[i].addr,lynq_call_lists[i].call_state,lynq_call_lists[i].direction);

+            

+            if(lynq_call_lists[i].call_id > 0)

             {

                 call_end = 0;

-                for(int id = 0; id < LYNQ_CALL_MAX; id++)

+                for(n = 0; n < LYNQ_CALL_MAX; n++)

                 {

-                    if(strcmp(call_list[id].addr,lynq_call_lists[i].addr) == 0)

+                    if(call_list[n].call_id == lynq_call_lists[i].call_id)

                     {

                         call_end = 1;

-                        LYINFLOG("find lynq call i %d, id %d!!!",i,id);

+                        LYINFLOG("find lynq call local idx %d, service idx %d  id is %d!!!",i,n,lynq_call_lists[i].call_id);

+                        break;

                     }

                 }

                 if(call_end == 0)

                 {

-                    LYINFLOG("MT hungup,then clean call info");

-                    cleanCallList(i);

-                    continue;

+                    LYINFLOG("MT hungup,then clean call info local idx is %d id is %d",i, lynq_call_lists[i].call_id);

+                    cleanCallList(i);                   

                 }

             } //fix bug API-54

+            else 

+            {

+                LYINFLOG("local id is 0");

+            }

+        }

+        LYINFLOG("clear local index end, local used cnt is %d", cnt);

+

+        LYINFLOG("add or update local index begin ");

+        for (i = 0;i < LYNQ_CALL_MAX;i++)

+        {    

+            if(call_list[i].call_id==0)

+            {

+                break;

+            }

+

+            LYINFLOG("servie idx %d begin: call_id=%d, call_state=%d, direction=%d, addr=%s, toa=%d",i,call_list[i].call_id, call_list[i].call_state,

+                call_list[i].direction,call_list[i].addr,call_list[i].toa);

+        

             if(call_list[i].direction == 1)//MT call

             {

+                 LYINFLOG("This is a MT CALL");

                  /*MT CALL state code

                  **LYNQ_CALL_INCOMING = 4,

                  **LYNQ_CALL_WAITING = 5,

                  */

                 if((call_list[i].call_state ==4) || (call_list[i].call_state ==5))

                 {

-                    /*you call me, and i call you,One party failed to dial*/

-                    if(!checkHasCall(call_list[i].addr))

+#ifdef ECALL_SUPPORT

+                    if(lynq_ecall_is_running())

                     {

-                        lynqIncomingCallId = getUnusedElement();

-                        addCallListToLynqCallList(&lynq_call_lists[lynqIncomingCallId],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction,call_list[i].addr);

-                        sendSignalIncomingCall();

+                        lynq_call_hungup(&(call_list[i].call_id));

+                        continue;

                     }

-                    else

+#endif          

+                }

+                /*you call me, and i call you,One party failed to dial*/

+                n = find_call_id_with_addr(call_list[i].addr);

+                if(n ==INVALID_ID)

+                {

+                    n = addAddr(call_list[i].addr);

+                    updateCallList(&lynq_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

+                    lynqIncomingCallId = call_list[i].call_id;

+                    sendSignalIncomingCall();

+                }

+                else if(lynq_call_lists[n].call_state == call_list[i].call_state)

+                {

+                    LYINFLOG("state not changed, state is %d ",call_list[i].call_state);

+                    if(call_list[i].call_state ==4 || call_list[i].call_state ==5)

                     {

-                        int temp_call_id = find_call_id_with_addr(call_list[i].addr);

                         /*if call state not change,Maybe this call was ignored, so we need to continue to inform the user of 

                         **an incoming call until the status changes.

                         **fix bug API-54

                         */

-                        if((temp_call_id > 0) && (lynq_call_lists[temp_call_id].call_state == call_list[i].call_state))

-                        {

-                            sendSignalIncomingCall();

-                        }

+                        LYINFLOG("resend incoming call signal");

+                        sendSignalIncomingCall();

                     }

                 }

-                /*if state changed*/

-                else

+                else 

                 {

-                    /*update call state*/

-                    for(int n = 0 ; n < LYNQ_CALL_MAX; n++)

-                    {

-                        if(strcmp(call_list[i].addr,lynq_call_lists[n].addr)==0)

-                        {

-                            updateCallList(&lynq_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

-                            break;

-                        }

-                    }

-                }

+                    LYINFLOG("state changed from %d to %d",lynq_call_lists[n].call_state,call_list[i].call_state);

+                    

+                    updateCallList(&lynq_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

+                }                               

             }

             else

-            {

-                if(call_list[i].call_id==0)

+            {     

+                LYINFLOG("This is a MO CALL");

+                call_end = 0;

+                for(n = 0 ; n < LYNQ_CALL_MAX; n++)

                 {

-                    break;

-                }

-                for(int n = 0 ; n < LYNQ_CALL_MAX; n++)

-                {

-                    if((lynq_call_lists[n].hasTimeout == 1) && (strcmp(lynq_call_lists[n].addr,call_list[i].addr) == 0))

+                    if(lynq_call_lists[n].used && ((strcmp(call_list[i].addr,lynq_call_lists[n].addr)==0)||(call_list[i].call_id==lynq_call_lists[n].call_id)))

                     {

-                        cleanCallList(n);//if this call time out,need clean lynq call list.

-                        /*hangup call with call id*/

-                        lynq_call_hungup(&call_list[i].call_id);

-                        lynq_call_lists[n].hasTimeout==0;

+                        if(lynq_call_lists[n].call_id==0)

+                        {

+                             LYINFLOG("add a call id");

+                             update=1;

+                        }

+                        LYINFLOG("local idx %d updated, original call id is %d origial addr is %s original state is %d",n,lynq_call_lists[n].call_id,lynq_call_lists[n].addr,lynq_call_lists[n].call_state);                    

+                        updateCallList(&lynq_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

+                        call_end = 1;

+                        break;

+                    }                    

+                }

+

+                if(call_end == 0)

+                {  

+                    LYINFLOG("need to hangup id %d", call_list[i].call_id);

+#ifdef ECALL_SUPPORT

+                    if(is_ecall_dial==1)

+                    {

+                        LYINFLOG("ecall is dialing, for the timebeing, don't huangup");

                         continue;

                     }

-                    LYDBGLOG("lynq_call_lists n is %d, used is %d, addr is %s addr2 %s\n",

-                    n,lynq_call_lists[n].used,call_list[i].addr,lynq_call_lists[n].addr);

-                    if(lynq_call_lists[n].used && (strcmp(call_list[i].addr,lynq_call_lists[n].addr)==0))

-                    {

-                        LYINFLOG("updated\n");                    

-                        updateCallList(&lynq_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

-                        update=1;

-                        break;

-                    }

+#endif

+                    LYINFLOG("hang up service call id %d",call_list[i].call_id); 

+                    lynq_call_hungup(&(call_list[i].call_id));

                 }

-                LYDBGLOG("[count:%d]call_id=%d,call_state=%d,direction=%d,addr=%s,toa=%d",i,call_list[i].call_id,call_list[i].call_state,

-                call_list[i].direction,call_list[i].addr,call_list[i].toa);

             }

+            LYDBGLOG("servie idx %d end",i);

         }

+        LYINFLOG("add or update local index end ");

         s_call_urc_event_complete = 1;

-        if((isDial==1) && (update==1))

+        if(isDial==1)

         {

-            sendSignalToWaitCallStateChange();

-            isDial = 0;

+            LYINFLOG("now is dialing");

+            if(update==1)

+            {

+                LYINFLOG("find added call");

+                sendSignalToWaitCallStateChange();

+                isDial = 0;

+            }    

+            else

+            {

+                LYINFLOG("not find added call");

+            }                

+        }

+        else 

+        {

+            LYINFLOG("now is not dialing");

         }

         pthread_mutex_unlock(&s_urc_call_state_change_mutex);

     }

@@ -547,14 +641,14 @@
     /*

     if(inet_pton(AF_INET,"127.0.0.1", &lynq_socket_server_addr.sin_addr) <= 0)

     {

-        LYDBGLOG("[%s] is not a valid IPaddress\n", argv[1]);

+        LYDBGLOG("[%s] is not a valid IPaddress", argv[1]);

         exit(1);

     }

 */

     lynq_call_client_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

     if(connect(lynq_call_client_sockfd, (struct sockaddr *)&lynq_socket_server_addr, sizeof(lynq_socket_server_addr)) == -1)

     {

-        LYERRLOG("connect error\n");

+        LYERRLOG("connect error");

         return -1;

     }

     #endif

@@ -583,10 +677,11 @@
         LYERRLOG("lynq_update_call_list_loop fail!!!");

         return -1;

     }

-    LYDBGLOG("lynq_update_call_list_loop success!!!\n");

+    LYDBGLOG("lynq_update_call_list_loop success!!!");

     return 0;

 

 }

+

 void *thread_urc_recv(void *parg)

 {

     int socket_fd = (int64_t)parg;

@@ -600,10 +695,12 @@
     Parcel *p = NULL;

     struct sockaddr_in dest_addr;

 #ifdef ECALL_SUPPORT

-    int ecall_ind;    

+    int ecall_ind;

+    int ecallId;

+    int unused_callid;

 #endif

 

-    LYINFLOG("thread_urc_recv in running....\n");

+    LYINFLOG("thread_urc_recv in running....");

     while(urc_call_recive_status)

     {

         bzero(urc_data,LYNQ_REC_BUF);

@@ -611,10 +708,10 @@
         len = recvfrom(socket_fd,urc_data,LYNQ_REC_BUF,0,(struct sockaddr *)&dest_addr,&addr_len);

         if(len <= 0)

         {

-            LYERRLOG("thread_urc_recv step2 fail\n");

+            LYERRLOG("thread_urc_recv step2 fail");

             break;

         }

-        LYDBGLOG("=====>urc data len<=====:%d\n",len);

+        LYDBGLOG("=====>urc data len<=====:%d",len);

         p = new Parcel();

         if(p==NULL)

         {

@@ -628,12 +725,12 @@
             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);

+            //LYDBGLOG("*******Warren test*******:resp_type=%d,urcid=%d,slot_id=%d",resp_type,urcid,slot_id);

             switch (urcid)

             {

                 case 1001://RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED

                 {

-                    LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d\n",resp_type,urcid,slot_id);

+                    LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d",resp_type,urcid,slot_id);

                     lynqRespWatingEvent();

                     break;

                 }

@@ -648,24 +745,95 @@
                 case 1029://RIL_UNSOL_RINGBACK_TONE

                 case 3049://RIL_UNSOL_CALL_INFO_INDICATION

                 {

-                     LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d\n",resp_type,urcid,slot_id);

+                    LYINFLOG("**************:resp_type=%d,urcid=%d,slot_id=%d",resp_type,urcid,slot_id);

                     break;

                 }

 #ifdef ECALL_SUPPORT

                 case RIL_UNSOL_ECALL_INDICATIONS:

                 {

-                    p->readInt32(&ecall_ind);                  

-                    lynqIncomingEcallIndication=ecall_ind;

-                    if(LYNQ_ECALL_ACTIVE==lynqIncomingEcallIndication)

-                    {

-                        if(isDial==1)

-                        {                               

-                            p->readInt32(&lynqEcallId);

+                    p->readInt32(&ecall_ind);   

+                    g_lynqIncomingEcallIndication = ecall_ind;

+                    p->readInt32(&ecallId);

+                    LYINFLOG("**************:RIL_UNSOL_ECALL_INDICATIONS ,Id %d, ind %d, ecall dialing is %d, normal dialing is %d, local ecall id is %d",ecallId,ecall_ind,is_ecall_dial,isDial,g_ecallId);

+                    if(lynq_is_msd_suc(g_lynqIncomingEcallIndication)) 

+                    {                        

+                        if(is_ecall_dial)

+                        {

+                            LYINFLOG("ecall is dialing, recv suc indication");

+                            is_ecall_dial=0;

+                            if(ecallId >0 && find_call_id_with_call_id(ecallId)==INVALID_ID)

+                            {

+                                  LYINFLOG("add ecall in loacl list");

+                                  g_ecallId = ecallId;

+                                  unused_callid=addAddr("ecall");

+                                  lynq_call_lists[unused_callid].call_id=g_ecallId;

+                            }        

                             sendSignalToWaitCallStateChange();

-                            usleep(300*1000);

-                        }                              

-                    }     

+                        }        

+                        else if(ecallId >0 && (find_call_id_with_call_id(ecallId)==INVALID_ID)){

+                            LYERRLOG("ecall is not in dialing and first recv suc indication, hangup");

+                            lynq_call_hungup(&ecallId);

+                        }   

+                        else 

+                        {

+                             LYERRLOG("ecall is not in dialing and not first recv suc indication");

+                        }

+                    } 

+                    else if (LYNQ_ECALL_PSAP_CALLBACK_START == g_lynqIncomingEcallIndication)

+                    {

+                        if(lynq_ecall_is_running()==0)

+                        {

+                            LYINFLOG("ecall is not running, recv psap call back msd start, set ecall in dialing");

+                            is_ecall_dial=1;

+                            if(isDial)

+                            {

+                                LYINFLOG("stop normal dial");

+                                sendSignalToWaitCallStateChange();

+                            }

+                            else 

+                            {

+                                LYINFLOG("no normal dial");

+                            }                            

+                        }

+                        else 

+                        {

+                            LYERRLOG("ecall is running, recv psap call back msd start");

+                        }

+                    }

+                    else if (LYNQ_ECALL_ABNORMAL_HANGUP == g_lynqIncomingEcallIndication)

+                    {

+                        if(is_ecall_dial==0)                             

+                        {

+                            LYERRLOG("ecall is not in dialing, recv abnormal hangup");

+                            g_ecallId = INVALID_ID;

+                        }

+                        else 

+                        {

+                            LYINFLOG("ecall is in dialing, recv abnormal hangup");

+                        }

+                    }

+                    else if (LYNQ_ECALL_DISCONNECTED == g_lynqIncomingEcallIndication ||

+                            LYNQ_ECALL_REDIAL_TIMER_OUT == g_lynqIncomingEcallIndication ||

+                            LYNQ_ECALL_T2_TIMER_OUT == g_lynqIncomingEcallIndication)

+                    {

+                        g_ecallId = INVALID_ID;

+                        if(is_ecall_dial)

+                        {

+                            LYERRLOG("ecall is in dialing, recv like disconnect indication");

+                            is_ecall_dial=0;

+                            sendSignalToWaitCallStateChange();

+                        }

+                        else 

+                        {

+                            LYINFLOG("ecall is not in dialing, recv like disconnect indication");

+                        }

+                    }

+                    else 

+                    {

+                        LYINFLOG("not special indication");

+                    }                    

                     sendSignalIncomingECallEvent();

+                    LYINFLOG("**************:RIL_UNSOL_ECALL_INDICATIONS, local ecall id is %d", g_ecallId);

                     break;

                  }

 #endif

@@ -689,7 +857,7 @@
     socket_fd = socket(AF_INET,SOCK_DGRAM,0);

     if(socket_fd < 0)

     {

-        LYERRLOG("creaet socket for udp fail\n");

+        LYERRLOG("creaet socket for udp fail");

         return -1;

     }

     urc_local_addr.sin_family = AF_INET;

@@ -699,7 +867,7 @@
     rt = setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on);

     if(rt<0)

     {

-        LYERRLOG("SO_REUSEADDR fail\n");

+        LYERRLOG("SO_REUSEADDR fail");

         return -1;

     }

     rt = bind(socket_fd ,(struct sockaddr*)&urc_local_addr, sizeof(urc_local_addr));

@@ -713,10 +881,10 @@
     rt = pthread_create(&lynq_call_urc_tid,&attr,thread_urc_recv,(void *)socket_fd);

     if(rt < 0)

     {

-        LYERRLOG("urc loop failure!!!\n");

+        LYERRLOG("urc loop failure!!!");

         return -1;

     }

-    LYDBGLOG("urc loop success!!!\n");

+    LYDBGLOG("urc loop success!!!");

     return 0;

 }

 int getSelfElement(char addr[])

@@ -737,7 +905,7 @@
 

 void lynq_call_state_change_test(int soc_id)

 {

-    LYDBGLOG("call state change,sim:%d\n",soc_id);

+    LYDBGLOG("call state change,sim:%d",soc_id);

 }

 int lynq_init_call(int uToken)

 {   

@@ -773,6 +941,7 @@
 }

 int lynq_deinit_call()

 {

+    int ret;

     if(g_lynq_call_init_flag == 0)

     {

         LYDBGLOG("lynq_deinit_call failed!!!");

@@ -781,7 +950,7 @@
     else

     {   

         g_lynq_call_init_flag = 0;

-        int ret = -1;

+        lynq_call_hungup_all();       

         if(lynq_call_client_sockfd>0)

         {

             close(lynq_call_client_sockfd);

@@ -824,7 +993,7 @@
         vsnprintf(client.param, LYNQ_REQUEST_PARAM_BUF, format, args);

         va_end(args);    

     }

-    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s\n",client.uToken,client.request,client.paramLen,client.param);

+    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

@@ -855,7 +1024,7 @@
     client.request = request_id;

     client.paramLen = 0;

     bzero(client.param,LYNQ_REQUEST_PARAM_BUF);

-    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s\n",client.uToken,client.request,client.paramLen,client.param);

+    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

@@ -879,27 +1048,45 @@
     int slot_id = -1;

     int error = -1;

     int lynq_call_id = -1;

+

+    LYINFLOG("lynq_call begin addr %s",addr);

     if(addr==NULL)

     {

         LYERRLOG("Phone num is null!!!");

         return -1;

     }

+

+    if(find_call_id_with_addr(addr)!=INVALID_ID)

+    {

+        LYERRLOG("addr %s exists",addr);

+        return LYNQ_E_CONFLICT;

+    }

+

+#ifdef ECALL_SUPPORT

+    if(lynq_ecall_is_running())

+    {

+        LYERRLOG("lynq_fast_ecall ecall is running");

+        return LYNQ_E_ECALL_BEING_RUNNING;

+    }

+#endif   

+    

     client.uToken = Global_uToken_call;

     client.request = 10;//RIL_REQUEST_DIAL

     client.paramLen = 2;

     bzero(client.param,LYNQ_REQUEST_PARAM_BUF);

     memcpy(client.param,addr,strlen(addr)+1);

     strcat(client.param," 0");

-    LYERRLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

+    lynq_call_id = addAddr(addr);

+    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

+        cleanCallList(lynq_call_id);   

         return -1;

     }

     get_response(lynq_call_client_sockfd,p);

     JumpHeader(p,&resp_type,&request,&slot_id,&error);

     LYINFLOG("resp_type=%d,request=%d,slot_id=%d,error_code=%d",resp_type,request,slot_id,error);

-    lynq_call_id = updateAddr(addr);

     if(error==0)

     {

         isDial = 1;

@@ -907,14 +1094,28 @@
         {

             //if timeout,this call need destroy.

             isDial = 0;

-

             error = LYNQ_E_TIME_OUT;

-            LYERRLOG("timeout:wait Call state fail!!!");

-            lynq_call_lists[lynq_call_id].hasTimeout = 1;

+            LYERRLOG("lynq_call timeout:wait Call state fail!!! clear local idx %d",lynq_call_id);

+            cleanCallList(lynq_call_id);            

             return error;

         }

-    *handle = lynq_call_id;

+         isDial = 0;

+        *handle = lynq_call_lists[lynq_call_id].call_id;

+        if(*handle > 0)

+        {

+            LYINFLOG("lynq_call dial addr %s suc, id is %d",addr,*handle);

+            return 0;

+        }

+        else 

+        {   

+            LYERRLOG("lynq_call dial addr %s fail, invalid id",addr);

+            cleanCallList(lynq_call_id);      

+            return LYNQ_E_INVALID_ID_ANONALY;

+        }      

+        

     }

+    LYERRLOG("lynq_call dial addr %s fail, service error %d",addr, error);

+    cleanCallList(lynq_call_id);      

     return error;

 }

 int lynq_call_answer()

@@ -929,7 +1130,7 @@
     client.request = 40;//RIL_REQUEST_DIAL

     client.paramLen = 0;

     bzero(client.param,LYNQ_REQUEST_PARAM_BUF);

-    LYDBGLOG("uToken=%d,request=%d,paralen=%d,param=%s\n",client.uToken,client.request,client.paramLen,client.param);

+    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

@@ -949,7 +1150,7 @@
     int slot_id = -1;

     int error = -1;

     int call_id = 0;

-    int lynq_call_id = 0;

+    int lynq_call_id;

     if(handle==NULL||!((*handle>=0)&&(*handle<10)))

     {

         LYERRLOG("[%s] illegal input!!!!",__FUNCTION__);

@@ -959,10 +1160,9 @@
     client.request = 12;//RIL_REQUEST_HUNGUP

     client.paramLen = 1;

     bzero(client.param,LYNQ_REQUEST_PARAM_BUF);

-    lynq_call_id = *handle;

-    call_id = lynq_call_lists[lynq_call_id].call_id;

+    call_id = *handle;

     sprintf(client.param,"%d",call_id);

-    LYDBGLOG("uToken=%d,request=%d,paralen=%d,param=%s\n",client.uToken,client.request,client.paramLen,client.param);

+    LYINFLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

@@ -973,7 +1173,11 @@
     LYINFLOG("resp_type=%d,request=%d,slot_id=%d,error_code=%d",resp_type,request,slot_id,error);

     if(error==0)

     {

-        cleanCallList(lynq_call_id);

+        lynq_call_id=find_call_id_with_call_id(call_id);

+        if(lynq_call_id!=INVALID_ID)

+        {

+            cleanCallList(lynq_call_id);

+        }        

     }

     return error;

 }

@@ -989,7 +1193,7 @@
     client.request = 17;//RIL_REQUEST_UDUB

     client.paramLen = 0;

     bzero(client.param,LYNQ_REQUEST_PARAM_BUF);

-    LYDBGLOG("uToken=%d,request=%d,paralen=%d,param=%s\n",client.uToken,client.request,client.paramLen,client.param);

+    LYDBGLOG("uToken=%d,request=%d,paralen=%d,param=%s",client.uToken,client.request,client.paramLen,client.param);

     if(send_request(lynq_call_client_sockfd,&client)==-1)

     {

         LYERRLOG("send request fail");

@@ -1017,11 +1221,17 @@
 int lynq_get_current_call_state(int *handle,    int *call_state,int *toa,int *direction,char addr[])

 {

     int lynq_call_id = 0;

+    LYINFLOG("lynq_get_current_call_state begin ");

     if(handle==NULL)

     {

+        LYERRLOG("handle is NULL");

         return LYNQ_E_NULL_ANONALY;

     }

-    lynq_call_id = *handle;

+    lynq_call_id = find_call_id_with_call_id(*handle);

+    if(lynq_call_id==INVALID_ID)

+    {

+        return LYNQ_E_INVALID_ID_ANONALY;

+    }

     *call_state = lynq_call_lists[lynq_call_id].call_state;

     *toa = lynq_call_lists[lynq_call_id].toa;

     *direction = lynq_call_lists[lynq_call_id].direction;

@@ -1124,7 +1334,7 @@
 } 

 int lynq_incall_record_start(const char* file_path)

 {

-	return lynq_set_common_request(8011,2,"%s %s","1",file_path); //LYNQ_REQUEST_RECORD

+    return lynq_set_common_request(8011,2,"%s %s","1",file_path); //LYNQ_REQUEST_RECORD

 }

 int lynq_incall_record_stop()

 {

@@ -1178,7 +1388,7 @@
 

     if(test_num==NULL || test_num_length > LYNQ_PHONE_NUMBER_MAX )

     {

-       LYERRLOG("test_num is null or test_num_length %d s greater than %d\n ",test_num_length,LYNQ_PHONE_NUMBER_MAX);

+       LYERRLOG("test_num is null or test_num_length %d s greater than %d ",test_num_length,LYNQ_PHONE_NUMBER_MAX);

        return -1;

     }       

     

@@ -1192,20 +1402,23 @@
     return error;

 }

 

-

 int lynq_fast_ecall(int* handle, LYNQ_ECall_Category lynq_ecall_cat, LYNQ_ECall_Variant lynq_ecall_variant,  const char *addr, int addr_length, const unsigned char *msd_data,int msd_length)

 {

-    int error = -1;

-    int lynq_call_id = -1;

+    int error;

     RIL_ECall_Variant ril_ecall_variant = lynq_get_ril_ecall_variant_from_lynq_variant (lynq_ecall_variant);

     RIL_ECall_Category ril_ecall_cat = lynq_get_ril_ecall_cat_from_lynq_cat(lynq_ecall_cat);

     char lynq_msd_data[MSD_MAX_LENGTH*2+1]={0};

     unsigned int i;

-

-    if(msd_length > MSD_MAX_LENGTH)

+    if(lynq_ecall_is_running())

     {

-        LYERRLOG("msd_length %d is greater than %d, parameter error\n",msd_length,MSD_MAX_LENGTH);

-        return -1;

+        LYERRLOG("lynq_fast_ecall ecall is running");

+        return LYNQ_E_ECALL_BEING_RUNNING;

+    }

+

+    if(msd_length > MSD_MAX_LENGTH || msd_length <=0)

+    {

+        LYERRLOG("lynq_fast_ecall msd_length %d is greater than %d or <= 0, parameter error",msd_length,MSD_MAX_LENGTH);

+        return LYNQ_E_ECALL_MSD_LENGTH_ERROR;

     }    

 

     for(i =0; i<msd_length;i++)

@@ -1213,33 +1426,35 @@
         sprintf(&(lynq_msd_data[i<<1]),"%02x",msd_data[i]);

     }    

 

-    lynq_call_id = updateAddr(e_call_addr[lynq_ecall_variant]);

 

-    LYINFLOG("e_call_addr is %s\n",e_call_addr[lynq_ecall_variant]);

+    LYINFLOG("lynq_fast_ecall addr is %s",e_call_addr[lynq_ecall_variant]);

 

     error=lynq_set_common_request(RIL_REQUEST_ECALL_FAST_MAKE_ECALL,4,"%d %d %s %s",ril_ecall_cat, ril_ecall_variant, "null", lynq_msd_data);

    

     if(error==0)

-    {        

-        isDial = 1;

-        if(waitCallstateChange(30000)==ETIMEDOUT)//30000ms

+    {   

+        is_ecall_dial = 1;

+        if(waitCallstateChange(180000)==ETIMEDOUT)//180000ms

         {

-            isDial = 0;

-            error = LYNQ_E_TIME_OUT;

-            cleanCallList(lynq_call_id);

-            LYERRLOG("timeout:wait Call state fail!!!");           

-            return error;

+            LYERRLOG("lynq_fast_ecall timeout:wait Call state time out!!!");       

+            is_ecall_dial = 0;

+            lynqRespWatingEvent();                

+            return LYNQ_E_TIME_OUT;

         }

-         

-        *handle = lynq_call_id;

-        if(lynq_ecall_variant==LYNQ_ECALL_EMERGENCY){

-            lynq_call_lists[lynq_call_id].call_id=lynqEcallId;

-        }

-        LYINFLOG("lynq_fast_ecall handle is:%d, call id is %d",lynq_call_id,lynq_call_lists[lynq_call_id].call_id);

+        is_ecall_dial = 0;

+        lynqRespWatingEvent();        

         

-    }

-    else {

-        cleanCallList(lynq_call_id);

+        if(g_ecallId != INVALID_ID)

+        {

+            *handle=g_ecallId;         

+            LYINFLOG("lynq_fast_ecall id is %d",g_ecallId);

+            return 0;

+        }

+        else 

+        {

+            LYERRLOG("lynq_fast_ecall service return fail");

+            return LYNQ_E_INVALID_ID_ANONALY;

+        }               

     }

 

     return error;

@@ -1263,7 +1478,7 @@
 

     if(handle==NULL)

     {

-        LYERRLOG("handle is NULL, parameter error \n ");

+        LYERRLOG("handle is NULL, parameter error  ");

            return -1;

     }

     

@@ -1273,13 +1488,12 @@
     {

         lynq_ecall_variant=lynq_get_lynq_ecall_variant_from_lynq_type(type);

       

-        lynq_call_id = updateAddr(e_call_addr[lynq_ecall_variant]);

+        lynq_call_id = addAddr(e_call_addr[lynq_ecall_variant]);

         isDial = 1;

         if(waitCallstateChange(10000)==ETIMEDOUT)//10000ms

         {

             error = LYNQ_E_TIME_OUT;

             LYERRLOG("timeout:wait Call state fail!!!");

-            lynq_call_lists[lynq_call_id].hasTimeout = 1;

             return error;

         }

  

@@ -1295,23 +1509,31 @@
     char lynq_msd_data[MSD_MAX_LENGTH*2+1]={0};

     unsigned int i;

 

-    if(handle==NULL || ((*handle) >= LYNQ_CALL_MAX) || msd_length > MSD_MAX_LENGTH)

+    if(handle==NULL || ((*handle) >= LYNQ_CALL_MAX) || msd_length > MSD_MAX_LENGTH || msd_length == 0 || msd_data ==NULL)

     {

-        LYERRLOG("handle is NULL or *handle %d is greater or equeal to %d or msd_length %d is greater than %d, parameter error\n",*handle,LYNQ_CALL_MAX,msd_length,MSD_MAX_LENGTH);

+        LYERRLOG("lynq_set_msd handle is NULL or *handle %d is greater or equeal to %d or msd_length %d is greater than %d or msd_data %s is NULL, parameter error",*handle,LYNQ_CALL_MAX,msd_length,MSD_MAX_LENGTH, msd_data);

         return -1;

     }    

 

     for(i=0; i<msd_length;i++)

     {

         sprintf(&(lynq_msd_data[i<<1]),"%02x",msd_data[i]);

-    }    

+    }   

+

+    LYINFLOG("lynq_set_msd ");

 

     return lynq_set_common_request(RIL_REQUEST_ECALL_SET_MSD,2,"%d %s",lynq_call_lists[(*handle)].call_id,lynq_msd_data);

 }

 

 int lynq_set_ivs(int enable)

 {

-    return lynq_set_common_request(RIL_REQUEST_ECALL_SET_IVS,1,"%d",enable);

+    if(enable<0)

+    {

+       lynq_set_common_request(RIL_REQUEST_ECALL_SET_IVS,1,"%d",enable);

+       return 0;

+    }

+

+    return lynq_set_common_request(RIL_REQUEST_ECALL_SET_IVS,1,"%d",enable);    

 }

 

 int lynq_reset_ivs()

@@ -1329,15 +1551,15 @@
     int ret = 0;

     pthread_mutex_lock(&s_incoming_e_call_mutex);

     ret = pthread_cond_wait(&s_incoming_e_call_cond,&s_incoming_e_call_mutex);

-    pthread_mutex_unlock(&s_incoming_e_call_mutex);

+    pthread_mutex_unlock(&s_incoming_e_call_mutex); 

     return ret;

 }

 

 int lynq_wait_ecall_indication(LYNQ_ECall_Indication *eCall_Indication)

 {

     wait_ecall_event();

-    *eCall_Indication = lynqIncomingEcallIndication;

-    LYINFLOG("lynq incoming e-call indication id:%d",lynqIncomingEcallIndication);

+    *eCall_Indication = g_lynqIncomingEcallIndication;

+    LYINFLOG("lynq_wait_ecall_indication id: %d",g_lynqIncomingEcallIndication);

     return 0;

 }

 

@@ -1350,10 +1572,10 @@
     n = lynq_init_call(lynq_call_state_change_test,2222);

     if(n<0)

     {

-        LYDBGLOG("lynq init call fail!!!\n");

+        LYDBGLOG("lynq init call fail!!!");

         return -1;

     }

-    LYDBGLOG("lynq call init success!!!\n");

+    LYDBGLOG("lynq call init success!!!");

     char phoneNum[LYNQ_PHONE_NUMBER_MAX];

     sprintf(phoneNum,"18180053406 0",strlen("18180053406 0")+1);

     lynq_call(phoneNum);