1/*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "cellular_call_config.h"
17
18#include "cellular_call_data_struct.h"
19#include "cellular_call_hisysevent.h"
20#include "cellular_call_rdb_helper.h"
21#include "cellular_call_register.h"
22#include "cellular_call_service.h"
23#include "core_manager_inner.h"
24#include "core_service_client.h"
25#include "module_service_utils.h"
26#include "parameters.h"
27#include "standardize_utils.h"
28#include "string_ex.h"
29#include "telephony_types.h"
30
31namespace OHOS {
32namespace Telephony {
33const int32_t SIM_PRESENT = 1;
34const int32_t SIM_ABSENT = 0;
35const int32_t IMS_SWITCH_STATUS_UNKNOWN = -1;
36const int32_t IMS_SWITCH_STATUS_OFF = 0;
37const int32_t IMS_SWITCH_STATUS_ON = 1;
38const int32_t VONR_SWITCH_STATUS_UNKNOWN = -1;
39const int32_t VONR_SWITCH_STATUS_OFF = 0;
40const int32_t VONR_SWITCH_STATUS_ON = 1;
41const int32_t SAVE_IMS_SWITCH_FAILED = 0;
42const int32_t SAVE_IMS_SWITCH_SUCCESS_CHANGED = 1;
43const int32_t SAVE_IMS_SWITCH_SUCCESS_NOT_CHANGED = 2;
44const int32_t INVALID_SIM_ID = 0;
45const int32_t IMS_GBA_BIT = 0x02;
46const int32_t SYSTEM_PARAMETER_LENGTH = 0x02;
47const int32_t CARRIER_NR_MODE_DEFAULT = 0;
48const int32_t CARRIER_NR_MODE_SA = 2;
49const int32_t CARRIER_NR_MODE_SA_AND_NSA = 3;
50const int MCC_LEN = 3;
51const std::string LAST_ICCID_KEY = "persist.telephony.last_iccid";
52const std::string IMSSWITCH_STATE = "persist.telephony.imsswitch";
53const std::string VONR_STATE = "persist.telephony.vonrswitch";
54
55std::map<int32_t, int32_t> CellularCallConfig::modeMap_;
56std::map<int32_t, int32_t> CellularCallConfig::modeTempMap_;
57std::map<int32_t, bool> CellularCallConfig::imsSwitchOnByDefault_;
58std::map<int32_t, bool> CellularCallConfig::hideImsSwitch_;
59std::map<int32_t, bool> CellularCallConfig::volteSupported_;
60std::map<int32_t, std::vector<int32_t>> CellularCallConfig::nrModeSupportedList_;
61std::map<int32_t, bool> CellularCallConfig::volteProvisioningSupported_;
62std::map<int32_t, bool> CellularCallConfig::ssOverUtSupported_;
63std::map<int32_t, bool> CellularCallConfig::imsGbaRequired_;
64std::map<int32_t, bool> CellularCallConfig::utProvisioningSupported_;
65std::map<int32_t, bool> CellularCallConfig::imsPreferForEmergency_;
66std::map<int32_t, int32_t> CellularCallConfig::callWaitingServiceClass_;
67std::map<int32_t, std::vector<std::string>> CellularCallConfig::imsCallDisconnectResoninfoMapping_;
68std::map<int32_t, bool> CellularCallConfig::forceVolteSwitchOn_;
69std::map<int32_t, int32_t> CellularCallConfig::vonrSwithStatus_;
70std::mutex mutex_;
71std::mutex CellularCallConfig::operatorMutex_;
72std::map<int32_t, std::vector<EmergencyCall>> CellularCallConfig::eccListRadioMap_;
73std::vector<EmergencyCall> CellularCallConfig::eccList3gppHasSim_;
74std::vector<EmergencyCall> CellularCallConfig::eccList3gppNoSim_;
75std::map<int32_t, std::vector<EmergencyCall>> CellularCallConfig::allEccList_;
76std::map<int32_t, int32_t> CellularCallConfig::simState_;
77std::map<int32_t, std::string> CellularCallConfig::curPlmn_;
78std::map<int32_t, CellularCallConfig::cellularNetworkState> CellularCallConfig::networkServiceState_;
79std::map<int32_t, bool> CellularCallConfig::readyToCall_;
80std::map<int32_t, int32_t> CellularCallConfig::nrModeSupported_;
81bool CellularCallConfig::isOperatorConfigInit_ = false;
82
83void CellularCallConfig::InitDefaultOperatorConfig()
84{
85    std::lock_guard<std::mutex> lock(operatorMutex_);
86    for (int32_t i = DEFAULT_SIM_SLOT_ID; i < SIM_SLOT_COUNT; ++i) {
87        CellularCallConfig::imsSwitchOnByDefault_.insert(std::pair<int, bool>(i, false));
88        CellularCallConfig::hideImsSwitch_.insert(std::pair<int, bool>(i, false));
89        CellularCallConfig::volteSupported_.insert(std::pair<int, bool>(i, false));
90        CellularCallConfig::nrModeSupportedList_.insert(std::pair<int, std::vector<int32_t>>(
91            i, std::vector<int32_t> { CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA }));
92        CellularCallConfig::volteProvisioningSupported_.insert(std::pair<int, bool>(i, false));
93        CellularCallConfig::ssOverUtSupported_.insert(std::pair<int, bool>(i, false));
94        CellularCallConfig::imsGbaRequired_.insert(std::pair<int, bool>(i, false));
95        CellularCallConfig::utProvisioningSupported_.insert(std::pair<int, bool>(i, false));
96        CellularCallConfig::imsPreferForEmergency_.insert(std::pair<int, bool>(i, true));
97        CellularCallConfig::callWaitingServiceClass_.insert(
98            std::pair<int, int32_t>(i, DEFAULT_CALL_WAITING_SERVICE_CLASS_CONFIG));
99        CellularCallConfig::imsCallDisconnectResoninfoMapping_.insert(
100            std::pair<int, std::vector<std::string>>(i, IMS_CALL_DISCONNECT_REASONINFO_MAPPING_CONFIG));
101        CellularCallConfig::forceVolteSwitchOn_.insert(std::pair<int, bool>(i, false));
102        CellularCallConfig::readyToCall_.insert(std::pair<int, bool>(i, true));
103        CellularCallConfig::vonrSwithStatus_.insert(std::pair<int, int>(i, VONR_SWITCH_STATUS_UNKNOWN));
104        CellularCallConfig::nrModeSupported_.insert(std::pair<int, int>(i, CARRIER_NR_MODE_DEFAULT));
105        CellularCallConfig::cellularNetworkState cellularState;
106        CellularCallConfig::networkServiceState_.insert(std::pair<int, CellularCallConfig::cellularNetworkState>(i,
107            cellularState));
108    }
109}
110
111CellularCallConfig::CellularCallConfig()
112{
113    if (!isOperatorConfigInit_) {
114        InitDefaultOperatorConfig();
115        isOperatorConfigInit_ = true;
116    }
117}
118
119int32_t CellularCallConfig::SetDomainPreferenceMode(int32_t slotId, int32_t mode)
120{
121    if (mode < DomainPreferenceMode::CS_VOICE_ONLY || mode > DomainPreferenceMode::IMS_PS_VOICE_ONLY) {
122        TELEPHONY_LOGE("SetDomainPreferenceMode return, mode out of range!");
123        return CALL_ERR_PARAMETER_OUT_OF_RANGE;
124    }
125    modeTempMap_[slotId] = mode;
126    return configRequest_.SetDomainPreferenceModeRequest(slotId, mode);
127}
128
129int32_t CellularCallConfig::GetDomainPreferenceMode(int32_t slotId)
130{
131    return configRequest_.GetDomainPreferenceModeRequest(slotId);
132}
133
134int32_t CellularCallConfig::SetImsSwitchStatus(int32_t slotId, bool active)
135{
136    TELEPHONY_LOGI("entry, slotId:%{public}d, active:%{public}d", slotId, active);
137    if (!volteSupported_[slotId]) {
138        TELEPHONY_LOGE("Enable ims switch failed due to volte is not supported.");
139        return CALL_ERR_VOLTE_NOT_SUPPORT;
140    }
141    if (active && !IsVolteProvisioned(slotId)) {
142        TELEPHONY_LOGE("Enable ims switch failed due to volte provisioning disabled.");
143        return CALL_ERR_VOLTE_PROVISIONING_DISABLED;
144    }
145    int32_t simId = CoreManagerInner::GetInstance().GetSimId(slotId);
146    if (simId <= INVALID_SIM_ID) {
147        TELEPHONY_LOGE("failed due to invalid sim id %{public}d", simId);
148        return TELEPHONY_ERR_SLOTID_INVALID;
149    }
150
151    active = ChangeImsSwitchWithOperatorConfig(slotId, active);
152    int32_t ret = SaveImsSwitch(slotId, BooleanToImsSwitchValue(active));
153    if (ret == SAVE_IMS_SWITCH_FAILED) {
154        return TELEPHONY_ERR_DATABASE_WRITE_FAIL;
155    } else if (ret == SAVE_IMS_SWITCH_SUCCESS_NOT_CHANGED) {
156        return TELEPHONY_SUCCESS;
157    }
158
159    SimState simState = SimState::SIM_STATE_UNKNOWN;
160    CoreManagerInner::GetInstance().GetSimState(slotId, simState);
161    TELEPHONY_LOGI("active: %{public}d simState : %{public}d", active, simState);
162    if (simState == SimState::SIM_STATE_LOADED || simState == SimState::SIM_STATE_READY) {
163        UpdateImsCapabilities(slotId, !active);
164    }
165    return TELEPHONY_SUCCESS;
166}
167
168int32_t CellularCallConfig::GetImsSwitchStatus(int32_t slotId, bool &enabled)
169{
170    TELEPHONY_LOGD("entry, slotId: %{public}d", slotId);
171    auto itorHide = hideImsSwitch_.find(slotId);
172    if (itorHide != hideImsSwitch_.end()) {
173        if (itorHide->second) {
174            auto itorSwitch = imsSwitchOnByDefault_.find(slotId);
175            if (itorSwitch != imsSwitchOnByDefault_.end()) {
176                enabled = imsSwitchOnByDefault_[slotId];
177            }
178        } else {
179            int32_t imsSwitchStatus = GetSwitchStatus(slotId);
180            enabled = imsSwitchStatus;
181        }
182    } else {
183        TELEPHONY_LOGI("do not find hideImsSwitch");
184        int32_t imsSwitchStatus = GetSwitchStatus(slotId);
185        enabled = imsSwitchStatus;
186    }
187    return TELEPHONY_SUCCESS;
188}
189
190int32_t CellularCallConfig::SetVoNRSwitchStatus(int32_t slotId, int32_t state)
191{
192    TELEPHONY_LOGI(
193        "CellularCallConfig::SetVoNRSwitchStatus entry, slotId: %{public}d, state: %{public}d", slotId, state);
194    if (!IsVonrSupported(slotId, IsGbaValid(slotId))) {
195        TELEPHONY_LOGE("Enable VoNR switch failed due to VoNR is not supported.");
196        return TELEPHONY_ERR_FAIL;
197    }
198    SimState simState = SimState::SIM_STATE_UNKNOWN;
199    CoreManagerInner::GetInstance().GetSimState(slotId, simState);
200    if (simState == SimState::SIM_STATE_LOADED || simState == SimState::SIM_STATE_READY) {
201        configRequest_.SetVoNRSwitchStatusRequest(slotId, state);
202        vonrSwithStatus_[slotId] = state;
203        return TELEPHONY_SUCCESS;
204    }
205    return TELEPHONY_ERR_NO_SIM_CARD;
206}
207
208int32_t CellularCallConfig::GetVoNRSwitchStatus(int32_t slotId, int32_t &state)
209{
210    if (!IsVonrSupported(slotId, IsGbaValid(slotId))) {
211        TELEPHONY_LOGE("Enable VoNR switch failed due to VoNR is not supported.");
212        state = VONR_SWITCH_STATUS_OFF;
213        return TELEPHONY_SUCCESS;
214    }
215    state = ObtainVoNRState(slotId);
216    return TELEPHONY_SUCCESS;
217}
218
219void CellularCallConfig::HandleSimStateChanged(int32_t slotId)
220{
221    TELEPHONY_LOGI("CellularCallConfig::HandleSimStateChanged entry, slotId: %{public}d", slotId);
222    if (CheckAndUpdateSimState(slotId)) {
223        UpdateEccNumberList(slotId);
224    }
225}
226
227void CellularCallConfig::HandleFactoryReset(int32_t slotId)
228{
229    if (!IsValidSlotId(slotId)) {
230        TELEPHONY_LOGE(" invalid slot id %{public}d", slotId);
231        return;
232    }
233    bool hasSimCard = false;
234    DelayedRefSingleton<CoreServiceClient>::GetInstance().HasSimCard(slotId, hasSimCard);
235    if (!hasSimCard) {
236        TELEPHONY_LOGE("return due to no sim card");
237        return;
238    }
239    // Set VoLTE to default
240    int32_t ret = SaveImsSwitch(slotId, BooleanToImsSwitchValue(imsSwitchOnByDefault_[slotId]));
241    TELEPHONY_LOGI("Save ims switch ret: %{public}d", ret);
242    UpdateImsCapabilities(slotId, true);
243}
244
245void CellularCallConfig::HandleSimRecordsLoaded(int32_t slotId)
246{
247    TELEPHONY_LOGI("CellularCallConfig::HandleSimRecordsLoaded entry, slotId: %{public}d", slotId);
248    CheckAndUpdateSimState(slotId);
249    UpdateEccNumberList(slotId);
250}
251
252void CellularCallConfig::HandleResidentNetworkChange(int32_t slotId, std::string plmn)
253{
254    TELEPHONY_LOGI("CellularCallConfig::HandleResidentNetworkChange entry, slotId: %{public}d", slotId);
255    curPlmn_[slotId] = plmn;
256    CheckAndUpdateSimState(slotId);
257    UpdateEccNumberList(slotId);
258}
259
260void CellularCallConfig::HandleNetworkStateChange(int32_t slotId)
261{
262    {
263        std::lock_guard<std::mutex> lock(operatorMutex_);
264        TELEPHONY_LOGI("CellularCallConfig::HandleNetworkStateChange entry, slotId: %{public}d", slotId);
265        auto itSlotId = networkServiceState_.find(slotId);
266        if (itSlotId == networkServiceState_.end()) {
267            TELEPHONY_LOGE("slotId is not in networkServiceState_");
268            return;
269        }
270        sptr<NetworkState> networkState = nullptr;
271        CoreManagerInner::GetInstance().GetNetworkStatus(slotId, networkState);
272        if (networkState == nullptr) {
273            TELEPHONY_LOGE("networkState get failed, slotId: %{public}d", slotId);
274            return;
275        }
276        bool isInSrv = networkState->GetRegStatus() == RegServiceState::REG_STATE_IN_SERVICE ? true : false;
277        bool isRoam = networkState->IsRoaming();
278        if (networkServiceState_[slotId].isInService_ == isInSrv
279            && networkServiceState_[slotId].isRoaming_ == isRoam) {
280            TELEPHONY_LOGI("service state and roaming state are not change, slotId: %{public}d", slotId);
281            return;
282        }
283        networkServiceState_[slotId].isInService_ = isInSrv;
284        networkServiceState_[slotId].isRoaming_ = isRoam;
285    }
286    CheckAndUpdateSimState(slotId);
287    UpdateEccNumberList(slotId);
288}
289
290void CellularCallConfig::GetEccListFromResult(const std::vector<EccNum> &eccVec,
291    std::vector<std::string> &callListWithCard, std::vector<std::string> &callListNoCard)
292{
293    if (!eccVec.empty()) {
294        std::string eccWithCard = eccVec[0].ecc_withcard;
295        callListWithCard = StandardizeUtils::Split(eccWithCard, ",");
296        std::string eccNoCard = eccVec[0].ecc_nocard;
297        callListNoCard = StandardizeUtils::Split(eccNoCard, ",");
298    }
299}
300
301int32_t CellularCallConfig::CheckHomeAndPresentState(int32_t slotId, bool &isHomeAndPresent)
302{
303    sptr<NetworkState> networkState = nullptr;
304    CoreManagerInner::GetInstance().GetNetworkStatus(slotId, networkState);
305    if (networkState == nullptr) {
306        TELEPHONY_LOGE("networkState get failed, slotId: %{public}d", slotId);
307        return TELEPHONY_ERR_FAIL;
308    }
309    RegServiceState regState = networkState->GetRegStatus();
310    bool isRoam = networkState->IsRoaming();
311    bool isNetworkInService = (regState == RegServiceState::REG_STATE_IN_SERVICE);
312    bool isHomeNetRegister = isNetworkInService && !isRoam;
313    bool isSimPresent = false;
314    {
315        std::lock_guard<std::mutex> lock(simStateLock_);
316        isSimPresent = simState_[slotId] == SIM_PRESENT;
317    }
318    isHomeAndPresent = isHomeNetRegister && isSimPresent;
319    return TELEPHONY_SUCCESS;
320}
321
322void CellularCallConfig::UpdateEccNumberList(int32_t slotId)
323{
324    std::u16string u16Hplmn = u"";
325    CoreManagerInner::GetInstance().GetSimOperatorNumeric(slotId, u16Hplmn);
326    std::string hplmn = Str16ToStr8(u16Hplmn);
327    std::vector<std::string> callListWithCard;
328    std::vector<std::string> callListNoCard;
329    std::vector<EccNum> eccVec;
330    bool isHomeAndPresent = false;
331    if (CheckHomeAndPresentState(slotId, isHomeAndPresent) != TELEPHONY_SUCCESS) {
332        return;
333    }
334    if (!hplmn.empty() && isHomeAndPresent) {
335        OperatorConfig operatorConfig;
336        CoreManagerInner::GetInstance().GetOperatorConfigs(slotId, operatorConfig);
337        callListWithCard = operatorConfig.stringArrayValue[KEY_EMERGENCY_CALL_STRING_ARRAY];
338        if (callListWithCard.empty()) {
339            DelayedSingleton<CellularCallRdbHelper>::GetInstance()->QueryEccList(hplmn, eccVec);
340            GetEccListFromResult(eccVec, callListWithCard, callListNoCard);
341        }
342    } else {
343        if (curPlmn_[slotId].empty()) {
344            std::u16string u16Rplmn = CoreManagerInner::GetInstance().GetOperatorNumeric(slotId);
345            std::string rplmn = Str16ToStr8(u16Rplmn);
346            if (rplmn.empty()) {
347                TELEPHONY_LOGE("rplmn is empty");
348                return;
349            }
350            curPlmn_[slotId] = rplmn;
351        }
352        DelayedSingleton<CellularCallRdbHelper>::GetInstance()->QueryEccList(curPlmn_[slotId], eccVec);
353        GetEccListFromResult(eccVec, callListWithCard, callListNoCard);
354    }
355    std::vector<EmergencyCall> eccInfoList;
356    for (auto it : callListWithCard) {
357        eccInfoList.push_back(BuildDefaultEmergencyCall(it, SimpresentType::TYPE_HAS_CARD));
358    }
359    for (auto it : callListNoCard) {
360        eccInfoList.push_back(BuildDefaultEmergencyCall(it, SimpresentType::TYPE_NO_CARD));
361    }
362    SetEmergencyCallList(slotId, eccInfoList);
363}
364
365void CellularCallConfig::HandleSimAccountLoaded(int32_t slotId)
366{
367    TELEPHONY_LOGI("entry, slotId: %{public}d", slotId);
368    saveImsSwitchStatusToLocalForPowerOn(slotId);
369    ResetImsSwitch(slotId);
370    UpdateImsCapabilities(slotId, true);
371    CheckAndUpdateSimState(slotId);
372    UpdateEccNumberList(slotId);
373}
374
375void CellularCallConfig::HandleOperatorConfigChanged(int32_t slotId)
376{
377    OperatorConfig operatorConfig;
378    int32_t ret = CoreManagerInner::GetInstance().GetOperatorConfigs(slotId, operatorConfig);
379    if (ret != TELEPHONY_SUCCESS) {
380        TELEPHONY_LOGE("failed due to get operator config");
381        return;
382    }
383
384    int32_t result = ParseAndCacheOperatorConfigs(slotId, operatorConfig);
385    if (result != TELEPHONY_SUCCESS) {
386        TELEPHONY_LOGE("failed due to parse operator config");
387        return;
388    }
389    ResetImsSwitch(slotId);
390    UpdateImsCapabilities(slotId, true);
391}
392
393int32_t CellularCallConfig::ParseAndCacheOperatorConfigs(int32_t slotId, OperatorConfig &poc)
394{
395    TELEPHONY_LOGI("CellularCallConfig::ParseAndCacheOperatorConfigs start. slotId %{public}d", slotId);
396    std::lock_guard<std::mutex> lock(operatorMutex_);
397    if (!IsValidSlotId(slotId)) {
398        TELEPHONY_LOGE(" invalid slot id %{public}d", slotId);
399        return TELEPHONY_ERROR;
400    }
401
402    ParseBoolOperatorConfigs(slotId, imsSwitchOnByDefault_, poc, KEY_IMS_SWITCH_ON_BY_DEFAULT_BOOL);
403    ParseBoolOperatorConfigs(slotId, hideImsSwitch_, poc, KEY_HIDE_IMS_SWITCH_BOOL);
404    ParseBoolOperatorConfigs(slotId, volteSupported_, poc, KEY_VOLTE_SUPPORTED_BOOL);
405    ParseBoolOperatorConfigs(slotId, volteProvisioningSupported_, poc, KEY_VOLTE_PROVISIONING_SUPPORTED_BOOL);
406    ParseBoolOperatorConfigs(slotId, ssOverUtSupported_, poc, KEY_SS_OVER_UT_SUPPORTED_BOOL);
407    ParseBoolOperatorConfigs(slotId, imsGbaRequired_, poc, KEY_IMS_GBA_REQUIRED_BOOL);
408    ParseBoolOperatorConfigs(slotId, utProvisioningSupported_, poc, KEY_UT_PROVISIONING_SUPPORTED_BOOL);
409    ParseBoolOperatorConfigs(slotId, imsPreferForEmergency_, poc, KEY_IMS_PREFER_FOR_EMERGENCY_BOOL);
410    ParseBoolOperatorConfigs(slotId, forceVolteSwitchOn_, poc, KEY_FORCE_VOLTE_SWITCH_ON_BOOL);
411
412    if (poc.intArrayValue.count(KEY_NR_MODE_SUPPORTED_LIST_INT_ARRAY) > 0) {
413        nrModeSupportedList_[slotId] = poc.intArrayValue[KEY_NR_MODE_SUPPORTED_LIST_INT_ARRAY];
414    }
415    if (poc.intValue.count(KEY_CALL_WAITING_SERVICE_CLASS_INT) > 0) {
416        callWaitingServiceClass_[slotId] = poc.intValue[KEY_CALL_WAITING_SERVICE_CLASS_INT];
417    }
418    if (poc.intValue.count(KEY_NR_MODE_SUPPORTED_INT) > 0) {
419        nrModeSupported_[slotId] = poc.intValue[KEY_NR_MODE_SUPPORTED_INT];
420    }
421    if (poc.stringArrayValue.count(KEY_IMS_CALL_DISCONNECT_REASONINFO_MAPPING_STRING_ARRAY) > 0) {
422        imsCallDisconnectResoninfoMapping_[slotId] =
423            poc.stringArrayValue[KEY_IMS_CALL_DISCONNECT_REASONINFO_MAPPING_STRING_ARRAY];
424    }
425    return TELEPHONY_SUCCESS;
426}
427
428void CellularCallConfig::ParseBoolOperatorConfigs(
429    int32_t slotId, std::map<int32_t, bool> &config, OperatorConfig &poc, std::string configName)
430{
431    auto it = poc.boolValue.find(configName);
432    if (it != poc.boolValue.end()) {
433        config[slotId] = it->second;
434    } else {
435        TELEPHONY_LOGE("do't find operator config %{public}s", configName.c_str());
436    }
437}
438
439void CellularCallConfig::ResetImsSwitch(int32_t slotId)
440{
441    bool hasSimCard = false;
442    CoreManagerInner::GetInstance().HasSimCard(slotId, hasSimCard);
443    if (!hasSimCard) {
444        TELEPHONY_LOGE("return due to no sim card");
445        return;
446    }
447    std::u16string iccId;
448    CoreManagerInner::GetInstance().GetSimIccId(slotId, iccId);
449    if (IsSimChanged(slotId, Str16ToStr8(iccId)) && forceVolteSwitchOn_[slotId]) {
450        int32_t ret = CoreManagerInner::GetInstance().SaveImsSwitch(
451            slotId, BooleanToImsSwitchValue(imsSwitchOnByDefault_[slotId]));
452        if (ret != TELEPHONY_SUCCESS) {
453            TELEPHONY_LOGE("SaveImsSwitch failed");
454        } else {
455            saveImsSwitchStatusToLocal(slotId, BooleanToImsSwitchValue(imsSwitchOnByDefault_[slotId]));
456        }
457    }
458}
459
460void CellularCallConfig::UpdateImsCapabilities(int32_t slotId, bool needUpdateUtCapability)
461{
462    bool isGbaValid = IsGbaValid(slotId);
463    ImsCapabilityList imsCapabilityList;
464    TELEPHONY_LOGI("UpdateImsCapabilities entry");
465    UpdateImsVoiceCapabilities(slotId, isGbaValid, imsCapabilityList);
466    if (needUpdateUtCapability) {
467        UpdateImsUtCapabilities(slotId, isGbaValid, imsCapabilityList);
468    }
469    configRequest_.UpdateImsCapabilities(slotId, imsCapabilityList);
470    configRequest_.SetImsSwitchStatusRequest(slotId, IsNeedTurnOnIms(imsCapabilityList));
471}
472bool CellularCallConfig::IsGbaValid(int32_t slotId)
473{
474    if (imsGbaRequired_[slotId]) {
475        std::u16string simist = CoreManagerInner::GetInstance().GetSimIst(slotId);
476        std::string simistStr = Str16ToStr8(simist);
477        // If carrier requires that IMS is only available if GBA capable SIM is used,
478        // then this function checks GBA bit in EF IST.
479        // Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
480        if (!simistStr.empty() && simistStr.length() > 1) {
481            bool result = (IMS_GBA_BIT & simistStr.at(1)) != 0;
482            return result;
483        }
484    }
485    return true;
486}
487
488void CellularCallConfig::UpdateImsVoiceCapabilities(
489    int32_t slotId, bool isGbaValid, ImsCapabilityList &imsCapabilityList)
490{
491    int32_t vonrSwitch = VONR_SWITCH_STATUS_OFF;
492    GetVoNRSwitchStatus(slotId, vonrSwitch);
493    bool vonrSwitchEnabled = vonrSwitch == VONR_SWITCH_STATUS_ON;
494    ImsCapability vonrCapability;
495    vonrCapability.imsCapabilityType = ImsCapabilityType::CAPABILITY_TYPE_VOICE;
496    vonrCapability.imsRadioTech = ImsRegTech::IMS_REG_TECH_NR;
497    vonrCapability.enable = IsVonrSupported(slotId, isGbaValid) && vonrSwitchEnabled;
498    imsCapabilityList.imsCapabilities.push_back(vonrCapability);
499
500    bool imsSwitch = false;
501    GetImsSwitchStatus(slotId, imsSwitch);
502    bool isVolteProvisioned = IsVolteProvisioned(slotId);
503    ImsCapability volteCapability;
504    volteCapability.imsCapabilityType = ImsCapabilityType::CAPABILITY_TYPE_VOICE;
505    volteCapability.imsRadioTech = ImsRegTech::IMS_REG_TECH_LTE;
506    volteCapability.enable = vonrCapability.enable
507        || (volteSupported_[slotId] && isGbaValid && imsSwitch && isVolteProvisioned);
508    imsCapabilityList.imsCapabilities.push_back(volteCapability);
509    TELEPHONY_LOGI("slotId = %{public}d, vonrCapability = %{public}d, volteSupported = %{public}d, "
510        "isGbaValid = %{public}d, imsSwitch = %{public}d, isVolteProvisioned = %{public}d",
511        slotId, vonrCapability.enable, volteSupported_[slotId], isGbaValid, imsSwitch, isVolteProvisioned);
512}
513
514void CellularCallConfig::UpdateImsUtCapabilities(int32_t slotId, bool isGbaValid, ImsCapabilityList &imsCapabilityList)
515{
516    ImsCapability utCapability;
517    utCapability.imsCapabilityType = ImsCapabilityType::CAPABILITY_TYPE_UT;
518    utCapability.imsRadioTech = ImsRegTech::IMS_REG_TECH_LTE;
519    utCapability.enable = ssOverUtSupported_[slotId] && isGbaValid && IsUtProvisioned(slotId);
520    imsCapabilityList.imsCapabilities.push_back(utCapability);
521}
522
523bool CellularCallConfig::IsVolteProvisioned(int32_t slotId)
524{
525    if (volteProvisioningSupported_[slotId]) {
526        int32_t volteFeatureValue;
527        int32_t result = configRequest_.GetImsFeatureValueRequest(FeatureType::TYPE_VOICE_OVER_LTE, volteFeatureValue);
528        if (result != TELEPHONY_SUCCESS) {
529            TELEPHONY_LOGE("get volte feature value failed");
530            return false;
531        }
532        return volteFeatureValue == ImsFeatureIntResult::IMS_FEATURE_INT_VALUE_ENABLED;
533    }
534    return true;
535}
536
537bool CellularCallConfig::IsVonrSupported(int32_t slotId, bool isGbaValid)
538{
539    return nrModeSupported_[slotId] == CARRIER_NR_MODE_SA_AND_NSA || nrModeSupported_[slotId] == CARRIER_NR_MODE_SA;
540}
541
542bool CellularCallConfig::IsUtProvisioned(int32_t slotId)
543{
544    if (utProvisioningSupported_[slotId]) {
545        int32_t utFeatureValue;
546        int32_t result = configRequest_.GetImsFeatureValueRequest(FeatureType::TYPE_SS_OVER_UT, utFeatureValue);
547        if (result != TELEPHONY_SUCCESS) {
548            TELEPHONY_LOGE("get ut feature value failed");
549            return false;
550        }
551        return utFeatureValue == ImsFeatureIntResult::IMS_FEATURE_INT_VALUE_ENABLED;
552    }
553    return true;
554}
555
556EmergencyCall CellularCallConfig::BuildEmergencyCall(int32_t slotId, const EmergencyInfo &from)
557{
558    EmergencyCall to = {};
559    to.eccNum = from.eccNum;
560    to.eccType = EccType(from.category);
561    to.simpresent = SimpresentType(from.simpresent);
562    to.mcc = from.mcc;
563    to.abnormalService = AbnormalServiceType(from.abnormalService);
564    return to;
565}
566
567bool CellularCallConfig::IsNeedTurnOnIms(const ImsCapabilityList &imsCapabilityList)
568{
569    for (auto imsCapabilitie : imsCapabilityList.imsCapabilities) {
570        if (imsCapabilitie.imsCapabilityType == ImsCapabilityType::CAPABILITY_TYPE_VOICE
571            || imsCapabilitie.imsCapabilityType == ImsCapabilityType::CAPABILITY_TYPE_VIDEO) {
572            if (imsCapabilitie.enable) {
573                return true;
574            }
575        }
576    }
577    return false;
578}
579
580bool CellularCallConfig::IsSimChanged(int32_t slotId, std::string iccid)
581{
582    const int32_t sysparaSize = SYSTEM_PARAMETER_LENGTH;
583    char lastIccid[sysparaSize] = { 0 };
584    std::string key = LAST_ICCID_KEY + std::to_string(slotId);
585    GetParameter(key.c_str(), "", lastIccid, sysparaSize);
586
587    if (iccid.compare(lastIccid) != 0) {
588        SetParameter(key.c_str(), iccid.c_str());
589        return true;
590    }
591    return false;
592}
593
594bool CellularCallConfig::ChangeImsSwitchWithOperatorConfig(int32_t slotId, bool active)
595{
596    auto itorHide = hideImsSwitch_.find(slotId);
597    if (itorHide != hideImsSwitch_.end()) {
598        if (itorHide->second) {
599            auto itorSwitch = imsSwitchOnByDefault_.find(slotId);
600            if (itorSwitch != imsSwitchOnByDefault_.end()) {
601                active = imsSwitchOnByDefault_[slotId];
602                return active;
603            }
604        }
605    }
606    TELEPHONY_LOGE("do not find hideImsSwitch or imsSwitchOnByDefault config");
607    return active;
608}
609
610int32_t CellularCallConfig::SaveImsSwitch(int32_t slotId, int32_t imsSwitchValue)
611{
612    int32_t lastImsSwitchValue = IMS_SWITCH_STATUS_UNKNOWN;
613    int32_t queryRet = CoreManagerInner::GetInstance().QueryImsSwitch(slotId, lastImsSwitchValue);
614    if (queryRet != TELEPHONY_SUCCESS) {
615        TELEPHONY_LOGE("query ims switch failed");
616        return SAVE_IMS_SWITCH_FAILED;
617    }
618    if (imsSwitchValue == lastImsSwitchValue) {
619        TELEPHONY_LOGI("ims switch status do not change, imsSwitchValue: %{public}d", imsSwitchValue);
620        return SAVE_IMS_SWITCH_SUCCESS_NOT_CHANGED;
621    }
622    int32_t saveRet = CoreManagerInner::GetInstance().SaveImsSwitch(slotId, imsSwitchValue);
623    if (saveRet != TELEPHONY_SUCCESS) {
624        TELEPHONY_LOGE("save ims switch status to database failed!");
625        return SAVE_IMS_SWITCH_FAILED;
626    }
627    saveImsSwitchStatusToLocal(slotId, imsSwitchValue);
628    SaveVoNRState(slotId, imsSwitchValue);
629    return SAVE_IMS_SWITCH_SUCCESS_CHANGED;
630}
631
632void CellularCallConfig::saveImsSwitchStatusToLocalForPowerOn(int32_t slotId)
633{
634    int32_t imsSwitchStatus = IMS_SWITCH_STATUS_UNKNOWN;
635    int32_t ret = CoreManagerInner::GetInstance().QueryImsSwitch(slotId, imsSwitchStatus);
636    if (ret != TELEPHONY_SUCCESS || imsSwitchStatus == IMS_SWITCH_STATUS_UNKNOWN) {
637        TELEPHONY_LOGI("get ims switch state failed from database, return operator config default value");
638        imsSwitchStatus = imsSwitchOnByDefault_[slotId] ? IMS_SWITCH_STATUS_ON : IMS_SWITCH_STATUS_OFF;
639    }
640
641    TELEPHONY_LOGI(
642        "save slotId[%{public}d] imsSwitchStatus:%{public}d to local for Power on", slotId, imsSwitchStatus);
643    std::string imsSwitchStateKey = IMSSWITCH_STATE + std::to_string(slotId);
644    std::string imsSwitchState = std::to_string(imsSwitchStatus);
645    SetParameter(imsSwitchStateKey.c_str(), imsSwitchState.c_str());
646}
647
648void CellularCallConfig::saveImsSwitchStatusToLocal(int32_t slotId, int32_t imsSwitchStatus)
649{
650    TELEPHONY_LOGI("save slotId[%{public}d] imsSwitchStatus:%{public}d to local", slotId, imsSwitchStatus);
651    std::string imsSwitchStateKey = IMSSWITCH_STATE + std::to_string(slotId);
652    std::string imsSwitchState = std::to_string(imsSwitchStatus);
653    SetParameter(imsSwitchStateKey.c_str(), imsSwitchState.c_str());
654}
655
656void CellularCallConfig::SaveVoNRState(int32_t slotId, int32_t state)
657{
658    CellularCallHiSysEvent::WriteVoNRSwitchChangeEvent(state);
659    TELEPHONY_LOGI("slotId: %{public}d, switchState: %{public}d", slotId, state);
660    std::string vonrState = std::to_string(state);
661    std::string vonrStateKey = VONR_STATE + std::to_string(slotId);
662    SetParameter(vonrStateKey.c_str(), vonrState.c_str());
663}
664
665int32_t CellularCallConfig::ObtainVoNRState(int32_t slotId)
666{
667    std::string vonrStateKey = VONR_STATE + std::to_string(slotId);
668    int32_t vonrState = GetIntParameter(vonrStateKey.c_str(), VONR_SWITCH_STATUS_ON);
669    TELEPHONY_LOGI("slotId: %{public}d, switchState: %{public}d", slotId, vonrState);
670    return vonrState;
671}
672
673void CellularCallConfig::HandleSetLteImsSwitchResult(int32_t slotId, ErrType result)
674{
675    TELEPHONY_LOGI("CellularCallConfig::HandleSetLteImsSwitchResult entry, slotId: %{public}d", slotId);
676    if (result != ErrType::NONE) {
677        TELEPHONY_LOGE("HandleSetLteImsSwitchResult set ims switch to modem failed!");
678        // need to reset the Ims Switch parameter and notify APP to update UI.
679    }
680}
681
682void CellularCallConfig::HandleSetVoNRSwitchResult(int32_t slotId, ErrType result)
683{
684    TELEPHONY_LOGD("CellularCallConfig::HandleSetVoNRSwitchResult entry, slotId: %{public}d", slotId);
685    if (result != ErrType::NONE) {
686        TELEPHONY_LOGE("HandleSetVoNRSwitchResult set vonr switch to modem failed!");
687        return;
688    }
689    SaveVoNRState(slotId, vonrSwithStatus_[slotId]);
690    ImsCapabilityList imsCapabilityList;
691    UpdateImsVoiceCapabilities(slotId, IsGbaValid(slotId), imsCapabilityList);
692    configRequest_.UpdateImsCapabilities(slotId, imsCapabilityList);
693}
694
695void CellularCallConfig::GetDomainPreferenceModeResponse(int32_t slotId, int32_t mode)
696{
697    modeMap_[slotId] = mode;
698}
699
700void CellularCallConfig::GetImsSwitchStatusResponse(int32_t slotId, int32_t active) {}
701
702int32_t CellularCallConfig::GetPreferenceMode(int32_t slotId) const
703{
704    return modeMap_[slotId];
705}
706
707int32_t CellularCallConfig::GetSwitchStatus(int32_t slotId)
708{
709    std::string imsSwitchStateKey = IMSSWITCH_STATE + std::to_string(slotId);
710    int32_t imsSwitchStatus = GetIntParameter(imsSwitchStateKey.c_str(), IMS_SWITCH_STATUS_UNKNOWN);
711    if (imsSwitchStatus == IMS_SWITCH_STATUS_UNKNOWN) {
712        TELEPHONY_LOGI("get ims switch state failed from local, try to get it from database");
713        int32_t ret = CoreManagerInner::GetInstance().QueryImsSwitch(slotId, imsSwitchStatus);
714        if (ret != TELEPHONY_SUCCESS || imsSwitchStatus == IMS_SWITCH_STATUS_UNKNOWN) {
715            TELEPHONY_LOGI("get ims switch state failed from database, return operator config default value");
716            imsSwitchStatus = imsSwitchOnByDefault_[slotId] ? IMS_SWITCH_STATUS_ON : IMS_SWITCH_STATUS_OFF;
717        }
718        // save DB or operator config default ims switch status to local
719        saveImsSwitchStatusToLocal(slotId, imsSwitchStatus);
720    }
721    TELEPHONY_LOGD("slotId[%{public}d] GetSwitchStatus imsSwitchStatus:%{public}d", slotId, imsSwitchStatus);
722    return imsSwitchStatus;
723}
724
725int32_t CellularCallConfig::SetImsConfig(ImsConfigItem item, const std::string &value)
726{
727    return configRequest_.SetImsConfigRequest(item, value);
728}
729
730int32_t CellularCallConfig::SetImsConfig(ImsConfigItem item, int32_t value)
731{
732    return configRequest_.SetImsConfigRequest(item, value);
733}
734
735int32_t CellularCallConfig::GetImsConfig(ImsConfigItem item)
736{
737    return configRequest_.GetImsConfigRequest(item);
738}
739
740int32_t CellularCallConfig::SetImsFeatureValue(FeatureType type, int32_t value)
741{
742    return configRequest_.SetImsFeatureValueRequest(type, value);
743}
744
745int32_t CellularCallConfig::GetImsFeatureValue(FeatureType type)
746{
747    int32_t imsFeatureValue;
748    int32_t ret = configRequest_.GetImsFeatureValueRequest(type, imsFeatureValue);
749    GetImsFeatureValueResponse response;
750    response.result = ret;
751    response.value = imsFeatureValue;
752    DelayedSingleton<CellularCallRegister>::GetInstance()->ReportGetImsFeatureResult(response);
753    return ret;
754}
755
756void CellularCallConfig::SetTempMode(int32_t slotId)
757{
758    modeMap_[slotId] = modeTempMap_[slotId];
759}
760
761void CellularCallConfig::InitModeActive()
762{
763    TELEPHONY_LOGI("InitModeActive");
764    int32_t slotId = DEFAULT_SIM_SLOT_ID;
765    modeMap_[slotId] = DomainPreferenceMode::IMS_PS_VOICE_PREFERRED;
766    std::lock_guard<std::mutex> lock(mutex_);
767    eccListRadioMap_.clear();
768    eccList3gppHasSim_.clear();
769    eccList3gppNoSim_.clear();
770    allEccList_.clear();
771    eccList3gppHasSim_.push_back(BuildDefaultEmergencyCall("112", SimpresentType::TYPE_HAS_CARD));
772    eccList3gppHasSim_.push_back(BuildDefaultEmergencyCall("911", SimpresentType::TYPE_HAS_CARD));
773    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("112", SimpresentType::TYPE_NO_CARD));
774    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("911", SimpresentType::TYPE_NO_CARD));
775    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("000", SimpresentType::TYPE_NO_CARD));
776    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("08", SimpresentType::TYPE_NO_CARD));
777    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("110", SimpresentType::TYPE_NO_CARD));
778    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("118", SimpresentType::TYPE_NO_CARD));
779    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("119", SimpresentType::TYPE_NO_CARD));
780    eccList3gppNoSim_.push_back(BuildDefaultEmergencyCall("999", SimpresentType::TYPE_NO_CARD));
781    TELEPHONY_LOGD("InitModeActive finish");
782}
783
784EmergencyCall CellularCallConfig::BuildDefaultEmergencyCall(const std::string &number, SimpresentType simType)
785{
786    TELEPHONY_LOGD("BuildDefaultEmergencyCall, eccNum:%{public}s", number.c_str());
787    EmergencyCall emergencyCall;
788    emergencyCall.eccNum = number;
789    emergencyCall.eccType = EccType::TYPE_CATEGORY;
790    emergencyCall.simpresent = simType;
791    emergencyCall.mcc = "";
792    emergencyCall.abnormalService = AbnormalServiceType::TYPE_ALL;
793    std::string::size_type pos = number.find('+');
794    if (pos != std::string::npos) {
795        int32_t startOps = 0;
796        std::string category = number.substr(startOps, pos);
797        emergencyCall.eccType = static_cast<EccType>(std::atoi(category.c_str()));
798        emergencyCall.eccNum = number.substr(pos, number.size());
799    }
800    return emergencyCall;
801}
802
803bool CellularCallConfig::GetRoamingState(int32_t slotId)
804{
805    sptr<NetworkState> networkState = nullptr;
806    CoreManagerInner::GetInstance().GetNetworkStatus(slotId, networkState);
807    if (networkState == nullptr) {
808        TELEPHONY_LOGE("networkState get failed, slotId: %{public}d", slotId);
809        return false;
810    }
811    bool isRoaming = networkState->IsRoaming();
812    TELEPHONY_LOGD("isRoaming=%{public}d", isRoaming);
813    return isRoaming;
814}
815
816void CellularCallConfig::MergeEccCallList(int32_t slotId)
817{
818    std::map<int32_t, std::vector<EmergencyCall>> tempEccList;
819    std::string mcc = GetMcc(slotId);
820    for (auto ecc : eccListRadioMap_[slotId]) {
821        ecc.mcc = mcc;
822        tempEccList[slotId].push_back(ecc);
823    }
824    TELEPHONY_LOGD("MergeEccCallList merge radio slotId  %{public}d size  %{public}d", slotId,
825        static_cast<int32_t>(eccListRadioMap_[slotId].size()));
826    SimState simState = SimState::SIM_STATE_UNKNOWN;
827    CoreManagerInner::GetInstance().GetSimState(slotId, simState);
828    bool hasSim = simState == SimState::SIM_STATE_READY || simState == SimState::SIM_STATE_LOADED;
829    if (hasSim) {
830        if (!mcc.empty()) {
831            for (auto ecc : eccList3gppHasSim_) {
832                ecc.mcc = mcc;
833                tempEccList[slotId].push_back(ecc);
834            }
835        }
836    } else {
837        for (auto ecc : eccList3gppNoSim_) {
838            ecc.mcc = mcc;
839            tempEccList[slotId].push_back(ecc);
840        }
841    }
842    std::u16string u16Hplmn = u"";
843    CoreManagerInner::GetInstance().GetSimOperatorNumeric(slotId, u16Hplmn);
844    std::string hplmn = Str16ToStr8(u16Hplmn);
845    if (hasSim && !GetRoamingState(slotId) && !hplmn.empty()) {
846        std::vector<EccNum> eccVec;
847        DelayedSingleton<CellularCallRdbHelper>::GetInstance()->QueryEccList(hplmn, eccVec);
848        if (!eccVec.empty()) {
849            std::string ecc = eccVec[0].ecc_fake;
850            std::vector<std::string> callList = StandardizeUtils::Split(ecc, ",");
851            for (auto it : callList) {
852                EmergencyCall call = BuildDefaultEmergencyCall(it, SimpresentType::TYPE_HAS_CARD);
853                call.mcc = mcc;
854                tempEccList[slotId].push_back(call);
855            }
856        }
857    }
858    UniqueEccCallList(slotId, tempEccList[slotId]);
859}
860
861void CellularCallConfig::UniqueEccCallList(int32_t slotId, std::vector<EmergencyCall> &eccList)
862{
863    allEccList_[slotId].clear();
864    for (auto call : eccList) {
865        if (std::find(allEccList_[slotId].begin(), allEccList_[slotId].end(), call) ==
866            allEccList_[slotId].end()) {
867            allEccList_[slotId].push_back(call);
868        }
869    }
870    for (auto call : allEccList_[slotId]) {
871        TELEPHONY_LOGD("UniqueEccCallList end slotId %{public}d eccNum:%{public}s, mcc:%{public}s", slotId,
872            call.eccNum.c_str(), call.mcc.c_str());
873    }
874}
875
876std::string CellularCallConfig::GetMcc(int32_t slotId)
877{
878    std::u16string operatorNumeric;
879    CoreManagerInner::GetInstance().GetSimOperatorNumeric(slotId, operatorNumeric);
880    std::string imsi = Str16ToStr8(operatorNumeric);
881    int len = static_cast<int>(imsi.length());
882    std::string mcc = imsi;
883    if (len >= MCC_LEN) {
884        mcc = imsi.substr(0, MCC_LEN);
885    }
886    TELEPHONY_LOGD("getMcc slotd %{public}d mcc %{public}s end", slotId, mcc.c_str());
887    return mcc;
888}
889
890int32_t CellularCallConfig::SetMute(int32_t slotId, int32_t mute)
891{
892    return configRequest_.SetMuteRequest(slotId, mute);
893}
894
895int32_t CellularCallConfig::GetMute(int32_t slotId)
896{
897    return configRequest_.GetMuteRequest(slotId);
898}
899
900int32_t CellularCallConfig::GetEmergencyCallList(int32_t slotId)
901{
902    return configRequest_.GetEmergencyCallListRequest(slotId);
903}
904
905int32_t CellularCallConfig::SetEmergencyCallList(int32_t slotId, std::vector<EmergencyCall> &eccVec)
906{
907    TELEPHONY_LOGD("SetEmergencyCallList start %{public}d", slotId);
908    return configRequest_.SetEmergencyCallListRequest(slotId, eccVec);
909}
910
911bool CellularCallConfig::CheckAndUpdateSimState(int32_t slotId)
912{
913    SimState simState = SimState::SIM_STATE_UNKNOWN;
914    CoreManagerInner::GetInstance().GetSimState(slotId, simState);
915    int32_t simStateForEcc;
916    switch (simState) {
917        case SimState::SIM_STATE_READY:
918        case SimState::SIM_STATE_LOADED: {
919            simStateForEcc = SIM_PRESENT;
920            break;
921        }
922        default: {
923            simStateForEcc = SIM_ABSENT;
924            break;
925        }
926    }
927    std::lock_guard<std::mutex> lock(simStateLock_);
928    bool result = (simState_[slotId] != simStateForEcc);
929    simState_[slotId] = simStateForEcc;
930    return result;
931}
932
933void CellularCallConfig::UpdateEmergencyCallFromRadio(int32_t slotId, const EmergencyInfoList &eccList)
934{
935    TELEPHONY_LOGD("UpdateEmergencyCallFromRadio %{publid}d size %{public}d", slotId, eccList.callSize);
936    std::lock_guard<std::mutex> lock(mutex_);
937    eccListRadioMap_[slotId].clear();
938    for (auto ecc : eccList.calls) {
939        TELEPHONY_LOGD("UpdateEmergencyCallFromRadio , data: eccNum %{public}s mcc %{public}s", ecc.eccNum.c_str(),
940            ecc.mcc.c_str());
941        eccListRadioMap_[slotId].push_back(BuildEmergencyCall(slotId, ecc));
942    }
943    MergeEccCallList(slotId);
944}
945
946std::vector<EmergencyCall> CellularCallConfig::GetEccCallList(int32_t slotId)
947{
948    TELEPHONY_LOGD("GetEccCallList  start %{public}d", slotId);
949    std::lock_guard<std::mutex> lock(mutex_);
950    TELEPHONY_LOGD("GetEccCallList size %{public}zu", allEccList_[slotId].size());
951    for (auto ecc : allEccList_[slotId]) {
952        TELEPHONY_LOGD("GetEccCallList, data: eccNum %{public}s mcc %{public}s", ecc.eccNum.c_str(), ecc.mcc.c_str());
953    }
954    return allEccList_[slotId];
955}
956
957int32_t CellularCallConfig::BooleanToImsSwitchValue(bool value)
958{
959    return value ? IMS_SWITCH_STATUS_ON : IMS_SWITCH_STATUS_OFF;
960}
961
962bool CellularCallConfig::GetImsSwitchOnByDefaultConfig(int32_t slotId)
963{
964    if (!IsValidSlotId(slotId)) {
965        TELEPHONY_LOGE("invalid slot id");
966        return true;
967    }
968    return imsSwitchOnByDefault_[slotId];
969}
970
971bool CellularCallConfig::GethideImsSwitchConfig(int32_t slotId)
972{
973    if (!IsValidSlotId(slotId)) {
974        TELEPHONY_LOGE("invalid slot id");
975        return false;
976    }
977    return hideImsSwitch_[slotId];
978}
979
980bool CellularCallConfig::GetvolteSupportedConfig(int32_t slotId)
981{
982    if (!IsValidSlotId(slotId)) {
983        TELEPHONY_LOGE("invalid slot id");
984        return false;
985    }
986    return volteSupported_[slotId];
987}
988
989std::vector<int32_t> CellularCallConfig::GetNrModeSupportedListConfig(int32_t slotId)
990{
991    if (!IsValidSlotId(slotId)) {
992        TELEPHONY_LOGE("invalid slot id");
993        return std::vector<int32_t> { CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA };
994    }
995    return nrModeSupportedList_[slotId];
996}
997
998bool CellularCallConfig::GetVolteProvisioningSupportedConfig(int32_t slotId)
999{
1000    if (!IsValidSlotId(slotId)) {
1001        TELEPHONY_LOGE("invalid slot id");
1002        return false;
1003    }
1004    return volteProvisioningSupported_[slotId];
1005}
1006
1007bool CellularCallConfig::GetSsOverUtSupportedConfig(int32_t slotId)
1008{
1009    if (!IsValidSlotId(slotId)) {
1010        TELEPHONY_LOGE("invalid slot id");
1011        return false;
1012    }
1013    return ssOverUtSupported_[slotId];
1014}
1015
1016bool CellularCallConfig::GetImsGbaRequiredConfig(int32_t slotId)
1017{
1018    if (!IsValidSlotId(slotId)) {
1019        TELEPHONY_LOGE("invalid slot id");
1020        return false;
1021    }
1022    return imsGbaRequired_[slotId];
1023}
1024
1025bool CellularCallConfig::GetUtProvisioningSupportedConfig(int32_t slotId)
1026{
1027    if (!IsValidSlotId(slotId)) {
1028        TELEPHONY_LOGE("invalid slot id");
1029        return false;
1030    }
1031    return utProvisioningSupported_[slotId];
1032}
1033
1034bool CellularCallConfig::GetImsPreferForEmergencyConfig(int32_t slotId)
1035{
1036    if (!IsValidSlotId(slotId)) {
1037        TELEPHONY_LOGE("invalid slot id");
1038        return true;
1039    }
1040    return imsPreferForEmergency_[slotId];
1041}
1042
1043std::int32_t CellularCallConfig::GetCallWaitingServiceClassConfig(int32_t slotId)
1044{
1045    if (!IsValidSlotId(slotId)) {
1046        TELEPHONY_LOGE("invalid slot id");
1047        return 1;
1048    }
1049    return callWaitingServiceClass_[slotId];
1050}
1051
1052std::vector<std::string> CellularCallConfig::GetImsCallDisconnectResoninfoMappingConfig(int32_t slotId)
1053{
1054    std::lock_guard<std::mutex> lock(operatorMutex_);
1055    if (!IsValidSlotId(slotId)) {
1056        TELEPHONY_LOGE("invalid slot id");
1057        return std::vector<std::string> {};
1058    }
1059    return imsCallDisconnectResoninfoMapping_[slotId];
1060}
1061
1062bool CellularCallConfig::GetForceVolteSwitchOnConfig(int32_t slotId)
1063{
1064    if (!IsValidSlotId(slotId)) {
1065        TELEPHONY_LOGE("invalid slot id");
1066        return false;
1067    }
1068    return forceVolteSwitchOn_[slotId];
1069}
1070
1071bool CellularCallConfig::IsValidSlotId(int32_t slotId)
1072{
1073    int32_t count = SIM_SLOT_COUNT;
1074    if ((slotId >= DEFAULT_SIM_SLOT_ID) && (slotId < count)) {
1075        return true;
1076    }
1077
1078    TELEPHONY_LOGE("SlotId is InValid = %{public}d", slotId);
1079    return false;
1080}
1081
1082void CellularCallConfig::SetReadyToCall(int32_t slotId, bool isReadyToCall)
1083{
1084    if (!IsValidSlotId(slotId)) {
1085        TELEPHONY_LOGE("invalid slot id");
1086        return;
1087    }
1088    readyToCall_[slotId] = isReadyToCall;
1089}
1090
1091bool CellularCallConfig::IsReadyToCall(int32_t slotId)
1092{
1093    if (!IsValidSlotId(slotId)) {
1094        TELEPHONY_LOGE("invalid slot id");
1095        return false;
1096    }
1097    return readyToCall_[slotId];
1098}
1099
1100bool CellularCallConfig::NeedReadThirdParyLib()
1101{
1102    std::string readThirdParty = system::GetParameter(KEY_CONST_TELEPHONY_READ_THIRD_PARTY_LIB, "");
1103    if (readThirdParty.compare("false") == 0) {
1104        return false;
1105    }
1106    return true;
1107}
1108} // namespace Telephony
1109} // namespace OHOS
1110