[Bugfix][API-551][ecall] bug fix in lab certification test, from GSW-ECALL to main branch

Change-Id: Idf83ae02ee7d309efabc6b5782a063116b83b164
diff --git a/lib/liblynq-call/lynq_call.cpp b/lib/liblynq-call/lynq_call.cpp
index b90b44b..b0ba48a 100755
--- a/lib/liblynq-call/lynq_call.cpp
+++ b/lib/liblynq-call/lynq_call.cpp
@@ -179,9 +179,12 @@
 

 static pthread_mutex_t s_incoming_e_call_mutex = PTHREAD_MUTEX_INITIALIZER;

 static pthread_cond_t s_incoming_e_call_cond = PTHREAD_COND_INITIALIZER;

+static pthread_mutex_t s_ecall_variable_mutex = PTHREAD_MUTEX_INITIALIZER;

 

 LYNQ_ECall_Indication g_lynqIncomingEcallIndication;

-int g_lynqIncomingEcallId;

+int g_lynqIncomingEcallId=INVALID_ID;

+LYNQ_ECall_Variant g_lynqEcallVariant=LYNQ_ECALL_VAR_NONE;

+int g_ecall_whether_preempt=0;

 

 void sendSignalIncomingECallEvent()

 {

@@ -196,7 +199,7 @@
     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_T5_TIMER_OUT  == lynqIncomingEcallIndication ||

        LYNQ_ECALL_T6_TIMER_OUT  == lynqIncomingEcallIndication ||

        LYNQ_ECALL_T7_TIMER_OUT  == lynqIncomingEcallIndication)

     {

@@ -208,7 +211,22 @@
 

 int lynq_ecall_is_running()

 {

-    return (is_ecall_dial!=LYNQ_ECALL_DAILING_STATE_NONE) || (g_ecallId !=INVALID_ID);

+    return (is_ecall_dial!=LYNQ_ECALL_DAILING_STATE_NONE) || (g_ecallId !=INVALID_ID || g_lynqEcallVariant == LYNQ_ECALL_CALLBACK);

+}

+

+void print_ecall_info()

+{

+     LYERRLOG("%s is ecall dial is %d, ecall id is %d, ecall vairant is %d, incoming ecall ind is %d, incoming ecall id is %d, whether preempt is %d",__func__,is_ecall_dial,g_ecallId,g_lynqEcallVariant,g_lynqIncomingEcallIndication,g_lynqIncomingEcallId,g_ecall_whether_preempt);

+}

+

+int lynq_ecall_is_permit_in_call(int ecall_id)

+{

+    return g_lynqEcallVariant == LYNQ_ECALL_CALLBACK && (g_ecallId ==INVALID_ID || g_ecallId ==ecall_id);

+}

+

+int lynq_ecall_is_in_voice()

+{

+    return (is_ecall_dial==LYNQ_ECALL_DAILING_STATE_NONE) && (g_ecallId !=INVALID_ID);

 }

 #endif

 

@@ -481,6 +499,9 @@
     int update=0;

     int cnt;

     int i,n;

+#ifdef ECALL_SUPPORT

+    int handupIncomingMT=0;

+#endif

     

     while(call_list_loop)

     {

@@ -550,16 +571,21 @@
                  **LYNQ_CALL_INCOMING = 4,

                  **LYNQ_CALL_WAITING = 5,

                  */

+#ifdef ECALL_SUPPORT

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

                 {

-#ifdef ECALL_SUPPORT

-                    if(lynq_ecall_is_running())

+

+                    pthread_mutex_lock(&s_ecall_variable_mutex);

+                    handupIncomingMT=lynq_ecall_is_running() && (lynq_ecall_is_permit_in_call(call_list[i].call_id)==false);   

+                    pthread_mutex_unlock(&s_ecall_variable_mutex);  

+                    LYINFLOG("handupIncomingMT is %d",handupIncomingMT);

+                    if(handupIncomingMT)

                     {

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

                         continue;

-                    }

-#endif          

+                    }         

                 }

+#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)

@@ -741,6 +767,8 @@
     int ecall_ind;

     int ecallId;

     int unused_callid;

+    int send_signal_to_wait_call_state;

+    int handup_ecall_id;

 #endif

 

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

@@ -794,6 +822,9 @@
 #ifdef ECALL_SUPPORT

                 case RIL_UNSOL_ECALL_INDICATIONS:

                 {

+                    pthread_mutex_lock(&s_ecall_variable_mutex);

+		            send_signal_to_wait_call_state = false;

+                    handup_ecall_id=false;

                     p->readInt32(&ecall_ind);   

                     g_lynqIncomingEcallIndication = ecall_ind;

                     p->readInt32(&ecallId);

@@ -807,10 +838,17 @@
                                 is_ecall_dial = LYNQ_ECALL_DAILING_STATE_ANSWERED;

                             }

                             break;

+                       case LYNQ_ECALL_SENDING_START:

+                            if(lynq_ecall_is_in_voice())

+                            {

+                                LYINFLOG("recv msd in voice, ind is changed to %d",LYNQ_ECALL_SENDING_START_IN_VOICE);

+                                g_lynqIncomingEcallIndication = LYNQ_ECALL_SENDING_START_IN_VOICE; 

+                            }

+                            break;

                        case LYNQ_ECALL_LLACK_RECEIVED:

                        case LYNQ_ECALL_ALACK_POSITIVE_RECEIVED:

                        case LYNQ_ECALL_ALACK_CLEARDOWN_RECEIVED:

-                       case LYNQ_ECALL_T5_TIMER_OUT:

+                       //case LYNQ_ECALL_T5_TIMER_OUT:  /*when Certificate CP 1.1.10.2, no msd start (ind 1), so T5 timeout is not regard as success*/

                        case LYNQ_ECALL_T6_TIMER_OUT:

                        case LYNQ_ECALL_T7_TIMER_OUT:                          

                            if(is_ecall_dial)

@@ -823,13 +861,13 @@
                                      g_ecallId = ecallId;

                                      unused_callid=addAddr("ecall");

                                      lynq_call_lists[unused_callid].call_id=g_ecallId;

-                               }        

