| //SPDX-License-Identifier: MediaTekProprietary | 
 | /* Copyright Statement: | 
 |  * | 
 |  * This software/firmware and related documentation ("MediaTek Software") are | 
 |  * protected under relevant copyright laws. The information contained herein | 
 |  * is confidential and proprietary to MediaTek Inc. and/or its licensors. | 
 |  * Without the prior written permission of MediaTek inc. and/or its licensors, | 
 |  * any reproduction, modification, use or disclosure of MediaTek Software, | 
 |  * and information contained herein, in whole or in part, shall be strictly prohibited. | 
 |  */ | 
 | /* MediaTek Inc. (C) 2010. All rights reserved. | 
 |  * | 
 |  * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES | 
 |  * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") | 
 |  * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON | 
 |  * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, | 
 |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF | 
 |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. | 
 |  * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE | 
 |  * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR | 
 |  * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH | 
 |  * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES | 
 |  * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES | 
 |  * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK | 
 |  * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR | 
 |  * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND | 
 |  * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, | 
 |  * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, | 
 |  * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO | 
 |  * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. | 
 |  * | 
 |  * The following software/firmware and/or related documentation ("MediaTek Software") | 
 |  * have been modified by MediaTek Inc. All revisions are subject to any receiver's | 
 |  * applicable license agreements with MediaTek Inc. | 
 |  */ | 
 | #include "ecall/eCall.h" | 
 |  | 
 | #include <vendor-ril/telephony/ril.h> | 
 | #include <string> | 
 | #include <vector> | 
 | #include <glib.h> | 
 | #include <cutils/jstring.h> | 
 | #include <time.h> | 
 | #include <signal.h> | 
 | #include <pthread.h> | 
 | #include <string.h> | 
 | #include <memory> | 
 |  | 
 | #include "util/utils.h" | 
 | #include "cc.h" | 
 | #include "common.h" | 
 | #include "sms/sms.h" | 
 | #include "sms/gsm/sms_pdu.h" | 
 | #include "./gost/utils/GostEcallUtils.h" | 
 | #include "./gost/sslp/SslpManager.h" | 
 | #include "./gost/sslp/ecall/EcallUtils.h" | 
 | #include "network.h" | 
 |  | 
 | #undef LOG_TAG | 
 | #define LOG_TAG "DEMO_ECALL" | 
 | #define PROP_ECALL_TEST_CASE "vendor.gost.ecall.ecall_case_test" | 
 | #define PROP_ECALL_DEREGIST_TIME "vendor.gost.ecall.nad_deregistration_time_minute" | 
 | #define PROP_ECALL_REDIAL_TIMER "vendor.ecall.redial.timer" //default 120s | 
 |  | 
 | int fast_argc = 0; | 
 | std::vector<std::string> fast_argv; | 
 | int fast_ecall_socket_id = -1; | 
 | static ECALL_TYPE ecall_type = ECALL_TYPE::EN16454_ECALL; | 
 | static bool inNeedRegister = false; | 
 | static bool gostFastEcallFlg = false; | 
 | static bool is_ecall_audio_path = false; | 
 |  | 
 | int gost_sms_argc = 0; | 
 | std::vector<std::string> gost_sms_argv; | 
 | int gost_sms_socket_id = -1; | 
 |  | 
 | typedef enum { | 
 |     REDIAL_DOING = 1, | 
 |     REDIAL_SUCCESS = 2, | 
 |     REDIAL_EXPIRES = 3, | 
 |     REDIAL_UNKNOWN = 4, | 
 | }ecall_redial_status; | 
 |  | 
 | int act_fecall_socid = -1; | 
 | int act_feCall_Id = -1; | 
 | static ecall_redial_status redial_tag = REDIAL_UNKNOWN; | 
 | static bool normal_ecall_tag = false; | 
 |  | 
 | #ifdef ECALL_SUPPORT | 
 | extern speech_status getSpeechStatus(); | 
 | extern void setSpeechAndStatus(int value); | 
 | int resetIVS(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI); | 
 | int dialFastEcall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI); | 
 | void start_ecll_timer(timer_t timer, int signal_value, int milliseconds); | 
 | //RIL_REQUEST_ECALL_SET_MSD | 
 | int setMSD(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI); | 
 | int T7GostEcallSmsMsd(sigval_t sig); | 
 | int setNadRegState(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI); | 
 | int gostStartDeregisterTimer(); | 
 |  | 
 | static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; | 
 | //#define PROP_ECALL_MSD_DATA "vendor.ecall.msd.data" | 
 | static char* msd_data = NULL; | 
 |  | 
 | //LOCAL_SET_MSD_DATA_FOR_TEST | 
 | int setMsdDateForTest(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |     if (argc < 1 || argv[1] == NULL) { | 
 |         RLOGD("setMsdDateForTest invalid parameters"); | 
 |         free(pRI); | 
 |         return -1; | 
 |     } | 
 |     char *msd_data_src = (char*) argv[1]; | 
 |     int len = strlen(msd_data_src); | 
 |  | 
 |     if (len % 2 == 1) { | 
 |         RLOGD("setMsdDateForTest invalid parameters, length is't right"); | 
 |         free(pRI); | 
 |         return -1; | 
 |     } | 
 |     if(msd_data) { | 
 |         free(msd_data); | 
 |         msd_data = NULL; | 
 |     } | 
 |     msd_data = strdup(msd_data_src); | 
 |     RLOGD("setMsdDateForTest() data: %s", (msd_data == NULL ? "": msd_data)); | 
 |     return 0; | 
 | } | 
 |  | 
 | static timer_t sT2; | 
 | static timer_t sT5; | 
 | static timer_t sT6; | 
 | static timer_t sT7; | 
 | static timer_t sRedialTimer; | 
 | static timer_t sAutoAnsTimer; | 
 | static timer_t gostResendMsdTimer; | 
 | static timer_t gostDeregistrationTimer; | 
 |  | 
 | #define T2_TIMEOUT 60*60*1000 | 
 | #define T5_TIMEOUT 5*1000 | 
 | #define T6_TIMEOUT 5*1000 | 
 | #define T7_TIMEOUT 20*1000 | 
 | //#define REDIAL_TIMEOUT 2*60*1000 | 
 | #define AUTOANS_TIMEOUT 60*60*1000 | 
 |  | 
 | static int sT2_sig_value = 2; | 
 | static int sT5_sig_value = 5; | 
 | static int sT6_sig_value = 6; | 
 | static int sT7_sig_value = 7; | 
 | static int redial_sig_value = 8; | 
 | static int autoAns_sig_value = 9; | 
 | static int gost_resend_msd_value = 11; | 
 | static int gost_deregistration_value = 12; | 
 |  | 
 | bool isEcallAudioPath() { | 
 |     RLOGD("%s , is_ecall_audio_path: %d", __FUNCTION__, is_ecall_audio_path); | 
 |     return is_ecall_audio_path; | 
 | } | 
 |  | 
 | bool isEcallAutoanswerTimerFinish() { | 
 |     struct itimerspec timespec; | 
 |     if(timer_gettime(sAutoAnsTimer, ×pec) == -1) { | 
 |         RLOGD("%s(), get time fail(%s)", __FUNCTION__, strerror(errno)); | 
 |         return true; | 
 |     } | 
 |     RLOGD("%s(), tv_sec=%ld, tv_nsec=%ld", __FUNCTION__,timespec.it_value.tv_sec, timespec.it_value.tv_nsec); | 
 |     if((timespec.it_value.tv_sec == 0)  && (timespec.it_value.tv_nsec == 0) ) { | 
 |         RLOGD("%s(), timer_id(%ld) had stopped", __FUNCTION__, (long)sAutoAnsTimer); | 
 |         return true; | 
 |     } | 
 |     return false; | 
 | } | 
 |  | 
 | void setEcallAudioPathOn(bool on) { | 
 |     RLOGD("%s() , is_ecall_audio_path: %d, on: %d", __FUNCTION__, is_ecall_audio_path, on); | 
 |  | 
 |     if((is_ecall_audio_path != on) && (isEcallAutoanswerTimerFinish())) { | 
 |         is_ecall_audio_path = on; | 
 |     } | 
 |     RLOGD("%s() , is_ecall_audio_path: %d", __FUNCTION__, is_ecall_audio_path); | 
 | } | 
 |  | 
 | void autoAnswerEcall(bool on) { | 
 |     RLOGD("%s() , is_ecall_audio_path: %d, on: %d", __FUNCTION__, is_ecall_audio_path, on); | 
 |     if(is_ecall_audio_path != on) { | 
 |         is_ecall_audio_path = on; | 
 |     } | 
 |     if(on) { | 
 |         char* argv[2] = {"", "1"}; | 
 |         autoAnswerCall(2, argv, RIL_SOCKET_ID(0), NULL); //unused socket id; | 
 |     } else { | 
 |         char* argv[2] = {"", "0"}; | 
 |         autoAnswerCall(2, argv, RIL_SOCKET_ID(0), NULL); //unused socket id; | 
 |     } | 
 | } | 
 |  | 
 | void saveFastEcallData(int argc, char** argv ,RIL_SOCKET_ID id) { | 
 |     fast_ecall_socket_id = id; | 
 |     fast_argc = argc; | 
 |     fast_argv.clear(); | 
 |     for(int i = 0; i < argc; i++) { | 
 |         RLOGD("fast_argv[%d] = %s", i, (argv[i]==NULL)? "NULL":argv[i]); | 
 |         fast_argv.push_back(argv[i]); | 
 |     } | 
 | } | 
 |  | 
 | void resetEcallIVSandAudio(int mode, RIL_SOCKET_ID id) { | 
 |     RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_RESET_IVS, mode, id); | 
 |     resetIVS(0, NULL, id, pRI); | 
 | //    char* argv[2] = { "RIL_REQUEST_SET_MUTE", "0" }; | 
 | //    setMute(2, argv, id, NULL); | 
 | } | 
 |  | 
 | void ecall_timer_handler(sigval_t sig) { | 
 |     RLOGD("ecall_timer_handler, sig_value: %d", sig.sival_int); | 
 |     int s; | 
 |     s = pthread_mutex_lock(&mtx); | 
 |     if(s != 0) { | 
 |         RLOGE("ecall_timer_handler, pthead_mutex_lock fail"); | 
 |     } | 
 |     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) { | 
 |             goto done; | 
 |         } | 
 |         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 | 
 |             || sig.sival_int == sT6_sig_value | 
 |             || sig.sival_int == sT7_sig_value) { | 
 |         normal_ecall_tag = false; | 
 |         resetEcallIVSandAudio(UDP, RIL_SOCKET_ID(fast_ecall_socket_id)); | 
 |         if(0 != T7GostEcallSmsMsd(sig)) | 
 |         { | 
 |             if(sig.sival_int == sT5_sig_value || sig.sival_int == sT7_sig_value) { | 
 |                 fast_argc = 0; | 
 |                 fast_argv.clear(); | 
 |             } | 
 |         } | 
 |     } else if(sig.sival_int == redial_sig_value) { | 
 |         redial_tag = REDIAL_EXPIRES; | 
 |         RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_RESET_IVS, UDP,RIL_SOCKET_ID(fast_ecall_socket_id)); | 
 |         resetIVS(0, NULL, RIL_SOCKET_ID(fast_ecall_socket_id), pRI); | 
 |         fast_argc = 0; | 
 |         fast_argv.clear(); | 
 |         start_ecll_timer(sAutoAnsTimer, autoAns_sig_value, AUTOANS_TIMEOUT); | 
 |         autoAnswerEcall(true); | 
 |     } else if(sig.sival_int == autoAns_sig_value) { | 
 |         autoAnswerEcall(false); | 
 |     } else if(sig.sival_int == gost_resend_msd_value) { | 
 |         //send msd | 
 |         char** argv = new char*[gost_sms_argv.size()]; | 
 |         argv[gost_sms_argv.size()] = nullptr; | 
 |         for(int i=0; i < gost_sms_argv.size(); i++) { | 
 |             char* temp = new char[gost_sms_argv[i].size()]; | 
 |             strcpy(temp, gost_sms_argv[i].c_str()); | 
 |             argv[i] = temp; | 
 |         } | 
 |  | 
 |         RequestInfo *pRI = creatRILInfoAndInit(RIL_REQUEST_SEND_SMS, UDP, (RIL_SOCKET_ID)gost_sms_socket_id); | 
 |         sendSMS(gost_sms_argc, argv, pRI->socket_id, pRI); | 
 |  | 
 |         for(int i=0; i < gost_sms_argv.size(); i++) { | 
 |             delete argv[i]; | 
 |         } | 
 |         delete argv; | 
 |     } else if(sig.sival_int == gost_deregistration_value) { | 
 |         RIL_SOCKET_ID id = (RIL_SOCKET_ID)fast_ecall_socket_id; | 
 |         if(id == -1) { | 
 |             id = (RIL_SOCKET_ID)get_default_sim_all_except_data(); | 
 |         } | 
 |         RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_SET_REGISTRATION_STATE, UDP, id); | 
 |         char* argv[2] = { "RIL_REQUEST_ECALL_SET_REGISTRATION_STATE", "0" }; | 
 |         setNadRegState(2, argv, id, pRI); | 
 |     } | 
 |     else { | 
 |         RLOGE("ecall_timer_handler, sig_value is invalid!"); | 
 |     } | 
 | done: | 
 |     s = pthread_mutex_unlock(&mtx); | 
 |     if(s != 0) { | 
 |         RLOGE("ecall_timer_handler, pthread_mutex_unlock fail"); | 
 |     } | 
 |  | 
 | } | 
 |  | 
 | void init_ecall_timer(timer_t* timer, int signal_value) { | 
 |  | 
 |     struct sigevent sevp; | 
 |     memset(&sevp, 0, sizeof(sevp)); | 
 |     sevp.sigev_value.sival_int = signal_value; | 
 |     sevp.sigev_notify = SIGEV_THREAD; | 
 |     sevp.sigev_notify_function = ecall_timer_handler; | 
 |  | 
 |     if(timer_create(CLOCK_MONOTONIC, &sevp, timer) == -1) { | 
 |         RLOGE("init_ecall_timer()  failed reason=[%s]", strerror(errno)); | 
 |     } | 
 |     RLOGD("init_ecall_timer(), timer_Id = %ld, signal_value=%d", (long)(*timer), signal_value); | 
 | } | 
 |  | 
 | void init_ecall_timer_all() { | 
 |     init_ecall_timer(&sT2,sT2_sig_value); | 
 |     init_ecall_timer(&sT5,sT5_sig_value); | 
 |     init_ecall_timer(&sT6,sT6_sig_value); | 
 |     init_ecall_timer(&sT7,sT7_sig_value); | 
 |     init_ecall_timer(&sRedialTimer,redial_sig_value); | 
 |     init_ecall_timer(&sAutoAnsTimer,autoAns_sig_value); | 
 |     init_ecall_timer(&gostResendMsdTimer,gost_resend_msd_value); | 
 |     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, ×pec) == -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) { | 
 |         str = "ECALL_ALACK_POSITIVE_RECEIVED"; | 
 |     } else if(ind == RIL_UNSOL_ECALL_ALACK_CLEARDOWN_RECEIVED) { | 
 |         str = "ECALL_ALACK_CLEARDOWN_RECEIVED"; | 
 |     } else { | 
 |         str = ""; | 
 |     } | 
 |     struct timespec real; | 
 |     clock_gettime(CLOCK_REALTIME, &real); | 
 |     RLOGD("saveEcallRecord(%s) tv_s:%ld, tv_ns:%ld",str.c_str(), real.tv_sec, real.tv_nsec); | 
 |     char utc_time[100]={0}; | 
 |     strftime(utc_time, sizeof(utc_time), "%D %T", gmtime(&real.tv_sec)); | 
 |     printf("saveEcallRecord, %s,UTC: data_time=%ld\n", str.c_str(),utc_time); | 
 |     RLOGD("saveEcallRecord, %s,UTC: data_time=%ld", str.c_str(),utc_time); | 
 |     char local_time[100]={0}; | 
 |     struct tm t; | 
 |     strftime(local_time, sizeof(local_time), "%D %T", localtime_r(&real.tv_sec, &t)); | 
 |     printf("saveEcallRecord, %s,local: data_time=%ld\n", str.c_str(),local_time); | 
 |     RLOGD("saveEcallRecord, %s,UTC: data_time=%ld", str.c_str(),utc_time); | 
 | } | 
 |  | 
 | void redialFastEcall(RIL_SOCKET_ID socket_id) { | 
 |     if(isGostEcall()) | 
 |     { | 
 |         RLOGD("gost ecall redialFastEcall return for test"); | 
 |         return; | 
 |     } | 
 |     RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_FAST_MAKE_ECALL, UDP, socket_id); | 
 |     char** argv = new char*[fast_argv.size()]; | 
 |     for(int i=0; i < fast_argv.size(); i++) { | 
 |         argv[i] = new char[fast_argv[i].size() +1]; | 
 |         memset(argv[i], 0 , fast_argv[i].size() +1); | 
 |         strncpy(argv[i], fast_argv[i].c_str(),fast_argv[i].size()); | 
 |         argv[i][fast_argv[i].size()] = '\0'; | 
 |     } | 
 |  | 
 |     dialFastEcall(fast_argc, argv, socket_id, pRI); | 
 |  | 
 |     for(int i=0; i < fast_argv.size(); i++) { | 
 |         delete [] argv[i]; | 
 |     } | 
 |     delete []argv; | 
 | } | 
 |  | 
 | void handleEcallIndication(const void* data, int datalen, RIL_SOCKET_ID soc_id) { | 
 |     if (data == NULL || datalen != sizeof(RIL_Ecall_Unsol_Indications)) { | 
 |       if (data == NULL) { | 
 |         RLOGE("handleEcallIndication invalid response: NULL"); | 
 |       } else { | 
 |         RLOGE("handleEcallIndication: invalid response length %d expecting len: %d", | 
 |               sizeof(RIL_Ecall_Unsol_Indications), data); | 
 |       } | 
 |       return ; | 
 |     } | 
 |  | 
 |     RIL_Ecall_Unsol_Indications *p_cur = (RIL_Ecall_Unsol_Indications *)data; | 
 |     RLOGD("handleEcallIndication, call_id: %d, ind: %d",p_cur->call_id, p_cur->ind); | 
 |     switch(p_cur->ind){ | 
 |     case RIL_UNSOL_ECALL_SENDING_START: // = 1, | 
 |     { | 
 |         RLOGD("handleEcallIndication: normal_ecall_tag=%d", normal_ecall_tag); | 
 |         if(!normal_ecall_tag){ | 
 |             //char msd_data[MSD_MAX_LENGTH]= {0}; | 
 |             //utils::mtk_property_get(PROP_ECALL_MSD_DATA, msd_data, NULL); | 
 |             RLOGD("msd_data: %s", msd_data==NULL ? "":msd_data); | 
 |             if(msd_data != NULL) { | 
 | //                char* arg[2] = { "RIL_REQUEST_SET_MUTE", "1" }; | 
 | //                setMute(2, arg, soc_id, NULL); | 
 |                 RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_SET_MSD, RSPD, soc_id); | 
 |                 char* argv[3] = {"RIL_REQUEST_ECALL_SET_MSD", "", "" }; | 
 |                 argv[1] = const_cast<char*>(std::to_string(p_cur->call_id).c_str()); | 
 |                 argv[2] = msd_data; | 
 |                 setMSD(3, argv, soc_id, pRI); | 
 |             } | 
 |         } else { | 
 |             stop_ecall_timer(sT5, sT5_sig_value); | 
 |         } | 
 |         break; | 
 |     } | 
 |     case RIL_UNSOL_ECALL_SENDING_MSD: // = 2, | 
 |     { | 
 |         start_ecll_timer(sT7,sT7_sig_value, T7_TIMEOUT); | 
 |         act_fecall_socid = soc_id; | 
 |         act_feCall_Id = p_cur->call_id; | 
 |         break; | 
 |     } | 
 |     case RIL_UNSOL_ECALL_LLACK_RECEIVED: // = 3, | 
 |     { | 
 |         fast_argc = 0; | 
 |         fast_argv.clear(); | 
 |         stop_ecall_timer(sT7, sT7_sig_value); | 
 |         start_ecll_timer(sT6, sT6_sig_value, T6_TIMEOUT); | 
 |         act_fecall_socid = soc_id; | 
 |         act_feCall_Id = p_cur->call_id; | 
 |         normal_ecall_tag = false; | 
 |         break; | 
 |     } | 
 |     case RIL_UNSOL_ECALL_ALACK_POSITIVE_RECEIVED: // = 4, | 
 |     { | 
 |         stop_ecall_timer(sT6, sT6_sig_value); | 
 |         resetEcallIVSandAudio(RSPD, soc_id); | 
 |         saveEcallRecord(p_cur->ind); | 
 |         break; | 
 |     } | 
 |     case RIL_UNSOL_ECALL_ALACK_CLEARDOWN_RECEIVED: // = 5, | 
 |     { | 
 |         stop_ecall_timer(sT6, sT6_sig_value); | 
 |         stop_ecall_timer(sT2, sT2_sig_value); | 
 |         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", "" }; | 
 |         argv[1] = id; | 
 |         hangupConnection(2, argv, soc_id, pRI); | 
 |         break; | 
 |     } | 
 |     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); | 
 |         autoAnswerEcall(false); | 
 |         start_ecll_timer(sT2, sT2_sig_value,T2_TIMEOUT); | 
 |         start_ecll_timer(sT5,sT5_sig_value, T5_TIMEOUT); | 
 |         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); | 
 |         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) { | 
 |             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; | 
 |             RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_RESET_IVS, UDP, soc_id); | 
 |             resetIVS(0, NULL, soc_id, pRI); | 
 |             redialFastEcall(soc_id); | 
 |         } | 
 |         break; | 
 |     } | 
 |     //case RIL_UNSOL_ECALL_IMS_MSD_ACK: // = 20, | 
 |     //case RIL_UNSOL_ECALL_IMS_UPDATE_MSD: // = 21, | 
 |     //case RIL_UNSOL_ECALL_UNSPECIFIED: // = 0xffff, | 
 |     default: | 
 |         RLOGD("handleEcallIndication don't handlt the value(%d)", 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(); | 
 |  | 
 |   if (getSpeechStatus() == SPEECH_OFF) { | 
 |     if (get_audio_path() == 0) { | 
 |       setSpeechAndStatus(1); | 
 |     } else { | 
 |       setSpeechAndStatus(2); | 
 |     } | 
 |   } | 
 |  | 
 |   //paramter int. 0 disable, 1 enable | 
 |   p.writeInt32(1); | 
 |   p.writeInt32(atoi(argv[1]) ? 1 : 0); | 
 |   p.setDataPosition(pos); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 |  | 
 | //RIL_REQUEST_ECALL_SET_MSD | 
 | int setMSD(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |   size_t pos = p.dataPosition(); | 
 |   int digitCount; | 
 |   uint8_t uct; | 
 |   int digitLimit; | 
 |   char *msd_data_src = (char *) argv[2]; | 
 |   unsigned char msd_data_dst[MSD_MAX_LENGTH] = {0}; | 
 |   int len = strlen(msd_data_src); | 
 |  | 
 |   if (argc < 2 || argv[2] == NULL || len % 2 == 1) { | 
 |     //add log msg | 
 |     free(pRI); | 
 |     return -1; | 
 |   } | 
 |  | 
 |   if (getSpeechStatus() == SPEECH_OFF) { | 
 |     if (get_audio_path() == 0) { | 
 |       setSpeechAndStatus(1); | 
 |     } else { | 
 |       setSpeechAndStatus(2); | 
 |     } | 
 |   } | 
 |   //call_id | 
 |   p.writeInt32(atoi(argv[1])); | 
 |   //msd_data Convert MSD to byte representation | 
 |   RLOGD("msd_data_src: msd_data_src length = %d %s\n", strlen(msd_data_src), | 
 |       msd_data_src); | 
 |   ConvertMsd((const char *) argv[2], msd_data_dst); | 
 |  | 
 |   digitLimit = MIN(len / 2, MSD_MAX_LENGTH); | 
 |   p.writeInt32(digitLimit); | 
 |  | 
 |   for (digitCount = 0; digitCount < digitLimit; digitCount++) { | 
 |     p.write(&(msd_data_dst[digitCount]), sizeof(uint8_t)); | 
 |   } | 
 |  | 
 |   p.setDataPosition(pos); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 | //RIL_REQUEST_ECALL_SET_PSAP | 
 | int setPASP(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |   size_t pos = p.dataPosition(); | 
 |  | 
 |   if (getSpeechStatus() == SPEECH_OFF) { | 
 |     if (get_audio_path() == 0) { | 
 |       setSpeechAndStatus(1); | 
 |     } else { | 
 |       setSpeechAndStatus(2); | 
 |     } | 
 |   } | 
 |  | 
 |   //paramter int. 0 disable, 1 enable | 
 |   p.writeInt32(1); | 
 |   p.writeInt32(atoi(argv[1]) ? 1 : 0); | 
 |   p.setDataPosition(pos); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 |  | 
 | //RIL_REQUEST_ECALL_IVS_PUSH_MSD | 
 | int IVSPushMSD(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |     RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |  | 
 |   if (getSpeechStatus() == SPEECH_OFF) { | 
 |     if (get_audio_path() == 0) { | 
 |       setSpeechAndStatus(1); | 
 |     } else { | 
 |       setSpeechAndStatus(2); | 
 |     } | 
 |   } | 
 |  | 
 |   //paramter none | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 | //RIL_REQUEST_ECALL_PSAP_PULL_MSD | 
 | int PSAPPushMSD(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |     RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |  | 
 |   if (getSpeechStatus() == SPEECH_OFF) { | 
 |     if (get_audio_path() == 0) { | 
 |       setSpeechAndStatus(1); | 
 |     } else { | 
 |       setSpeechAndStatus(2); | 
 |     } | 
 |   } | 
 |  | 
 |   //paramter none | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 | int setCTRLSequence(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |     RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |   size_t pos = p.dataPosition(); | 
 |  | 
 |   if (argc < 1 || argc > 4) { | 
 |     //add log msg | 
 |     free(pRI); | 
 |     return -1; | 
 |   } | 
 |   //CTRL Sequence | 
 |   p.writeInt32(3); | 
 |   writeStringToParcel(p, (const char *) argv[1]); | 
 |   writeStringToParcel(p, (const char *) argv[2]); | 
 |   writeStringToParcel(p, (const char *) argv[3]); | 
 |  | 
 |   p.setDataPosition(pos); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |  | 
 |   return 0; | 
 | } | 
 | //RIL_REQUEST_ECALL_RESET_IVS | 
 | int resetIVS(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |  | 
 |   if (getSpeechStatus() == SPEECH_OFF) { | 
 |     if (get_audio_path() == 0) { | 
 |       setSpeechAndStatus(1); | 
 |     } else { | 
 |       setSpeechAndStatus(2); | 
 |     } | 
 |   } | 
 |  | 
 |   //paramter none | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 | //RIL_REQUEST_ECALL_SET_TEST_NUM | 
 | int setTestNum(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |     RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |   size_t pos = p.dataPosition(); | 
 |  | 
 |   if(argc -1 == 0) { | 
 |     p.writeInt32(0); | 
 |     p.writeInt32(0); | 
 |     writeStringToParcel(p, ""); | 
 |   } else if (argc -1 == 1) { | 
 |     p.writeInt32(1); | 
 |     p.writeInt32(atoi(argv[1]) ? 1 : 0); | 
 |     writeStringToParcel(p, ""); | 
 |   } else if (argc - 1 == 2) { | 
 |     p.writeInt32(2); | 
 |     p.writeInt32(atoi(argv[1]) ? 1 : 0); | 
 |     writeStringToParcel(p, (const char *) argv[2]); | 
 |   } else { | 
 |     RLOGD("parameters is invalid"); | 
 |     free(pRI); | 
 |     return -1; | 
 |   } | 
 |   p.setDataPosition(pos); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 |  | 
 | //RIL_REQUEST_ECALL_SET_RECONF_NUM | 
 | int setReconfNum(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |     RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |   size_t pos = p.dataPosition(); | 
 |   if(argc -1 == 0) { | 
 |     p.writeInt32(0); | 
 |     p.writeInt32(0); | 
 |     writeStringToParcel(p, ""); | 
 |   } else if (argc -1 == 1) { | 
 |     p.writeInt32(1); | 
 |     p.writeInt32(atoi(argv[1]) ? 1 : 0); | 
 |     writeStringToParcel(p, ""); | 
 |   } else if (argc - 1 == 2) { | 
 |     p.writeInt32(2); | 
 |     p.writeInt32(atoi(argv[1]) ? 1 : 0); | 
 |     writeStringToParcel(p, (const char *) argv[2]); | 
 |   } else { | 
 |     RLOGD("parameters is invalid"); | 
 |     free(pRI); | 
 |     return -1; | 
 |   } | 
 |   p.setDataPosition(pos); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 |  | 
 | //RIL_REQUEST_ECALL_MAKE_ECALL | 
 | int makeECall(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |     RequestInfo *pRI) { | 
 |   android::Parcel p; | 
 |   size_t pos = p.dataPosition(); | 
 |   //paramter int, type | 
 |   int type; | 
 |   type = atoi(argv[1]); | 
 |   if (type < 0 || type > 3) { | 
 |     RLOGW("makeECall type is invaild. set default 0!"); | 
 |     type = 0; | 
 |   } | 
 |  | 
 |   p.writeInt32(1); | 
 |   p.writeInt32(type); | 
 |   p.setDataPosition(pos); | 
 |   setEcallAudioPathOn(true); | 
 |   pRI->pCI->dispatchFunction(p, pRI); | 
 |   return 0; | 
 | } | 
 |  | 
 | //RIL_REQUEST_ECALL_FAST_MAKE_ECALL | 
 | /*cmd:1, ecall_cat, | 
 | *2, ecall_variant, | 
 | *3, address | 
 | *4, msd_data | 
 | */ | 
 | int dialFastEcall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) | 
 | { | 
 |     if(isGostEcall()) | 
 |     { | 
 |         if(inNeedRegister) | 
 |         { | 
 |             RLOGD("%s:%d", __FUNCTION__, __LINE__); | 
 |             gostFastEcallFlg = true; | 
 |             gostNetworkSelectionSet(socket_id); | 
 |             while(inNeedRegister) | 
 |             { | 
 |                 sleep(1); | 
 |                 RLOGD("%s:%d", __FUNCTION__, __LINE__); | 
 |             } | 
 |             stop_ecall_timer(gostDeregistrationTimer,gost_deregistration_value); | 
 |         } | 
 |     } | 
 |     saveFastEcallData(argc, argv, socket_id); | 
 |     if (argc < 5 || argv[3] == NULL || argv[4] == NULL) { | 
 |         //add log msg | 
 |         free(pRI); | 
 |         return -1; | 
 |     } | 
 |     android::Parcel p; | 
 |     size_t pos =  p.dataPosition(); | 
 |     int digitCount; | 
 |     uint8_t uct; | 
 |     int digitLimit; | 
 |     char *msd_data_src = (char *)argv[4]; | 
 |     unsigned char msd_data_dst[MSD_MAX_LENGTH]; | 
 |     int len = strlen(msd_data_src); | 
 |  | 
 |     if (len%2 == 1) { | 
 |         //add log msg | 
 |         free(pRI); | 
 |         return -1; | 
 |     } | 
 |     //ecall_cat | 
 |     p.writeInt32(atoi(argv[1])); | 
 |     //ecall_variant | 
 |     p.writeInt32(atoi(argv[2])); | 
 |     //address; | 
 |     if(strcasecmp(argv[3], "null") == 0) | 
 |     { | 
 |         writeStringToParcel(p, ""); | 
 |     } else { | 
 |         writeStringToParcel(p, (const char *)argv[3]); | 
 |     } | 
 |  | 
 |     //msd_data Convert MSD to byte representation | 
 |     RLOGD("msd_data_src: %s , length = %d", msd_data_src, strlen(msd_data_src)); | 
 |     ConvertMsd((const char *)argv[4], msd_data_dst); | 
 |  | 
 |     digitLimit= MIN(len/2, MSD_MAX_LENGTH); | 
 |     p.writeInt32(digitLimit); | 
 |  | 
 |     for (digitCount = 0 ; digitCount < digitLimit; digitCount ++) { | 
 |         p.write(&(msd_data_dst[digitCount]), sizeof(uint8_t)); | 
 |     } | 
 |  | 
 |     p.setDataPosition(pos); | 
 |     normal_ecall_tag = true; | 
 |     setEcallAudioPathOn(true); | 
 |     pRI->pCI->dispatchFunction(p, pRI); | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 |  | 
 | //RIL_REQUEST_ECALL_SET_PRI | 
 | int setEmsdpri(int argc, char **argv, RIL_SOCKET_ID socket_id, | 
 |         RequestInfo *pRI) { | 
 |     if (argc != 5) { | 
 |         RLOGW("parameter is invalid"); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |     int data1 = atoi(argv[1]); | 
 |     int data2 = atoi(argv[2]); | 
 |     int data3 = atoi(argv[3]); | 
 |     int data4 = atoi(argv[4]); | 
 |  | 
 |     if (data1 + data2 + data3 + data4 != 10) { | 
 |         RLOGW("parameter is invalid , %d,%d,%d,%d", data1, data2, data3, data4); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |     android::Parcel p; | 
 |     size_t pos = p.dataPosition(); | 
 |     p.writeInt32(4); | 
 |     p.writeInt32(data1); | 
 |     p.writeInt32(data2); | 
 |     p.writeInt32(data3); | 
 |     p.writeInt32(data4); | 
 |     p.setDataPosition(pos); | 
 |     pRI->pCI->dispatchFunction(p, pRI); | 
 |     return 0; | 
 | } | 
 |  | 
 | //RIL_REQUEST_ECALL_SET_NAD_DEREGISTRATION_TIME | 
 | /* | 
 |  * "data" is const ints* | 
 |  *  ((const int *)data)[0] is purpose, 0-for eCall(currently only support 0, can be extended in future) | 
 |  *  ((const int *)data)[1] is mode, 1-set timer; 0-reset timer | 
 |  *  ((const int *)data)[2] is timer1, timer value (minute) set for emergency call | 
 |  *  ((const int *)data)[3] is timer2, timer value (minute) set for rest/reconfiguration call, | 
 |  * | 
 |  *   in current, timer1 and timer2 prefer to be the same value. | 
 |  */ | 
 | int setNadDeregTime(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |     if (argc != 5) { | 
 |         RLOGW("parameter is invalid"); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     int purpose = atoi(argv[1]); | 
 |     int mode = (atoi(argv[2]) != 0) ? 1 : 0; | 
 |     int timer1 = atoi(argv[3]); | 
 |     int timer2 = atoi(argv[4]); | 
 |     if (timer1 != timer2) { | 
 |         RLOGW("setNadDeregTime, parameter is invalid:data3 != data4"); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     android::Parcel p; | 
 |     size_t pos = p.dataPosition(); | 
 |     p.writeInt32(4); | 
 |     p.writeInt32(purpose); | 
 |     p.writeInt32(mode); | 
 |     p.writeInt32(timer1); | 
 |     p.writeInt32(timer2); | 
 |     p.setDataPosition(pos); | 
 |     pRI->pCI->dispatchFunction(p, pRI); | 
 |     return 0; | 
 | } | 
 |  | 
 | /** | 
 | * RIL_REQUEST_ECALL_SET_REGISTRATION_STATE | 
 | * | 
 | * REQUEST to set nad registration state of ecall only sim | 
 | * | 
 | * "data" is const ints* | 
 | *  ((const int *)data)[0] is state, 0-deregister from NW, enter the eCall inactivity procedure; | 
 | *                                             1-register to NW, leave the eCall inactivity procedure(not support, reserved for future use) | 
 | * "response" is NULL | 
 | * | 
 | * Valid errors: | 
 | *  SUCCESS | 
 | *  GENERIC_FAILURE | 
 | */ | 
 | int setNadRegState(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |     if(argc != 2) { | 
 |       RLOGW("parameter is invalid"); | 
 |       free(pRI); | 
 |       return 0; | 
 |     } | 
 |  | 
 |     int state = (atoi(argv[1])!= 0) ? 1 : 0; | 
 |  | 
 |     android::Parcel p; | 
 |     size_t pos = p.dataPosition(); | 
 |     p.writeInt32(1); | 
 |     p.writeInt32(state); | 
 |     p.setDataPosition(pos); | 
 |     pRI->pCI->dispatchFunction(p, pRI); | 
 |     return 0; | 
 | } | 
 |  | 
 | int setEcallType(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |     if(argc < 2) { | 
 |         RLOGW("[error],setEcallType parameter error!"); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |     RLOGD("setEcallType is %s",argv[1]); | 
 |     int value = atoi(argv[1]); | 
 |     switch(value) { | 
 |     case 1: | 
 |     { | 
 |         ecall_type = ECALL_TYPE::EN16454_ECALL; | 
 |         break; | 
 |     } | 
 |     case 2: | 
 |     { | 
 |         ecall_type = ECALL_TYPE::GOST_ECALL; | 
 |         break; | 
 |     } | 
 |     case 3: | 
 |     { | 
 |         ecall_type = ECALL_TYPE::NG_ECALL; | 
 |         break; | 
 |     } | 
 |     default: | 
 |         RLOGD("setEcallType error %s",argv[1]); | 
 |     } | 
 |  | 
 |     if(pRI) { | 
 |         free(pRI); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int getEcallType(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { | 
 |     RLOGD("%s, %d", __FUNCTION__, ecall_type); | 
 |  | 
 |     if(ecall_type == ECALL_TYPE::EN16454_ECALL) { | 
 |         printf("the current test type is: EN16454 ECALL\n"); | 
 |     } else if(ecall_type == ECALL_TYPE::GOST_ECALL) { | 
 |         printf("the current test type is: GOST ECALL\n"); | 
 |     } else if (ecall_type == ECALL_TYPE::NG_ECALL) { | 
 |         printf("the current test type is: NG ECALL (IMS)\n"); | 
 |     } else { | 
 |         printf("the current test type is: unknown\n"); | 
 |     } | 
 |  | 
 |     if(pRI) { | 
 |         free(pRI); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | bool isEn16454Ecall() { | 
 |     bool value = (ecall_type == ECALL_TYPE::EN16454_ECALL); | 
 |     RLOGD("%s=%d, type = %d", __FUNCTION__, value, ecall_type); | 
 |     return value; | 
 | } | 
 |  | 
 | bool isGostEcall() { | 
 |     bool value = (ecall_type == ECALL_TYPE::GOST_ECALL); | 
 |     RLOGD("%s=%d, type = %d", __FUNCTION__, value, ecall_type); | 
 |     return value; | 
 | } | 
 |  | 
 | bool isNgEcall() { | 
 |     bool value = (ecall_type == ECALL_TYPE::NG_ECALL); | 
 |     RLOGD("%s=%d, type = %d", __FUNCTION__, value, ecall_type); | 
 |     return value; | 
 | } | 
 |  | 
 | void gostSaveSmsData(int argc, char** argv ,RIL_SOCKET_ID id) { | 
 |     gost_sms_socket_id = id; | 
 |     gost_sms_argc = argc; | 
 |     gost_sms_argv.clear(); | 
 |     for(int i = 0; i < argc; i++) { | 
 |         gost_sms_argv.push_back(argv[i]); | 
 |     } | 
 | } | 
 |  | 
 | void gostDelSaveSmsData() { | 
 |     if(fast_argc != 0) | 
 |     { | 
 |         fast_argc = 0; | 
 |         fast_argv.clear(); | 
 |     } | 
 | } | 
 |  | 
 | #define INT_MEM_TRANSMIT_ATTEMPTS 10 | 
 | #define INT_MEM_TRANSMIT_INTERVAL (60*60*1000) | 
 | static int gost_attempts = INT_MEM_TRANSMIT_ATTEMPTS; | 
 | static int gost_interval = INT_MEM_TRANSMIT_INTERVAL; | 
 |  | 
 | void gostSetInNeedRegister(bool flags) | 
 | { | 
 |     RLOGD("%s:flags(%d) change!", __FUNCTION__, flags); | 
 |     inNeedRegister = flags; | 
 | } | 
 | void gostFastEcallFlgSet(bool flags) | 
 | { | 
 |     RLOGD("%s:flags(%d) change!", __FUNCTION__, flags); | 
 |     gostFastEcallFlg = flags; | 
 | } | 
 |  | 
 | int gostTransmitAttemptsSet(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) | 
 | { | 
 |     if(argc < 2) { | 
 |         RLOGW("[error],gostTransmitAttemptsSet parameter error!"); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     int attempts = atoi(argv[1]);; | 
 |     gost_attempts = attempts; | 
 |     RLOGD("%s:gost_attempts(%d)", __FUNCTION__, gost_attempts); | 
 |  | 
 |     if(pRI) { | 
 |         free(pRI); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int gostStartDeregisterTimer() | 
 | { | 
 |     char configNum[16]= {0}; | 
 |     int timerValue; | 
 |     utils::mtk_property_get(PROP_ECALL_DEREGIST_TIME, configNum, "60"); | 
 |     timerValue = atoi(configNum) * 60 * 1000; | 
 |     RLOGD("%s:configNum(%d)", __FUNCTION__, timerValue); | 
 |     return timerValue; | 
 | } | 
 |  | 
 | int gostTransmitIntervalSet(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) | 
 | { | 
 |     if(argc < 2) { | 
 |         RLOGW("[error],gostTransmitIntervalSet parameter error!"); | 
 |         free(pRI); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     int interval = atoi(argv[1]);; | 
 |     gost_interval = interval; | 
 |     RLOGD("%s:gost_interval(%d)", __FUNCTION__, gost_interval); | 
 |  | 
 |     if(pRI) { | 
 |         free(pRI); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int gostTransmitDefaultSet(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) | 
 | { | 
 |     gost_attempts = INT_MEM_TRANSMIT_ATTEMPTS; | 
 |     gost_interval = INT_MEM_TRANSMIT_INTERVAL; | 
 |     RLOGD("%s:gost_attempts(%d), gost_interval(%d)", __FUNCTION__, gost_attempts, gost_interval); | 
 |  | 
 |     if(pRI) { | 
 |         free(pRI); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int gostNetworkSelectionSet(int soc_id) | 
 | { | 
 |     RLOGD("%s:soc_id(%d)", __FUNCTION__, soc_id); | 
 |     if(isGostEcall() && gostFastEcallFlg) | 
 |     { | 
 |         RequestInfo *pRI = creatRILInfoAndInit(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, UDP, (RIL_SOCKET_ID)(soc_id)); | 
 |         if(pRI == NULL) | 
 |         { | 
 |             RLOGE("error PRI is NULL"); | 
 |             return 0; | 
 |         } | 
 |         char* argv[1] = {"RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC"}; | 
 |         setNetworkSelectionModeAutomatic(1, argv, (RIL_SOCKET_ID)(soc_id), pRI); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int gostEcallResendMsd(bool flg) | 
 | { | 
 |     static int resendnum = 0; | 
 |  | 
 |     //no resend | 
 |     if(!flg) | 
 |     { | 
 |         if(resendnum != 0) | 
 |         { | 
 |             stop_ecall_timer(gostResendMsdTimer,gost_resend_msd_value); | 
 |         } | 
 |         resendnum = 0; | 
 |         return 0; | 
 |     } | 
 |  | 
 |     //abandon | 
 |     if(resendnum > gost_attempts) | 
 |     { | 
 |         resendnum = 0; | 
 |         stop_ecall_timer(gostResendMsdTimer,gost_resend_msd_value); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     //resend | 
 |     resendnum++; | 
 |     start_ecll_timer(gostResendMsdTimer, gost_resend_msd_value, gost_interval); | 
 |     return 1; | 
 | } | 
 |  | 
 | int T7GostEcallSmsMsd(sigval_t sig) { | 
 |     char** argv = new char*[fast_argv.size()]; | 
 |     char msd[512]; | 
 |     char saveEcallData[512]; | 
 |     char sdata[512]; | 
 |  | 
 |     if((sig.sival_int != sT7_sig_value) && (sig.sival_int != sT5_sig_value)) | 
 |     { | 
 |         if(argv) { | 
 |             delete []argv; | 
 |         } | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if(isGostEcall()) | 
 |     { | 
 |         //for test | 
 |         char testCase[140]= {0}; | 
 |         utils::mtk_property_get(PROP_ECALL_TEST_CASE, testCase, "test"); | 
 |         if(strcmp(testCase, "33470") == 0) | 
 |         { | 
 |             if(argv) { | 
 |                 delete []argv; | 
 |             } | 
 |             RLOGD("%s:testCase(%s) not need send sms", __FUNCTION__, testCase); | 
 |             return -1; | 
 |         } | 
 |  | 
 |  | 
 |         if(fast_argv.size() < 5) { | 
 |             if(argv) { | 
 |                 delete []argv; | 
 |             } | 
 |             RLOGD("%s:testCase(%s) fast_argv size(%d) is not right", __FUNCTION__, testCase,fast_argv.size()); | 
 |             return -1; | 
 |         } | 
 |         for(int i=0; i < fast_argv.size(); i++) { | 
 |             argv[i] = new char[fast_argv[i].size() +1]; | 
 |             memset(argv[i], 0 , fast_argv[i].size() +1); | 
 |             strncpy(argv[i], fast_argv[i].c_str(),fast_argv[i].size()); | 
 |             argv[i][fast_argv[i].size()] = '\0'; | 
 |         } | 
 |  | 
 |         RLOGD("num:%s, data:%s\n", argv[3], argv[4]); | 
 |         char *msd_data_src = (char *)argv[4]; | 
 |         int len = strlen(msd_data_src); | 
 |         std::shared_ptr<SslpManager> manager = std::make_shared<SslpManager>(); | 
 |         std::string data = manager->encodeAllRecords(service_support_layer_protocol::EGTS_ECALL_SERVICE, | 
 |                 service_support_layer_protocol::EGTS_ECALL_SERVICE, | 
 |                 EcallUtils::EGTS_SR_RAW_MSD_DATA, | 
 |                 msd_data_src); | 
 |         //encode | 
 |         RLOGD("T7:data.c_str():%s\n", data.c_str()); | 
 |         int pt = GOST_EGTS_PT_APPDATA; | 
 |         gostTransferLayerEncode(msd, 0, const_cast<char*> (data.c_str()), pt, sizeof(msd)); | 
 |         RLOGD("T7:msd:%s\n", msd); | 
 |         gostSendSmsForMsd(fast_ecall_socket_id, argv[3], msd); | 
 |         for(int i=0; i < fast_argv.size(); i++) { | 
 |             delete [] argv[i]; | 
 |         } | 
 |         delete []argv; | 
 |  | 
 |         return 0; | 
 |     } | 
 |  | 
 |     if(argv) { | 
 |         delete []argv; | 
 |     } | 
 |     return -1; | 
 | } | 
 |  | 
 | #define GOST_OK 0 | 
 | #define GOST_ERROR -1 | 
 | int gostInitEcallViaSms(int soc_id, char *num, int ecalltype, char *msd) | 
 | { | 
 |     //init ecall | 
 |     RequestInfo *pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_FAST_MAKE_ECALL, UDP, (RIL_SOCKET_ID)(soc_id)); | 
 |     if(pRI == NULL) | 
 |     { | 
 |         RLOGE("error PRI is NULL"); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     int argc = 5; | 
 |     char *argv[5]; | 
 |     argv[0] = "RIL_REQUEST_ECALL_FAST_MAKE_ECALL"; | 
 |     if(ecalltype) | 
 |     { | 
 |         argv[1] = "2";//1:Manual 2:auto | 
 |     } | 
 |     else | 
 |     { | 
 |         argv[1] = "1";//1:Manual 2:auto | 
 |     } | 
 |     argv[2] = "2";    //1:test ecall 2:Emergency eCall 3:Reconfiguration eCall | 
 | //    argv[3] = "1";    //1:Pull mode 2:push mode | 
 |     argv[3] = num; | 
 |     argv[4] = msd; | 
 |     dialFastEcall(argc, argv, (RIL_SOCKET_ID)(soc_id), pRI); | 
 |     return 0; | 
 | } | 
 |  | 
 | int gostParseSmsHandle(int soc_id, char *num, char *msg) | 
 | { | 
 |     char msd[512] = {0}; | 
 |     char sdata[512] = {0}; | 
 |     char server_data[512] = {0}; | 
 |     int server_len = 0; | 
 |     int parseStatus; | 
 |     gost_transfer_head_t stransferHead; | 
 |  | 
 |     memset(&stransferHead, 0, sizeof(stransferHead)); | 
 |     parseStatus = gostTransferLayerDecode(msg, server_data, &server_len, &stransferHead); | 
 |     const char* SFRD = server_data; | 
 |     uint16_t FDL = server_len; | 
 |     std::shared_ptr<SslpManager> sMg = std::make_shared<SslpManager>(); | 
 |     parseStatus += sMg->decodeAllRecords(SFRD, FDL); | 
 |     std::uint16_t cmd = UINT16_MAX; | 
 |     if(sMg->isIncludedCmdCode(EcallUtils::EGTS_ECALL_REQ)) { | 
 |         cmd = EcallUtils::EGTS_ECALL_REQ; | 
 |     } else if(sMg->isIncludedCmdCode(EcallUtils::EGTS_ECALL_MSD_REQ)) { | 
 |         cmd = EcallUtils::EGTS_ECALL_MSD_REQ; | 
 |     } else if(sMg->isIncludedCmdCode(EcallUtils::EGTS_ECALL_DEREGISTRATION)) { | 
 |         cmd = EcallUtils::EGTS_ECALL_DEREGISTRATION; | 
 |     } | 
 |     if(cmd == UINT16_MAX) { | 
 |         MTK_RLOGW("don't support this ack,just return"); | 
 |         return -1; | 
 |     } | 
 |     MTK_RLOGD("the cmd = 0X%04X, parseStatus = %d", cmd, parseStatus); | 
 |     std::string sslp_ack = sMg->encodeAck(service_support_layer_protocol::EGTS_COMMANDS_SERVICE, | 
 |             service_support_layer_protocol::EGTS_COMMANDS_SERVICE, | 
 |             CmdUtils::EGTS_SR_COMMAND_DATA, | 
 |             cmd, | 
 |             (parseStatus == GOST_OK)); | 
 |     strncpy(sdata, sslp_ack.c_str(), 512 - 1); | 
 |     int pt = GOST_EGTS_PT_RESPONSE; | 
 |     gostResponseTypeSfrdEncode(sdata, stransferHead, parseStatus); | 
 |     gostTransferLayerEncode(msd, 0, sdata, pt, sizeof(msd)); | 
 |     //send SMS ACK | 
 |     gostSendSmsForMsd(soc_id, num, msd); | 
 |  | 
 |     if (parseStatus == GOST_OK) { | 
 |         if(cmd == EcallUtils::EGTS_ECALL_REQ) { | 
 |             int ecalltype = sMg->getEcallReqPara(); // 0 manual , 1: auto | 
 |             //make fast ECALL; | 
 |             if(msd_data == NULL) { | 
 |                 RLOGW("msd_data is empty, please input"); | 
 |                 return -1; | 
 |             } | 
 |  | 
 |             char ecallNum[64] = {0}; | 
 |             if(fast_argv.size() > 4) | 
 |             { | 
 |                 strcpy(ecallNum, fast_argv[3].c_str()); | 
 |             } | 
 |             gostInitEcallViaSms(soc_id, ecallNum, ecalltype, msd_data); | 
 |         } else if(cmd == EcallUtils::EGTS_ECALL_MSD_REQ) { | 
 |             //check whether need send SMS by decoding transport value in command. | 
 |             if(sMg->isNeedNewSms()) { | 
 |                   //TBD: send new SMS; | 
 |                 if(msd_data == NULL) { | 
 |                     RLOGW("msd_data is empty, please input"); | 
 |                     return -1; | 
 |                 } | 
 |                 std::string msdData(msd_data); | 
 |                 std::shared_ptr<SslpManager> sMg = std::make_shared<SslpManager>(); | 
 |                 std::string records = sMg->encodeAllRecords(service_support_layer_protocol::EGTS_ECALL_SERVICE, | 
 |                         service_support_layer_protocol::EGTS_ECALL_SERVICE, EcallUtils::EGTS_SR_RAW_MSD_DATA, msdData); | 
 |                 //transport encode and sms send | 
 |                 int pt = GOST_EGTS_PT_APPDATA; | 
 |                 memset(msd, 0, sizeof(msd)); | 
 |                 gostTransferLayerEncode(msd, 0, const_cast<char*> (records.c_str()), pt, sizeof(msd)); | 
 |                 gostSendSmsForMsd(soc_id, num, msd); | 
 |             } | 
 |         } else if(cmd == EcallUtils::EGTS_ECALL_DEREGISTRATION) { | 
 |             MTK_RLOGD("send RIL_REQUEST_ECALL_SET_REGISTRATION_STATE 0"); | 
 |             RIL_SOCKET_ID id = (RIL_SOCKET_ID)fast_ecall_socket_id; | 
 |             if(id == -1) { | 
 |                 id = (RIL_SOCKET_ID)get_default_sim_all_except_data(); | 
 |             } | 
 |             RequestInfo* pRI = creatRILInfoAndInit(RIL_REQUEST_ECALL_SET_REGISTRATION_STATE, UDP, id); | 
 |             char* argv[2] = { "RIL_REQUEST_ECALL_SET_REGISTRATION_STATE", "0" }; | 
 |             setNadRegState(2, argv, id, pRI); | 
 |         } | 
 |     } | 
 |     return 0; | 
 | } | 
 | #endif /*ECALL_SUPPORT*/ |