[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-tele-ril/lynq-riltel/ecall/eCall.cpp b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/ecall/eCall.cpp
new file mode 100644
index 0000000..48db868
--- /dev/null
+++ b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/ecall/eCall.cpp
@@ -0,0 +1,1306 @@
+//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, &timespec) == -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, &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) {
+        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];
+  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);
+}
+
+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))
+    {
+        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)
+        {
+            RLOGD("%s:testCase(%s) not need send sms", __FUNCTION__, testCase);
+            return -1;
+        }
+
+        if(fast_argv.size() < 5) {
+            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;
+    }
+
+    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;
+    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);
+    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*/