-                               sendSignalToWaitCallStateChange();

+                               } 

+                               send_signal_to_wait_call_state=true;                             

                            }        

-                           else if(ecallId >0 && (find_call_id_with_call_id(ecallId)==INVALID_ID))

+                           else if(ecallId >0 && (find_call_id_with_call_id(ecallId)==INVALID_ID) &&  (g_lynqEcallVariant != LYNQ_ECALL_CALLBACK))

                            {

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

-                               lynq_call_hungup(&ecallId);

+                               handup_ecall_id=true;

                            }   

                            else 

                            {

@@ -839,25 +877,26 @@
                        case LYNQ_ECALL_PSAP_CALLBACK_START:                            

                            if(lynq_ecall_is_running()==0)

                            {

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

-                               if(find_call_id_with_call_id(ecallId)!=INVALID_ID)

-                               {

+                               if(ecallId>0)

+                               {                                

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

+                                   g_lynqEcallVariant = LYNQ_ECALL_CALLBACK;

                                    g_ecallId = ecallId;

                                    if(isDial)

                                    {

                                        LYINFLOG("stop normal dial");

-                                       sendSignalToWaitCallStateChange();

+                                       send_signal_to_wait_call_state=true;                               

                                    }

                                    else 

                                    {

                                        LYINFLOG("no normal dial");

-                                   }                            

+                                   }  

                                }

                                else 

                                {

-                                    LYERRLOG("can't find ecall id in local list");

-                               }                            

-                           }

+                                   LYERRLOG("ecallId is abnormal in psap callback");

+                               }

+                           }                           

                            else 

                            {

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

@@ -873,7 +912,7 @@
                            {

                                LYERRLOG("ecall is in dialing state, recv no answer, recv abnormal hangup, dont' redial");

                                g_ecallId = INVALID_ID;

-                               sendSignalToWaitCallStateChange();                            

+                               send_signal_to_wait_call_state=true;                                                    

                            }    

                            else {

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

@@ -882,13 +921,17 @@
                        case LYNQ_ECALL_DISCONNECTED:

                        case LYNQ_ECALL_REDIAL_TIMER_OUT:

                        case LYNQ_ECALL_T2_TIMER_OUT :

-                       case LYNQ_ECALL_IMS_DISCONNECTED:

+                       case LYNQ_ECALL_IMS_DISCONNECTED:                           

                            g_ecallId = INVALID_ID;

+                           if(g_lynqEcallVariant == LYNQ_ECALL_CALLBACK)

+                           {

+                               g_lynqEcallVariant = LYNQ_ECALL_VAR_NONE; /*other type, needn't re-initialize*/

+                           }

                            if(is_ecall_dial != LYNQ_ECALL_DAILING_STATE_NONE)

                            {

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

-                               is_ecall_dial = LYNQ_ECALL_DAILING_STATE_NONE;

-                               sendSignalToWaitCallStateChange();

+                               is_ecall_dial = LYNQ_ECALL_DAILING_STATE_NONE;                         

+                               send_signal_to_wait_call_state=true;                               

                            }

                            else 

                            {

@@ -897,8 +940,17 @@
                            break;

                        default:                          

                            LYINFLOG("not special indication");

+                    }                         

+                    pthread_mutex_unlock(&s_ecall_variable_mutex);

+                    if(send_signal_to_wait_call_state)

+                    {

+                        sendSignalToWaitCallStateChange();

                     }                    

                     sendSignalIncomingECallEvent();

+                    if(handup_ecall_id)

+                    {

+                        lynq_call_hungup(&ecallId);

+                    }

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

                     break;

                  }

@@ -1380,6 +1432,21 @@
     return 0;

 }

 

