|  /* | 
 |  * Copyright (C) 2006 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 | #include <string.h> | 
 | #include <stddef.h> | 
 | #include <stdlib.h> | 
 | #include <stdio.h> | 
 | #include <stdbool.h> | 
 | #include<fcntl.h> | 
 | #include<sys/stat.h> | 
 | #include<sys/types.h> | 
 | #include<unistd.h> | 
 | #include <assert.h> | 
 | #include <log/log.h> | 
 | #include <vendor-ril/telephony/ril.h> | 
 | #include <string> | 
 | #include <mutex> | 
 | #include <vector> | 
 | #include <cutils/properties.h> | 
 |  | 
 | #include "Radio_capability_switch_util.h" | 
 | #include "common.h" | 
 | #include "Phone_utils.h" | 
 | #include "utils.h" | 
 | #include "data.h" | 
 | #include "cc.h" | 
 |  | 
 | #undef LOG_TAG | 
 | #define LOG_TAG "MULTI_USER_COMMON" | 
 |  | 
 | typedef enum { | 
 |     STATE_IN_SERVICE        =0, | 
 |     STATE_OUT_OF_SERVICE    =1, | 
 |     STATE_EMERGENCY_ONLY    =2, | 
 |     STATE_POWER_OFF         =3 | 
 | } Service_State; | 
 |  | 
 | RfDesenseTxTest* m_RfDesense; | 
 | static RIL_CardStatus_v6* cur_CardS_Status[2] = {NULL, NULL}; | 
 | static RIL_RadioCapability radio_capability[2]; | 
 |  | 
 | static int cur_voice_radio_tech[2] = {RADIO_TECH_UNKNOWN, RADIO_TECH_UNKNOWN}; | 
 |  | 
 | static int reg_voice_service_state[2] = {0, 0}; | 
 | static int reg_data_service_state[2] = {0, 0}; | 
 | static int reg_data_radio_tech[2] = {RADIO_TECH_UNKNOWN, RADIO_TECH_UNKNOWN}; | 
 | static int reg_voice_radio_tech[2] = {RADIO_TECH_UNKNOWN, RADIO_TECH_UNKNOWN}; | 
 | static int preferred_network_type[2]  = {Phone_utils::PREFERRED_NETWORK_MODE, Phone_utils::PREFERRED_NETWORK_MODE}; | 
 | static int radio_status[2] = {RADIO_STATE_UNAVAILABLE, RADIO_STATE_UNAVAILABLE}; | 
 | static std::vector<int> call_state[2]; | 
 |  | 
 | static int default_sim_all = RIL_SOCKET_1; | 
 | static int default_sim_all_except_data =  RIL_SOCKET_1; | 
 | static int default_sim_voice = RIL_SOCKET_1; | 
 | static int default_sim_data = RIL_SOCKET_1; | 
 | static int default_sim_sms = RIL_SOCKET_1; | 
 | static bool isNeedReconnect = false; | 
 |  | 
 | static std::int32_t token = 0; | 
 | static std::mutex g_mutex; | 
 |  | 
 | static int regCodeToRadioTechnology(int request, int code, int slot); | 
 |  | 
 | void update_call_state(void *response, size_t responselen, int slot) { | 
 |     int num = responselen / sizeof(RIL_Call *); | 
 |     if(num == 0) { | 
 |         call_state[slot].clear(); | 
 |         RLOGD("[SIM%d]clear call state", slot); | 
 |     } else { | 
 |         call_state[slot].clear(); | 
 |         for (int i = 0 ; i < num ; i++) { | 
 |             RIL_Call *p_cur = ((RIL_Call **) response)[i]; | 
 |             /* each call info */ | 
 |             call_state[slot].push_back(p_cur->state); | 
 |             RLOGD("[SIM%d][id:%d]update_call_state: %d", slot,p_cur->index, p_cur->state); | 
 |             if(p_cur->isMT) { | 
 |                 resetMute(); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | int is_call_state_idle(int slot) { | 
 |     bool is_idle = true; | 
 |     if(!call_state[slot].empty()) { | 
 |         is_idle = false; | 
 |     } | 
 |     RLOGD("[SIM%d]is_call_state_idle: %d", slot, is_idle); | 
 |     return is_idle; | 
 | } | 
 |  | 
 | void update_preferred_network_type(int type, int slot) { | 
 |     RLOGD("[SIM%d]update_preferred_network_type: %d", slot, type); | 
 |     preferred_network_type[slot] = type; | 
 | } | 
 |  | 
 | int get_preferred_network_type(int slot) { | 
 |     return preferred_network_type[slot]; | 
 | } | 
 |  | 
 | static int needBlockReq(int request) | 
 | { | 
 | #ifdef ENABLE_BLOCK_FEATURE | 
 |     return 1; | 
 | #endif | 
 |  | 
 |     switch (request){ | 
 |         case RIL_REQUEST_RADIO_POWER: return 1; | 
 |         case RIL_REQUEST_SET_IMS_ENABLE: return 1; | 
 |         //case RIL_REQUEST_DATA_REGISTRATION_STATE: return 1; | 
 |         default: return 0; | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | static int setupToken(int token, int mode, int block) | 
 | { | 
 |     switch (mode){ | 
 |     case INIT: | 
 |         token |= INIT_TOKEN_MARK; | 
 |         break; | 
 |     case UDP: | 
 |         token |= RIL_TOKEN_MARK; | 
 |         break; | 
 |     case ATCI: | 
 |         token |= ATCI_TOKEN_MARK; | 
 |         break; | 
 |     case RSPD: | 
 |         token |= RSP_DISP_TOKEN_MARK; | 
 |         break; | 
 |     case OTHER: | 
 |         token |= OTHER_TOKEN_MARK; | 
 |         break; | 
 |     default: | 
 |         break; | 
 |     } | 
 |  | 
 |     if(block) | 
 |         token |= BLOCK_MARK; | 
 |  | 
 |     return token; | 
 | } | 
 |  | 
 | bool isDataConnectEnable(int slot) { | 
 |     char value[PROPERTY_VALUE_MAX] = {0}; | 
 |     utils::getMSimProperty(slot,PROP_DEFAULT_DATA_SIM_STATUS, value); | 
 |     if(atoi(value) == 1)  { | 
 |         return true; | 
 |     } | 
 |     return false; | 
 | } | 
 |  | 
 | void updataDataConnectState(int slot, bool state) { | 
 |     utils::setMSimProperty(slot,PROP_DEFAULT_DATA_SIM_STATUS, const_cast<char*>(state ? "1":"0")); | 
 | } | 
 |  | 
 | std::int32_t GenerateToken(int mode, int request) { | 
 |     g_mutex.lock(); | 
 |     if (token +1 == TOKEN_MODE) { | 
 |         token = 1; | 
 |     } else { | 
 |         token++; | 
 |     } | 
 |     std::int32_t t= 0; | 
 |     t = setupToken(token,mode,needBlockReq(request)); | 
 |     g_mutex.unlock(); | 
 |     return t; | 
 | } | 
 |  | 
 | RequestInfo* creatRILInfoAndInit(int request, int mode, RIL_SOCKET_ID soc_id) | 
 | { | 
 |     RequestInfo *pRI  = (RequestInfo *)calloc(1, sizeof(RequestInfo)); | 
 |     if(pRI ==NULL){ | 
 |         RLOGE("%s,memory alloc error!",__func__); | 
 |         return NULL; | 
 |     } | 
 |     android::initRequestInfo(pRI,request,mode, soc_id); | 
 |     return pRI; | 
 | } | 
 |  | 
 | void set_default_sim_all_except_data(int slot_id) { | 
 |     RLOGD("set_default_sim_all excpet data: %d", slot_id); | 
 |     default_sim_all_except_data =  slot_id; | 
 |     set_default_sim_voice(slot_id); | 
 |     set_default_sim_sms(slot_id); | 
 | } | 
 |  | 
 | int get_default_sim_all_except_data() { | 
 |     return default_sim_all_except_data; | 
 | } | 
 |  | 
 | void set_default_sim_all(int slot_id){ | 
 |     RLOGD("set_default_sim_all: %d", slot_id); | 
 |     default_sim_all =  slot_id; | 
 |     set_default_sim_all_except_data(slot_id); | 
 |     set_default_sim_data(slot_id); | 
 | } | 
 |  | 
 | int get_default_sim_all(){ | 
 |     return default_sim_all; | 
 | } | 
 |  | 
 | void set_default_sim_voice(int slot_id){ | 
 |     RLOGD("set_default_sim_voice: %d", slot_id); | 
 |     default_sim_voice = slot_id; | 
 | } | 
 |  | 
 | int get_default_sim_voice(){ | 
 |     return default_sim_voice; | 
 | } | 
 |  | 
 | void set_default_sim_data(int slot) { | 
 |     if(get_default_sim_data() != slot) { | 
 |         if(isDataConnectEnable(get_default_sim_data())) { | 
 |             isNeedReconnect = true; | 
 |             deactivateDataCall(0,NULL,(RIL_SOCKET_ID)0,NULL); | 
 |         } | 
 |         default_sim_data = slot; | 
 |         utils::mtk_property_set(PROP_DEFAULT_DATA_SIM, std::to_string(default_sim_data + 1).c_str()); | 
 |         while(!isRadioAvailable(RIL_SOCKET_ID(slot))) { | 
 |             sleep(1); | 
 |             RLOGD("[SIM%d]set_default_sim_data(RIL_REQUEST_SET_RADIO_CAPABILITY): wait radio available", slot); | 
 |         } | 
 |         syncDataSettings(RIL_SOCKET_ID(slot)); | 
 |         if(utils::is_support_dsds()) { | 
 |             Radio_capability_switch_util::sendRadioCapabilityRequest(slot); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | bool isNeedConnect() { | 
 |     return isNeedReconnect; | 
 | } | 
 |  | 
 | void resetConnect() { | 
 |     isNeedReconnect = false; | 
 | } | 
 | int get_default_sim_data_for_switch() { | 
 |     return default_sim_data; | 
 | } | 
 |  | 
 | int get_default_sim_data(){ | 
 |     default_sim_data = utils::mtk_property_get_int32(PROP_DEFAULT_DATA_SIM, 1) -1; | 
 |     return default_sim_data; | 
 | } | 
 |  | 
 | void set_default_sim_sms(int slot_id){ | 
 |     RLOGD("set_default_sim_sms: %d", slot_id); | 
 |     default_sim_sms = slot_id; | 
 | } | 
 |  | 
 | int get_default_sim_sms() { | 
 |     return default_sim_sms; | 
 | } | 
 |  | 
 | static int regCodeToServiceState(int request,int code, int slot); | 
 |  | 
 | const char * radioStateToString(RIL_RadioState s) { | 
 |     switch (s) { | 
 |     case RADIO_STATE_OFF: | 
 |         return "RADIO_OFF"; | 
 |     case RADIO_STATE_UNAVAILABLE: | 
 |         return "RADIO_UNAVAILABLE"; | 
 |     case RADIO_STATE_SIM_NOT_READY: | 
 |         return "RADIO_SIM_NOT_READY"; | 
 |     case RADIO_STATE_SIM_LOCKED_OR_ABSENT: | 
 |         return "RADIO_SIM_LOCKED_OR_ABSENT"; | 
 |     case RADIO_STATE_SIM_READY: | 
 |         return "RADIO_SIM_READY"; | 
 |     case RADIO_STATE_RUIM_NOT_READY: | 
 |         return "RADIO_RUIM_NOT_READY"; | 
 |     case RADIO_STATE_RUIM_READY: | 
 |         return "RADIO_RUIM_READY"; | 
 |     case RADIO_STATE_RUIM_LOCKED_OR_ABSENT: | 
 |         return "RADIO_RUIM_LOCKED_OR_ABSENT"; | 
 |     case RADIO_STATE_NV_NOT_READY: | 
 |         return "RADIO_NV_NOT_READY"; | 
 |     case RADIO_STATE_NV_READY: | 
 |         return "RADIO_NV_READY"; | 
 |     case RADIO_STATE_ON: | 
 |         return "RADIO_ON"; | 
 |     default: | 
 |         return "<unknown state>"; | 
 |     } | 
 | } | 
 |  | 
 | const char *rilSocketIdToString(RIL_SOCKET_ID socket_id) { | 
 |     switch (socket_id) { | 
 |     case RIL_SOCKET_1: | 
 |         return "RIL_SOCKET_1"; | 
 | #if (SIM_COUNT >= 2) | 
 |     case RIL_SOCKET_2: | 
 |         return "RIL_SOCKET_2"; | 
 | #endif | 
 | #if (SIM_COUNT >= 3) | 
 |         case RIL_SOCKET_3: | 
 |         return "RIL_SOCKET_3"; | 
 | #endif | 
 | #if (SIM_COUNT >= 4) | 
 |         case RIL_SOCKET_4: | 
 |         return "RIL_SOCKET_4"; | 
 | #endif | 
 |     default: | 
 |         return "not a valid RIL"; | 
 |     } | 
 | } | 
 |  | 
 | void update_radio_capa(RIL_RadioCapability* cap, int slot) { | 
 |     memset(&radio_capability[slot], 0, sizeof(RIL_RadioCapability)); | 
 |     if(cap != NULL) { | 
 |         strcpy(radio_capability[slot].logicalModemUuid,cap->logicalModemUuid); | 
 |         radio_capability[slot].phase = cap->phase; | 
 |         radio_capability[slot].rat = cap->rat; | 
 |         radio_capability[slot].session = cap->session; | 
 |         radio_capability[slot].status = cap->status; | 
 |         radio_capability[slot].version = cap->version; | 
 |     } | 
 | } | 
 |  | 
 | RIL_RadioCapability get_radio_capa(int slot) { | 
 |     return radio_capability[slot]; | 
 | } | 
 |  | 
 | void update_voice_radio_tech(int code, int slot) { | 
 |     cur_voice_radio_tech[slot] = code; | 
 | } | 
 |  | 
 | int get_voice_radio_tech(int slot){ | 
 |     return cur_voice_radio_tech[slot]; | 
 | } | 
 |  | 
 | void updateCardStatusV6(RIL_CardStatus_v6 *card_status,int slot) | 
 | { | 
 |     if(cur_CardS_Status[slot] != NULL) { | 
 |         RLOGD("[slot%d]updateCardStatusV6", slot); | 
 |         for(int i = 0; i < cur_CardS_Status[slot]->num_applications; i++) { | 
 |         free(cur_CardS_Status[slot]->applications[i].aid_ptr); | 
 |         cur_CardS_Status[slot]->applications[i].aid_ptr = NULL; | 
 |         free(cur_CardS_Status[slot]->applications[i].app_label_ptr); | 
 |         cur_CardS_Status[slot]->applications[i].app_label_ptr = NULL; | 
 |         } | 
 |         free(cur_CardS_Status[slot]); | 
 |         cur_CardS_Status[slot] = NULL; | 
 |     } | 
 |     cur_CardS_Status[slot] = (RIL_CardStatus_v6 *)calloc(1, sizeof(RIL_CardStatus_v6)); | 
 |     memset(cur_CardS_Status[slot], 0, sizeof(RIL_CardStatus_v6)); | 
 |     cur_CardS_Status[slot]->card_state = card_status->card_state; | 
 |     cur_CardS_Status[slot]->cdma_subscription_app_index = card_status->cdma_subscription_app_index; | 
 |     cur_CardS_Status[slot]->gsm_umts_subscription_app_index = card_status->gsm_umts_subscription_app_index; | 
 |     cur_CardS_Status[slot]->ims_subscription_app_index = card_status->ims_subscription_app_index; | 
 |     cur_CardS_Status[slot]->num_applications = card_status->num_applications; | 
 |     cur_CardS_Status[slot]->universal_pin_state = card_status->universal_pin_state; | 
 |     RLOGD("[slot%d]updateCardStatusV6 card_state: %d, cdma_index: %d, gsm_index: %d, " | 
 |             "ims_index: %d, num_applications: %d, universal_pin_state: %d", | 
 |             slot, | 
 |             cur_CardS_Status[slot]->card_state, | 
 |             cur_CardS_Status[slot]->cdma_subscription_app_index, | 
 |             cur_CardS_Status[slot]->gsm_umts_subscription_app_index, | 
 |             cur_CardS_Status[slot]->ims_subscription_app_index, | 
 |             cur_CardS_Status[slot]->num_applications, | 
 |             cur_CardS_Status[slot]->universal_pin_state); | 
 |     if(card_status) | 
 |     { | 
 |         for(int i = 0; i < card_status->num_applications; i++) { | 
 |             cur_CardS_Status[slot]->applications[i].app_state       = card_status->applications[i].app_state; | 
 |             cur_CardS_Status[slot]->applications[i].app_type        = card_status->applications[i].app_type; | 
 |             cur_CardS_Status[slot]->applications[i].perso_substate  = card_status->applications[i].perso_substate; | 
 |             cur_CardS_Status[slot]->applications[i].pin1            = card_status->applications[i].pin1; | 
 |             cur_CardS_Status[slot]->applications[i].pin1_replaced   = card_status->applications[i].pin1_replaced; | 
 |             cur_CardS_Status[slot]->applications[i].pin2            = card_status->applications[i].pin2; | 
 |             cur_CardS_Status[slot]->applications[i].aid_ptr = strdup(card_status->applications[i].aid_ptr); | 
 |             cur_CardS_Status[slot]->applications[i].app_label_ptr = strdup(card_status->applications[i].app_label_ptr); | 
 |         } | 
 |     } else { | 
 |         RLOGD("[slot%d]updateCardStatusV6: sim card message is null", slot); | 
 |     } | 
 | } | 
 |  | 
 | char* getAid(int slot) | 
 | { | 
 |     char* aid = ""; | 
 |     int index = -1; | 
 |     if(cur_CardS_Status[slot] != NULL){ | 
 |         if(Phone_utils::get_phone_type(slot) == Phone_utils::PHONE_TYPE_CDMA) { | 
 |             index = cur_CardS_Status[slot]->cdma_subscription_app_index; | 
 |         } else { | 
 |             index = cur_CardS_Status[slot]->gsm_umts_subscription_app_index; | 
 |         } | 
 |         if(index >= 0 && index < cur_CardS_Status[slot]->num_applications) { | 
 |             aid =  cur_CardS_Status[slot]->applications[index].aid_ptr; | 
 |         } | 
 |     } | 
 |     RLOGD("[slot%d] index: %d, getAid: %s", slot, index, aid); | 
 |     return aid; | 
 | } | 
 |  | 
 | void update_reg_voice_service_state(int request, char *code, int slot, int32_t token) | 
 | { | 
 |     if((reg_voice_service_state[slot] != atoi(code)) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)) { | 
 |         reg_voice_service_state[slot] = atoi(code); | 
 |         regCodeToServiceState(request, atoi(code), slot); | 
 |     } | 
 | } | 
 |  | 
 | void update_reg_voice_radio_tech(int request, int code, int slot, int32_t token) { | 
 |     if((reg_voice_radio_tech[slot] != code) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)){ | 
 |         reg_voice_radio_tech[slot] = code; | 
 |         regCodeToRadioTechnology(request, code, slot); | 
 |     } | 
 | } | 
 |  | 
 | void update_reg_data_service_state(int request, char *code,int slot, int32_t token) | 
 | { | 
 |     if((reg_data_service_state[slot] != atoi(code)) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)) { | 
 |         reg_data_service_state[slot] = atoi(code); | 
 |         regCodeToServiceState(request, atoi(code), slot); | 
 |     } | 
 | } | 
 |  | 
 | void update_reg_data_radio_tech(int request, int code, int slot, int32_t token){ | 
 |     if((reg_data_radio_tech[slot] != code) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)) { | 
 |         reg_data_radio_tech[slot] = code; | 
 |         regCodeToRadioTechnology(request, code, slot); | 
 |     } | 
 | } | 
 |  | 
 | void registerRadioOn(RfDesenseTxTest* rf){ | 
 |     if(!m_RfDesense) { | 
 |         m_RfDesense = rf; | 
 |     } | 
 | } | 
 |  | 
 | void unregisterRadioOn() { | 
 |     if(m_RfDesense) { | 
 |         m_RfDesense == NULL; | 
 |     } | 
 | } | 
 |  | 
 | void registerRadioOffOrNotAvailable(RfDesenseTxTest* rf){ | 
 |     if(!m_RfDesense) { | 
 |         m_RfDesense = rf; | 
 |     } | 
 | } | 
 |  | 
 | void unregisterRadioOffOrNotAvailable() { | 
 |     if(m_RfDesense) { | 
 |         m_RfDesense == NULL; | 
 |     } | 
 | } | 
 |  | 
 | void registerOnUnsolOemHookRaw(RfDesenseTxTest* rf){ | 
 |     if(!m_RfDesense) { | 
 |         m_RfDesense = rf; | 
 |     } | 
 | } | 
 |  | 
 | void unregisterOnUnsolOemHookRaw(){ | 
 |     if(m_RfDesense) { | 
 |         m_RfDesense == NULL; | 
 |     } | 
 | } | 
 |  | 
 | void register_response_oem_hook_raw(RfDesenseTxTest* rf){ | 
 |     if(!m_RfDesense) { | 
 |         m_RfDesense = rf; | 
 |     } | 
 | } | 
 |  | 
 | void unregister_response_oem_hook_raw(){ | 
 |     if(m_RfDesense) { | 
 |         m_RfDesense == NULL; | 
 |     } | 
 | } | 
 |  | 
 | void updateRadioStatus(int newValue ,RIL_SOCKET_ID soc_id) | 
 | { | 
 |     RLOGD("updateRadioStatus oldState: %d, newState: %d", radio_status[soc_id], newValue); | 
 |     bool newOn = (newValue == RADIO_STATE_ON); | 
 |     bool oldOn = (radio_status[soc_id] == RADIO_STATE_ON); | 
 |     bool newAvaiable = (newValue != RADIO_STATE_UNAVAILABLE); | 
 |     bool oldAvaiable = (radio_status[soc_id] != RADIO_STATE_UNAVAILABLE); | 
 |     if (newOn && !oldOn) { | 
 |         RLOGD("RadioStateOn"); | 
 |         //printf("[SIM%d] radio on\n",soc_id +1); | 
 |         if(m_RfDesense){ | 
 |             m_RfDesense->emRadioStateOn(); | 
 |         } | 
 |     } | 
 |  | 
 |     if ((!newOn || !newAvaiable) && !((!oldOn || !oldAvaiable))) { | 
 |         RLOGD("RadioStateOfforNotAvailable"); | 
 |         //printf("[SIM%d] radio off or not available\n",soc_id +1); | 
 |         if(m_RfDesense){ | 
 |             m_RfDesense->emRadioStateOfforNotAvailable(); | 
 |         } | 
 |     } | 
 |     if(newValue != radio_status[soc_id]) { | 
 |         radio_status[soc_id] = newValue; | 
 |     } | 
 | } | 
 |  | 
 | bool isRadioOn(RIL_SOCKET_ID soc_id) | 
 | { | 
 |     return radio_status[soc_id] == RADIO_STATE_ON; | 
 | } | 
 |  | 
 | bool isRadioAvailable(RIL_SOCKET_ID soc_id) | 
 | { | 
 |     return radio_status[soc_id] != RADIO_STATE_UNAVAILABLE; | 
 | } | 
 |  | 
 | static int regCodeToServiceState(int request,int code, int slot) | 
 | { | 
 |     RLOGD("[slot%d]regCodeToServiceState %d, request: %s",slot, code, android::requestToString(request)); | 
 |     switch (code) | 
 |     { | 
 |         case 0: | 
 |         case 2: // 2 is "searching" | 
 |         case 3: // 3 is "registration denied" | 
 |         case 4: // 4 is "unknown" no vaild in current baseband | 
 |         case 10:// same as 0, but indicates that emergency call is possible. | 
 |         case 12:// same as 2, but indicates that emergency call is possible. | 
 |         case 13:// same as 3, but indicates that emergency call is possible. | 
 |         case 14:// same as 4, but indicates that emergency call is possible. | 
 |         { | 
 |             if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |                 printf("[Muser:%d][VOICE REG_STATUS][SIM%d] The current service state is OUT OF SERVICE\n", getpid(), slot); | 
 |             } else { | 
 |                 printf("[Muser:%d][DATA  REG_STATUS][SIM%d] The current service state is OUT OF SERVICE\n", getpid(), slot); | 
 |             } | 
 |             return STATE_OUT_OF_SERVICE; | 
 |         } | 
 |  | 
 |         case 1: | 
 |         case 5: | 
 |         { | 
 |             if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |                 printf("[Muser:%d][VOICE REG_STATUS][SIM%d] The current service state is IN SERVICE\n",getpid(), slot); | 
 |             } else { | 
 |                 printf("[Muser:%d][DATA  REG_STATUS][SIM%d] The current service state is IN SERVICE\n", getpid(),slot); | 
 |             } | 
 |             return STATE_IN_SERVICE; | 
 |         } | 
 |  | 
 |         default: | 
 |         { | 
 |             if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |                 printf("[Muser:%d][VOICE REG_STATUS][SIM%d] Unexpected service state %d\n", getpid(), slot, code); | 
 |             } else { | 
 |                 printf("[Muser:%d][DATA  REG_STATUS][SIM%d] Unexpected service state %d\n", getpid(), slot, code); | 
 |             } | 
 |             RLOGW("[SIM%d]regCodeToServiceState: unexpected service state %d", slot, code); | 
 |             return STATE_OUT_OF_SERVICE; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static int regCodeToRadioTechnology(int request, int code, int slot) { | 
 |     RLOGD("[slot%d]regCodeToRadioTechnology %d, request: %s",slot, code, android::requestToString(request)); | 
 |     switch(code) { | 
 |     case RADIO_TECH_LTE: | 
 |     { | 
 |         if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |             printf("[Muser:%d][VOICE REG_STATUS][SIM%d] The registered radio technology is 4G\n", getpid(), slot); | 
 |         } else { | 
 |             printf("[Muser:%d][DATA  REG_STATUS][SIM%d] The registered radio technology is 4G\n", getpid(), slot); | 
 |         } | 
 |         break; | 
 |     } | 
 |     case RADIO_TECH_GSM: | 
 |     case RADIO_TECH_GPRS: | 
 |     case RADIO_TECH_EDGE: | 
 |     case RADIO_TECH_IS95A: | 
 |     case RADIO_TECH_IS95B: | 
 |     case RADIO_TECH_1xRTT: | 
 |     { | 
 |         if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |             printf("[Muser:%d][VOICE REG_STATUS][SIM%d] The registered radio technology is 2G\n", getpid(), slot); | 
 |         } else { | 
 |             printf("[Muser:%d][DATA  REG_STATUS][SIM%d] The registered radio technology is 2G\n", getpid(), slot); | 
 |         } | 
 |         break; | 
 |     } | 
 |     case RADIO_TECH_UMTS: | 
 |     case RADIO_TECH_HSDPA: | 
 |     case RADIO_TECH_HSUPA: | 
 |     case RADIO_TECH_HSPA: | 
 |     case RADIO_TECH_EHRPD: | 
 |     case RADIO_TECH_HSPAP: | 
 |     case RADIO_TECH_TD_SCDMA: | 
 |     case RADIO_TECH_EVDO_0: | 
 |     case RADIO_TECH_EVDO_A: | 
 |     case RADIO_TECH_EVDO_B: | 
 |     { | 
 |         if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |             printf("[Muser:%d][VOICE REG_STATUS][SIM%d] The registered radio technology is 3G\n", getpid(), slot); | 
 |         } else { | 
 |             printf("[Muser:%d][DATA  REG_STATUS][SIM%d] The registered radio technology is 3G\n", getpid(), slot); | 
 |         } | 
 |         break; | 
 |     } | 
 |     case RADIO_TECH_UNKNOWN: | 
 |     { | 
 |         if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |             printf("[Muser:%d][VOICE REG_STATUS][SIM%d] The registered radio technology is unknown\n", getpid(), slot); | 
 |         } else { | 
 |             printf("[Muser:%d][DATA  REG_STATUS][SIM%d] The registered radio technology is unknown\n", getpid(), slot); | 
 |         } | 
 |         break; | 
 |     } | 
 |     default: | 
 |     { | 
 |         if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) { | 
 |             printf("[Muser:%d][VOICE REG_STATUS][SIM%d] %d is unexpected value\n",getpid(), slot, code); | 
 |         } else { | 
 |             printf("[Muser:%d][DATA  REG_STATUS][SIM%d] %d is unexpected value\n",getpid(), slot, code); | 
 |         } | 
 |     } | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int get_reg_data_radio_tech(int slot) { | 
 |     return reg_data_radio_tech[slot]; | 
 | } | 
 |  | 
 | int get_reg_voice_radio_tech(int slot) { | 
 |     return reg_voice_radio_tech[slot]; | 
 | } | 
 |  | 
 | #ifdef ECALL_SUPPORT | 
 | void ConvertMsd(const char *msdChar, unsigned char *msd) { | 
 |   unsigned int n, x; | 
 |  | 
 |   for (n = 0; n < MSD_MAX_LENGTH; n++) { | 
 |     if (sscanf(&msdChar[n<<1], "%2x", &x) == 1) { | 
 |         msd[n] = x; | 
 |     } else { | 
 |         RLOGE("invalid MSD characters"); | 
 |         break; | 
 |     } | 
 |   } | 
 | } | 
 | #endif /*ECALL_SUPPORT*/ | 
 |  | 
 | bool isFinalResponseErrorEx(char* str) { | 
 |     AtLine atline(str, NULL); | 
 |     return (atline.isFinalResponseErrorEx(0) == 1 ? true : false); | 
 | } | 
 |  | 
 | int get_atci_sim(){ | 
 |     return utils::mtk_property_get_int32(ATCI_SIM, 0); | 
 | } | 
 |  | 
 | static char *findNextChar(char *p, char c, int length) | 
 | { | 
 |     char *ptr = p; | 
 |     int i = 0; | 
 |     while (i++ < length) | 
 |     { | 
 |         if (*ptr++ == c) | 
 |             return ptr; | 
 |     } | 
 |     return NULL; | 
 | } | 
 |  | 
 | static int getGMTval(char *pdata) | 
 | { | 
 |     char *ptr; | 
 |     ptr = findNextChar(pdata, '+', strlen(pdata)); | 
 |     if (ptr == NULL) | 
 |     { | 
 |         ptr = findNextChar(pdata, '-', strlen(pdata)); | 
 |         if (ptr == NULL) | 
 |         { | 
 |             return 0; | 
 |         } | 
 |     } | 
 |     return atoi(ptr); | 
 | } | 
 |  | 
 | static void adjustGMT2LocalTime(struct tm *src, int dGMTval) | 
 | { | 
 |     time_t t1, t2; | 
 |     struct tm * ptm; | 
 |     char buf[255]; | 
 |     int dShiftSec; | 
 |  | 
 |     dShiftSec = dGMTval * 15 * 60; | 
 |     t1 = mktime(src); | 
 |     t2 = (time_t)(t1 + dShiftSec); | 
 |     ptm = gmtime(&t2); | 
 |  | 
 |     memcpy(src, ptm, sizeof(struct tm)); | 
 | } | 
 |  | 
 | void updateSystemTime(const void *data, int datalen) | 
 | { | 
 |     char strTime[32]; | 
 |     struct tm tm; | 
 |     time_t t; | 
 |     int dGMTval; | 
 |  | 
 |     if (data == NULL || datalen <= 0) | 
 |         return; | 
 |  | 
 |     memset(strTime, 0, sizeof(strTime)); | 
 |     strcat(strTime, "20"); | 
 |     strcat(strTime, (const char *)data); | 
 |  | 
 |     dGMTval = getGMTval(strTime); | 
 |     memset(&tm, 0, sizeof(struct tm)); | 
 |     strptime(strTime, "%Y/%m/%d,%H:%M:%S", &tm); | 
 |  | 
 |     adjustGMT2LocalTime(&tm, dGMTval); | 
 |  | 
 |     t = mktime(&tm); | 
 |     stime(&t); | 
 |  | 
 |     return; | 
 | } |