+int lynq_get_current_call_number()

+{

+    int cnt=0;

+    int i;

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

+    {

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

+        {

+            cnt++;           

+        }

+    }

+

+    return cnt;

+}

+

 /*audio begin*/

 static int judge_mic(const int enable){

     switch(enable){

@@ -1645,24 +1712,137 @@
     return error;

 }

 

+int lynq_ecall_can_be_preempted(LYNQ_ECall_Variant old_variant,LYNQ_ECall_Variant new_variant)

+{

+    int ret;

+

+    if(old_variant == LYNQ_ECALL_EMERGENCY)

+    {

+        return false;

+    }

+    else if(new_variant == LYNQ_ECALL_EMERGENCY)

+    {

+        return true;

+    }

+    else if(old_variant==LYNQ_ECALL_DAILING_STATE_NONE)

+    {

+        return true;

+    }        

+    else 

+    {

+        ret = (g_ecall_whether_preempt & 0x01);

+    }

+    LYINFLOG("ecall clear conflict call, lynq_ecall_can_be_preempted is true");

+    return ret;

+}

+

+int lynq_clear_current_call()

+{

+    int cnt;

+    if(lynq_call_hungup_all()!=0)

+    {

+        LYERRLOG("ecall clear conflict call,  hangup all failure");

+        return -1;

+    }       

+    cnt=0;

+    while(lynq_get_current_call_number()!=0 && cnt<80)

+    {

+        lynqRespWatingEvent();  

+        usleep(200 * 1000);//200ms

+        cnt++;                

+    }

+    if(lynq_get_current_call_number()!=0)

+    {

+        LYERRLOG("ecall clear conflict call, current call list can't cleared after 15s");

+        return -2;

+    } 

+

+    LYINFLOG("ecall clear conflict call, after %d 0.2s, call list  is cleared", cnt);         

+    return 0;

+}

+

+int lynq_clear_current_conflict_call(LYNQ_ECall_Variant old_variant,LYNQ_ECall_Variant new_variant)

+{

+    int cnt;

+    int ret;

+

+    if(lynq_ecall_is_running()==false)

+    {

+        if(lynq_get_current_call_number()==0)

+        {

+            LYINFLOG("ecall clear conflict call, no conflict ecall and normal call");

+        }

+        else if(g_ecall_whether_preempt & 0x02)

+        {

+            ret=lynq_clear_current_call();

+            LYERRLOG("ecall clear conflict call, relase current normal call ret is %d",ret);                         

+        }

+        return 0;          

+    }

+

+    LYINFLOG("ecall clear conflict call, two ecall occure at the same time, new is %d, old is %d, g_preempt is %d",new_variant,old_variant,g_ecall_whether_preempt);

+

+    if(lynq_ecall_can_be_preempted(old_variant,new_variant)==false)

+    {

+        LYERRLOG("ecall clear conflict call, new ecall %d can't preempt old ecall %d",new_variant,old_variant);

+        return -1;

+    }    

+

+    ret=lynq_clear_current_call();

+    LYINFLOG("ecall clear conflict call, relase current call(including ecall) ret is %d",ret);    

+

+    if(is_ecall_dial != LYNQ_ECALL_DAILING_STATE_NONE)

+    {

+        sendSignalToWaitCallStateChange();  

+        LYINFLOG("ecall clear conflict call, stop ecall in dailing status");

+    }             

+    

+    cnt=0;

+    while(lynq_ecall_is_running() && cnt<80)

+    {

+        usleep(200 * 1000);//200ms

+        cnt++;

+    }

+  

+    if(lynq_ecall_is_running())

+    {

+        LYERRLOG("ecall clear conflict call, after 16s, lynq ecall is still running");        

+    }

+    else

+    {

+        LYINFLOG("ecall clear conflict call, after %d 0.2s, ecall info is cleared", cnt);           

+    }

+

+    sleep(3);// for ecall disconnect

+    print_ecall_info();        

+    return 0;

+}

+

 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;

     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(lynq_ecall_is_running())

+    unsigned int i;          

+   

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

     {

-        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);

+        LYERRLOG("lynq_fast_ecall msd_length %d or ecall variant %d parameter error",msd_length,lynq_ecall_variant);

         return LYNQ_E_ECALL_MSD_LENGTH_ERROR;

-    }    

+    }     

+

+    if(lynq_clear_current_conflict_call(g_lynqEcallVariant,lynq_ecall_variant)!=0)

+    {

+         LYERRLOG("%s call lynq_clear_current_conflict_call false, old is %d, new is %d",__func__,g_lynqEcallVariant,lynq_ecall_variant);

+         return LYNQ_E_ECALL_BEING_RUNNING;

+    }  

+

+    pthread_mutex_lock(&s_ecall_variable_mutex);

+    is_ecall_dial = LYNQ_ECALL_DAILING_STATE_STARTED;

+    g_lynqEcallVariant = lynq_ecall_variant;

+    g_ecallId = INVALID_ID;

+    pthread_mutex_unlock(&s_ecall_variable_mutex);

 

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

     {

@@ -1676,20 +1856,23 @@
    

     if(error==0)

     {   

-        is_ecall_dial = LYNQ_ECALL_DAILING_STATE_STARTED;

         if(waitCallstateChange(270000)==ETIMEDOUT)//4.5 min, dailing 1 min, alerting 1 min, sending msd 30s, redial 2min

         {

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

-            is_ecall_dial = LYNQ_ECALL_DAILING_STATE_NONE;

-            lynqRespWatingEvent();                

+            pthread_mutex_lock(&s_ecall_variable_mutex);

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

+            is_ecall_dial = LYNQ_ECALL_DAILING_STATE_NONE;            

+            lynqRespWatingEvent();  

+            pthread_mutex_unlock(&s_ecall_variable_mutex);

             return LYNQ_E_TIME_OUT;

         }

+        pthread_mutex_lock(&s_ecall_variable_mutex);

         if(is_ecall_dial == LYNQ_ECALL_DAILING_STATE_STARTED)

         {

             /*just dail, no recv answer*/

             LYERRLOG("lynq_fast_ecall, no answer!");   

             is_ecall_dial = LYNQ_ECALL_DAILING_STATE_NONE;

-            lynqRespWatingEvent();         

+            lynqRespWatingEvent();   

+            pthread_mutex_unlock(&s_ecall_variable_mutex);

             return LYNQ_E_ECALL_DAILING_NO_ANSWER;            

         }

         

@@ -1700,15 +1883,21 @@
         {

             *handle=g_ecallId;         

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

+            pthread_mutex_unlock(&s_ecall_variable_mutex);

             return 0;

         }

-        else 

-        {

-            LYERRLOG("lynq_fast_ecall service return fail");

-            return LYNQ_E_INVALID_ID_ANONALY;

-        }               

+

+        LYERRLOG("lynq_fast_ecall service return fail");

+        pthread_mutex_unlock(&s_ecall_variable_mutex);      

+        return LYNQ_E_INVALID_ID_ANONALY;                       

     }

 

+    pthread_mutex_lock(&s_ecall_variable_mutex);

+    is_ecall_dial = LYNQ_ECALL_DAILING_STATE_NONE;

+    g_lynqEcallVariant = LYNQ_ECALL_VAR_NONE;

+    g_ecallId = INVALID_ID;

+    pthread_mutex_unlock(&s_ecall_variable_mutex);

+

     return error;

 }

 

@@ -1761,7 +1950,7 @@
     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 || msd_length == 0 || msd_data ==NULL)

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

     {

         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;

@@ -1774,16 +1963,29 @@
 

     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);

+    return lynq_set_common_request(RIL_REQUEST_ECALL_SET_MSD,2,"%d %s",*handle,lynq_msd_data);

 }

 

 int lynq_set_ivs(int enable)

 {

+#ifdef ECALL_SUPPORT

     if(enable<0)

     {

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

+       if(enable >-100)

+       {

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

+       }

+       else  if(enable== -1000)

+       {

+           print_ecall_info();

+       } 

+       else

+       {

+           g_ecall_whether_preempt= ((-100-enable) & 0x11);           

+       }

        return 0;

     }

+#endif

 

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

 }

@@ -1870,14 +2072,14 @@
         sprintf(cmd,RTP_FROM_CMD, \

             g_rtp_client_info.port,g_rtp_client_info.clockrate,g_rtp_client_info.channels, \

             g_rtp_client_info.latency);            

-        LYINFLOG("start from rtp play: cmd is %s",cmd);    

+    //  LYINFLOG("start from rtp play: cmd is %s",cmd);    

         system(cmd);

     }

     else if ((*rtp_mode) == RTP_SERVER)

     {

         sprintf(cmd,RTP_TO_CMD,   \

             g_rtp_server_info.ip,g_rtp_server_info.port);

-        LYINFLOG("start to rtp play: cmd is %s",cmd);

+    //  LYINFLOG("start to rtp play: cmd is %s",cmd);

         system(cmd);    

     }

     return NULL;