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_supplement.h"
17
18#include "cellular_call_register.h"
19#include "cellular_call_service.h"
20#include "ims_error.h"
21#include "mmi_code_message.h"
22#include "securec.h"
23#include "standardize_utils.h"
24#include "telephony_log_wrapper.h"
25
26namespace OHOS {
27namespace Telephony {
28const int32_t ACTIVATE_ACTION = 1;
29const int32_t DEACTIVATE_ACTION = 2;
30const int32_t USSD_MODE_NOTIFY = 0;
31const int32_t USSD_MODE_REQUEST = 1;
32const int32_t USSD_MODE_NW_RELEASE = 2;
33const int32_t USSD_SUCCESS = 0;
34const int32_t USSD_FAILED = 1;
35const int32_t RESULT_SUCCESS = 0;
36const int32_t MMI_CODE_FAILED = 1;
37const int32_t PIN_PUK_MIN = 4;
38const int32_t PIN_PUK_MAX = 8;
39const std::string BARR_ALL_OUTGOING_CALLS = "AO";
40const std::string BARR_OUTGOING_INTERNATIONAL_CALLS = "OI";
41const std::string BARR_OUTGOING_INTERNATIONAL_CALLS_EXCLUDING_HOME = "OX";
42const std::string BARR_ALL_INCOMING_CALLS = "AI";
43const std::string BARR_INCOMING_CALLS_OUTSIDE_HOME = "IR";
44const std::string ALL_BARRING_SERVICES = "AB";
45const std::string ALL_OUTGOING_BARRING_SERVICES = "AG";
46const std::string ALL_INCOMING_BARRING_SERVICES = "AC";
47
48constexpr unsigned long long operator"" _hash(char const *p, size_t s)
49{
50    return StandardizeUtils::HashCompileTime(p);
51}
52
53void CellularCallSupplement::HandleClip(int32_t slotId, const MMIData &mmiData)
54{
55    const std::string interrogate = "*#";
56    const std::string activate = "*";
57    const std::string deactivate = "#";
58    if (mmiData.actionString.empty()) {
59        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
60        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
61        return;
62    }
63    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
64    if (handler == nullptr) {
65        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
66        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
67        return;
68    }
69    int32_t result = TELEPHONY_ERROR;
70    auto utCommand = std::make_shared<SsRequestCommand>();
71    int32_t index;
72    handler->RequestSsRequestCommandIndex(index);
73    if (mmiData.actionString == activate) {
74        utCommand->action = ACTIVATE_ACTION;
75        result = supplementRequestIms_.SetClipRequest(slotId, ACTIVATE_ACTION, index);
76    } else if (mmiData.actionString == deactivate) {
77        utCommand->action = DEACTIVATE_ACTION;
78        result = supplementRequestIms_.SetClipRequest(slotId, DEACTIVATE_ACTION, index);
79    } else if (mmiData.actionString == interrogate) {
80        if (NeedUseImsToHandle(slotId)) {
81            result = supplementRequestIms_.GetClipRequest(slotId, index);
82        } else {
83            result = supplementRequestCs_.GetClipRequest(slotId, index);
84        }
85    }
86    if (result != TELEPHONY_SUCCESS) {
87        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
88    } else {
89        handler->SaveSsRequestCommand(utCommand, index);
90    }
91}
92
93void CellularCallSupplement::HandleClir(int32_t slotId, const MMIData &mmiData)
94{
95    const std::string interrogate = "*#";
96    const std::string activate = "*";
97    const std::string deactivate = "#";
98    if (mmiData.actionString.empty()) {
99        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
100        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
101        return;
102    }
103    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
104    if (handler == nullptr) {
105        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
106        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
107        return;
108    }
109    int32_t result = TELEPHONY_ERROR;
110    auto utCommand = std::make_shared<SsRequestCommand>();
111    int32_t index;
112    handler->RequestSsRequestCommandIndex(index);
113    if (mmiData.actionString == activate) {
114        utCommand->action = ACTIVATE_ACTION;
115        if (NeedUseImsToHandle(slotId)) {
116            result = supplementRequestIms_.SetClirRequest(slotId, ACTIVATE_ACTION, index);
117        } else {
118            result = supplementRequestCs_.SetClirRequest(slotId, ACTIVATE_ACTION, index);
119        }
120    } else if (mmiData.actionString == deactivate) {
121        utCommand->action = DEACTIVATE_ACTION;
122        if (NeedUseImsToHandle(slotId)) {
123            result = supplementRequestIms_.SetClirRequest(slotId, DEACTIVATE_ACTION, index);
124        } else {
125            result = supplementRequestCs_.SetClirRequest(slotId, DEACTIVATE_ACTION, index);
126        }
127    } else if (mmiData.actionString == interrogate) {
128        if (NeedUseImsToHandle(slotId)) {
129            result = supplementRequestIms_.GetClirRequest(slotId, index);
130        } else {
131            result = supplementRequestCs_.GetClirRequest(slotId, index);
132        }
133    }
134    if (result != TELEPHONY_SUCCESS) {
135        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
136    } else {
137        handler->SaveSsRequestCommand(utCommand, index);
138    }
139}
140
141void CellularCallSupplement::HandleColr(int32_t slotId, const MMIData &mmiData)
142{
143    const std::string interrogate = "*#";
144    const std::string activate = "*";
145    const std::string deactivate = "#";
146    if (mmiData.actionString.empty()) {
147        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
148        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
149        return;
150    }
151    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
152    if (handler == nullptr) {
153        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
154        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
155        return;
156    }
157    int32_t result = TELEPHONY_ERROR;
158    auto utCommand = std::make_shared<SsRequestCommand>();
159    int32_t index;
160    handler->RequestSsRequestCommandIndex(index);
161    if (mmiData.actionString == activate) {
162        utCommand->action = ACTIVATE_ACTION;
163        if (NeedUseImsToHandle(slotId)) {
164            result = supplementRequestIms_.SetColrRequest(slotId, ACTIVATE_ACTION, index);
165        }
166    } else if (mmiData.actionString == deactivate) {
167        utCommand->action = DEACTIVATE_ACTION;
168        if (NeedUseImsToHandle(slotId)) {
169            result = supplementRequestIms_.SetColrRequest(slotId, DEACTIVATE_ACTION, index);
170        }
171    } else if (mmiData.actionString == interrogate) {
172        if (NeedUseImsToHandle(slotId)) {
173            result = supplementRequestIms_.GetColrRequest(slotId, index);
174        }
175    }
176    if (result != TELEPHONY_SUCCESS) {
177        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
178    } else {
179        handler->SaveSsRequestCommand(utCommand, index);
180    }
181}
182
183void CellularCallSupplement::HandleColp(int32_t slotId, const MMIData &mmiData)
184{
185    const std::string interrogate = "*#";
186    const std::string activate = "*";
187    const std::string deactivate = "#";
188    if (mmiData.actionString.empty()) {
189        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
190        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
191        return;
192    }
193    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
194    if (handler == nullptr) {
195        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
196        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
197        return;
198    }
199    int32_t result = TELEPHONY_ERROR;
200    auto utCommand = std::make_shared<SsRequestCommand>();
201    int32_t index;
202    handler->RequestSsRequestCommandIndex(index);
203    if (mmiData.actionString == activate) {
204        utCommand->action = ACTIVATE_ACTION;
205        if (NeedUseImsToHandle(slotId)) {
206            result = supplementRequestIms_.SetColpRequest(slotId, ACTIVATE_ACTION, index);
207        }
208    } else if (mmiData.actionString == deactivate) {
209        utCommand->action = DEACTIVATE_ACTION;
210        if (NeedUseImsToHandle(slotId)) {
211            result = supplementRequestIms_.SetColpRequest(slotId, DEACTIVATE_ACTION, index);
212        }
213    } else if (mmiData.actionString == interrogate) {
214        if (NeedUseImsToHandle(slotId)) {
215            result = supplementRequestIms_.GetColpRequest(slotId, index);
216        }
217    }
218    if (result != TELEPHONY_SUCCESS) {
219        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
220    } else {
221        handler->SaveSsRequestCommand(utCommand, index);
222    }
223}
224
225void CellularCallSupplement::HandleCallTransfer(int32_t slotId, const MMIData &mmiData)
226{
227    const std::string interrogate = "*#";
228    int32_t serviceCode = ObtainServiceCode(mmiData.serviceInfoB);
229    int32_t cause = ObtainCause(mmiData.serviceCode);
230    if (!mmiData.actionString.empty() && mmiData.actionString == interrogate) {
231        HandleGetCallTransfer(slotId, cause);
232        return;
233    }
234    std::string phoneNumber = mmiData.serviceInfoA;
235    if (mmiData.actionString.empty()) {
236        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
237        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
238        return;
239    }
240    CallTransferSettingType callTransferAction;
241    int32_t result = ObtainCallTrasferAction(mmiData.actionString.c_str(), phoneNumber, callTransferAction);
242    if (result != TELEPHONY_SUCCESS) {
243        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
244        return;
245    }
246    HandleSetCallTransfer(slotId, serviceCode, cause, phoneNumber, callTransferAction);
247}
248
249int32_t CellularCallSupplement::ObtainServiceCode(const std::string &serviceInfoB)
250{
251    if (serviceInfoB.empty()) {
252        TELEPHONY_LOGI("serviceInfoB is empty!");
253        return NONE;
254    }
255    int32_t intServiceInfoB = atoi(serviceInfoB.c_str());
256    switch (intServiceInfoB) {
257        case ALL_TELE_SERVICES:
258            return SHORT_MESSAGE_SERVICE + FAX + VOICE;
259        case TELE_SERVICES:
260            return VOICE;
261        case ALL_DATA_TELE_SERVICES:
262            return SHORT_MESSAGE_SERVICE + FAX;
263        case FACSIMILE_SERVICES:
264            return FAX;
265        case SHORT_MESSAGE_SERVICES:
266            return SHORT_MESSAGE_SERVICE;
267        case ALL_TELE_SERVICES_EXCEPT_SMS:
268            return FAX + VOICE;
269        case ALL_BEARER_SERVICES:
270            return DATA_CIRCUIT_ASYNC + DATA_CIRCUIT_SYNC;
271        case ALL_ASYNC_SERVICES:
272            return DEDICATED_PAD_ACCESS + DATA_CIRCUIT_ASYNC;
273        case ALL_SYNC_SERVICES:
274            return DEDICATED_PACKET_ACCESS + DATA_CIRCUIT_SYNC;
275        case ALL_DATA_CIRCUIT_SYNC:
276            return DATA_CIRCUIT_SYNC;
277        case ALL_DATA_CIRCUIT_ASYNC:
278            return DATA_CIRCUIT_ASYNC;
279        case ALL_GPRS_BEARER_SERVICES:
280            return DEDICATED_PACKET_ACCESS;
281        default:
282            TELEPHONY_LOGE("serviceInfoB out of range, please check!");
283            return NONE;
284    }
285}
286
287int32_t CellularCallSupplement::ObtainCallTrasferAction(
288    const char *actionString, const std::string &phoneNumber, CallTransferSettingType &callTransferAction)
289{
290    // 3GPP TS 24.082 V4.0.0 (2001-03) 1 Call Forwarding Unconditional (CFU)
291    // 3GPP TS 24.082 V4.0.0 (2001-03) 2 Call Forwarding on mobile subscriber Busy (CFB)
292    // 3GPP TS 24.082 V4.0.0 (2001-03) 3 Call Forwarding on No Reply (CFNRy)
293    // 3GPP TS 24.082 V4.0.0 (2001-03) 4 Call Forwarding on mobile subscriber Not Reachable (CFNRc)
294    switch (StandardizeUtils::Hash_(actionString)) {
295        case "*"_hash:
296            if (phoneNumber.empty()) {
297                callTransferAction = CallTransferSettingType::CALL_TRANSFER_ENABLE;
298            } else {
299                callTransferAction = CallTransferSettingType::CALL_TRANSFER_REGISTRATION;
300            }
301            break;
302        case "#"_hash:
303            callTransferAction = CallTransferSettingType::CALL_TRANSFER_DISABLE;
304            break;
305        case "**"_hash:
306            callTransferAction = CallTransferSettingType::CALL_TRANSFER_REGISTRATION;
307            break;
308        case "##"_hash:
309            callTransferAction = CallTransferSettingType::CALL_TRANSFER_ERASURE;
310            break;
311        default:
312            TELEPHONY_LOGE("actionString out of range, please check!");
313            return TELEPHONY_ERR_ARGUMENT_MISMATCH;
314    }
315    return TELEPHONY_SUCCESS;
316}
317
318int32_t CellularCallSupplement::ObtainCause(const std::string &actionStr)
319{
320    if (actionStr.empty()) {
321        TELEPHONY_LOGE("actionStr is empty!");
322        return TELEPHONY_ERROR;
323    }
324
325    /*
326     * 3GPP TS 22.030 V4.0.0 (2001-03) Annex B (normative): Codes for defined Supplementary Services
327     * CFU	                21
328     * CF Busy	            67
329     * CF No Reply	        61
330     * CF Not Reachable 	62
331     * all CF		        002
332     * all conditional CF	004
333     */
334    switch (StandardizeUtils::Hash_(actionStr.c_str())) {
335        case "21"_hash:
336            return static_cast<int32_t>(CallTransferType::TRANSFER_TYPE_UNCONDITIONAL);
337        case "67"_hash:
338            return static_cast<int32_t>(CallTransferType::TRANSFER_TYPE_BUSY);
339        case "61"_hash:
340            return static_cast<int32_t>(CallTransferType::TRANSFER_TYPE_NO_REPLY);
341        case "62"_hash:
342            return static_cast<int32_t>(CallTransferType::TRANSFER_TYPE_NOT_REACHABLE);
343        default:
344            TELEPHONY_LOGE("actionStr out of range!");
345            return TELEPHONY_ERROR;
346    }
347}
348
349void CellularCallSupplement::HandleGetCallTransfer(int32_t slotId, int32_t cause)
350{
351    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
352    if (handler == nullptr) {
353        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
354        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
355        return;
356    }
357    auto utCommand = std::make_shared<SsRequestCommand>();
358    utCommand->cfReason = cause;
359    int32_t index;
360    handler->RequestSsRequestCommandIndex(index);
361    int32_t result = TELEPHONY_ERROR;
362    if (NeedUseImsToHandle(slotId)) {
363        result = supplementRequestIms_.GetCallTransferRequest(slotId, cause, index);
364    } else {
365        result = supplementRequestCs_.GetCallTransferRequest(slotId, cause, index);
366    }
367    if (result != TELEPHONY_SUCCESS) {
368        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
369    } else {
370        handler->SaveSsRequestCommand(utCommand, index);
371    }
372}
373
374void CellularCallSupplement::HandleSetCallTransfer(int32_t slotId, int32_t serviceCode, int32_t cause,
375    const std::string &phoneNumber, CallTransferSettingType callTransferAction)
376{
377    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
378    if (handler == nullptr) {
379        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
380        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
381        return;
382    }
383    auto utCommand = std::make_shared<SsRequestCommand>();
384    utCommand->cfReason = cause;
385    utCommand->cfAction = static_cast<int32_t>(callTransferAction);
386    utCommand->number = phoneNumber;
387    int32_t index;
388    handler->RequestSsRequestCommandIndex(index);
389    int32_t result = TELEPHONY_ERROR;
390    if (NeedUseImsToHandle(slotId)) {
391        CallTransferInfo cfInfo;
392        if (memcpy_s(cfInfo.transferNum, kMaxNumberLen, phoneNumber.c_str(), phoneNumber.length()) != EOK) {
393            TELEPHONY_LOGE("[slot%{public}d] memcpy_s failed!", slotId);
394            ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
395            return;
396        }
397        cfInfo.settingType = callTransferAction;
398        cfInfo.type = static_cast<CallTransferType>(cause);
399        // set the time as default min, this mean the time will not use at IMS
400        cfInfo.startHour = MIN_HOUR;
401        cfInfo.startMinute = MIN_MINUTE;
402        cfInfo.endHour = MIN_HOUR;
403        cfInfo.endMinute = MIN_MINUTE;
404        result = supplementRequestIms_.SetCallTransferRequest(slotId, cfInfo, serviceCode, index);
405    } else {
406        CallTransferParam callTransferParam;
407        callTransferParam.mode = static_cast<int32_t>(callTransferAction);
408        callTransferParam.reason = cause;
409        callTransferParam.number = phoneNumber;
410        callTransferParam.classx = serviceCode;
411        result = supplementRequestCs_.SetCallTransferRequest(slotId, callTransferParam, index);
412    }
413    if (result != TELEPHONY_SUCCESS) {
414        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
415    } else {
416        handler->SaveSsRequestCommand(utCommand, index);
417    }
418}
419
420void CellularCallSupplement::HandleCallRestriction(int32_t slotId, const MMIData &mmiData)
421{
422    std::string infoA = mmiData.serviceInfoA;
423    std::string facType = ObtainBarringInstallation(mmiData.serviceCode);
424    const std::string interrogate = "*#";
425    const std::string activate = "*";
426    const std::string deactivate = "#";
427    if (mmiData.actionString.empty()) {
428        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
429        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
430        return;
431    }
432    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
433    if (handler == nullptr) {
434        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
435        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
436        return;
437    }
438    auto utCommand = std::make_shared<SsRequestCommand>();
439    utCommand->facility = facType;
440    int32_t index;
441    handler->RequestSsRequestCommandIndex(index);
442    int32_t result = TELEPHONY_ERROR;
443    if (mmiData.actionString == interrogate) {
444        if (NeedUseImsToHandle(slotId)) {
445            result = supplementRequestIms_.GetCallRestrictionRequest(slotId, facType, index);
446        } else {
447            result = supplementRequestCs_.GetCallRestrictionRequest(slotId, facType, index);
448        }
449    } else if (mmiData.actionString == activate || mmiData.actionString == deactivate) {
450        utCommand->enable = mmiData.actionString == activate;
451        size_t cpyLen = strlen(infoA.c_str()) + 1;
452        size_t maxCpyLen = sizeof(utCommand->password);
453        if (strcpy_s(utCommand->password, cpyLen > maxCpyLen ? maxCpyLen : cpyLen, infoA.c_str()) != EOK) {
454            TELEPHONY_LOGE("[slot%{public}d] strcpy_s fail.", slotId);
455            return;
456        }
457        if (NeedUseImsToHandle(slotId)) {
458            result = supplementRequestIms_.SetCallRestrictionRequest(
459                slotId, facType, mmiData.actionString == activate, infoA, index);
460        } else {
461            result = supplementRequestCs_.SetCallRestrictionRequest(
462                slotId, facType, mmiData.actionString == activate, infoA, index);
463        }
464    }
465    if (result != TELEPHONY_SUCCESS) {
466        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
467    } else {
468        handler->SaveSsRequestCommand(utCommand, index);
469    }
470}
471
472std::string CellularCallSupplement::ObtainBarringInstallation(const std::string &serviceInfoC)
473{
474    if (serviceInfoC.empty()) {
475        TELEPHONY_LOGE("serviceInfoC is empty!");
476        return std::string();
477    }
478
479    /*
480     * 27007-430_2001 7.4	Facility lock +CLCK
481     *  Supplementary	Service Service	Code	SIA	SIB	SIC
482     * 	22.088
483     * 	BAOC	            33	                 PW	BS	-
484     * 	BAOIC	            331	                 PW	BS	-
485     * 	BAOIC exc home	    332	                 PW	BS	-
486     * 	BAIC	            35	                 PW	BS	-
487     * 	BAIC roaming	    351	                 PW	BS	-
488     *  all Barring Serv.   330	                 PW	BS	-
489     *  Outg. Barr. Serv.   333	                 PW	BS
490     *  Inc. Barr. Serv.	353	                 PW	BS
491     */
492    switch (StandardizeUtils::Hash_(serviceInfoC.c_str())) {
493        case "33"_hash:
494            // "AO"	BAOC (Barr All Outgoing Calls) (refer 3GPP TS 22.088 [6] clause 1)
495            return BARR_ALL_OUTGOING_CALLS;
496        case "331"_hash:
497            // "OI"	BOIC (Barr Outgoing International Calls) (refer 3GPP TS 22.088 [6] clause 1)
498            return BARR_OUTGOING_INTERNATIONAL_CALLS;
499        case "332"_hash:
500            // "OX"	BOIC exHC (Barr Outgoing International Calls except to Home Country)
501            // (refer 3GPP TS 22.088 [6] clause 1)
502            return BARR_OUTGOING_INTERNATIONAL_CALLS_EXCLUDING_HOME;
503        case "351"_hash:
504            // "IR"	BIC Roam (Barr Incoming Calls when Roaming outside the home country)
505            // (refer 3GPP TS 22.088 [6] clause 2)
506            return BARR_INCOMING_CALLS_OUTSIDE_HOME;
507        case "35"_hash:
508            // "AI"	BAIC (Barr All Incoming Calls) (refer 3GPP TS 22.088 [6] clause 2)
509            return BARR_ALL_INCOMING_CALLS;
510        case "330"_hash:
511            // "AB"	All Barring services (refer 3GPP TS 22.030 [19]) (applicable only for <mode>=0)
512            return ALL_BARRING_SERVICES;
513        case "333"_hash:
514            // "AG"	All outGoing barring services (refer 3GPP TS 22.030 [19]) (applicable only for <mode>=0)
515            return ALL_OUTGOING_BARRING_SERVICES;
516        case "353"_hash:
517            // "AC"	All inComing barring services (refer 3GPP TS 22.030 [19]) (applicable only for <mode>=0)
518            return ALL_INCOMING_BARRING_SERVICES;
519        default:
520            TELEPHONY_LOGE("serviceInfoC out of range!");
521            return std::string();
522    }
523}
524
525void CellularCallSupplement::HandleCallWaiting(int32_t slotId, const MMIData &mmiData)
526{
527    if (mmiData.actionString.empty()) {
528        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVALID_MMI_CODE);
529        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
530        return;
531    }
532    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
533    if (handler == nullptr) {
534        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
535        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
536        return;
537    }
538    const std::string activate = "*";
539    const std::string deactivate = "#";
540    const std::string interrogate = "*#";
541    int32_t result = TELEPHONY_ERROR;
542    int32_t classType = ObtainServiceCode(mmiData.serviceInfoA);
543    auto utCommand = std::make_shared<SsRequestCommand>();
544    utCommand->classType = classType;
545    int32_t index;
546    handler->RequestSsRequestCommandIndex(index);
547    if (mmiData.actionString == activate || mmiData.actionString == deactivate) {
548        utCommand->enable = mmiData.actionString == activate;
549        if (NeedUseImsToHandle(slotId)) {
550            result =
551                supplementRequestIms_.SetCallWaitingRequest(slotId, mmiData.actionString == activate, classType, index);
552        } else {
553            result =
554                supplementRequestCs_.SetCallWaitingRequest(slotId, mmiData.actionString == activate, classType, index);
555        }
556    } else if (mmiData.actionString == interrogate) {
557        if (NeedUseImsToHandle(slotId)) {
558            result = supplementRequestIms_.GetCallWaitingRequest(slotId, index);
559        } else {
560            result = supplementRequestCs_.GetCallWaitingRequest(slotId, index);
561        }
562    }
563    if (result != TELEPHONY_SUCCESS) {
564        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
565    } else {
566        handler->SaveSsRequestCommand(utCommand, index);
567    }
568}
569
570void CellularCallSupplement::EventGetCallWaiting(
571    const CallWaitResult &waitingInfo, const std::string &message, int32_t flag)
572{
573    CallWaitResponse callWaitResponse;
574    callWaitResponse.result = waitingInfo.result.result;
575    if (callWaitResponse.result == IMS_ERROR_UT_NO_CONNECTION) {
576        callWaitResponse.result = CALL_ERR_UT_NO_CONNECTION;
577    }
578
579    /*
580     * <n> (sets/shows the result code presentation status in the TA):
581     * 0	disable
582     * 1	enable
583     */
584    callWaitResponse.status = waitingInfo.status;
585    callWaitResponse.classCw = waitingInfo.classCw;
586    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
587    if (callRegister == nullptr) {
588        TELEPHONY_LOGE("callRegister is null.");
589        return;
590    }
591    if (flag == SS_FROM_MMI_CODE) {
592        std::string successMessage = GET_CALL_WAITING_SUCCESS;
593        CreateGetCallWaitingResultMessage(successMessage, callWaitResponse);
594        ReportMmiCodeMessage(
595            callWaitResponse.result, successMessage, message.empty() ? GET_CALL_WAITING_FAILED : message);
596    } else {
597        callRegister->ReportGetWaitingResult(callWaitResponse);
598    }
599}
600
601void CellularCallSupplement::EventSetCallWaiting(int32_t result, const std::string &message, int32_t flag)
602{
603    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
604    if (callRegister == nullptr) {
605        TELEPHONY_LOGE("callRegister is null.");
606        return;
607    }
608    if (flag == SS_FROM_MMI_CODE) {
609        ReportMmiCodeMessage(result, SET_CALL_WAITING_SUCCESS, message.empty() ? SET_CALL_WAITING_FAILED : message);
610    } else {
611        callRegister->ReportSetWaitingResult(result);
612    }
613}
614
615void CellularCallSupplement::EventGetCallTransferInfo(
616    const CallForwardQueryInfoList &cFQueryList, const std::string &message, int32_t flag)
617{
618    if (cFQueryList.result.result != TELEPHONY_SUCCESS && cFQueryList.callSize == 0) {
619        CallForwardQueryResult failResult;
620        failResult.result = cFQueryList.result.result;
621        failResult.reason = cFQueryList.result.reason;
622        BuildCallForwardQueryInfo(failResult, message, flag);
623    }
624    for (auto queryResult : cFQueryList.calls) {
625        TELEPHONY_LOGI("data: status %{public}d, classx %{public}d, reason %{public}d", queryResult.status,
626            queryResult.classx, queryResult.reason);
627        if (queryResult.classx > 0 && (static_cast<uint32_t>(queryResult.classx) & ServiceClassType::VOICE) != 0) {
628            BuildCallForwardQueryInfo(queryResult, message, flag);
629        }
630    }
631}
632
633void CellularCallSupplement::BuildCallForwardQueryInfo(
634    const CallForwardQueryResult &queryResult, const std::string &message, int32_t flag)
635{
636    // 3GPP TS 27.007 V3.9.0 (2001-06) 7.11	Call forwarding number and conditions +CCFC
637    CallTransferResponse response;
638    if (memset_s(&response, sizeof(response), 0, sizeof(response)) != EOK) {
639        TELEPHONY_LOGE("memset_s fail.");
640        return;
641    }
642    // <number>: string type phone number of forwarding address in format specified by <type>
643    if (strcpy_s(response.number, sizeof(response.number), queryResult.number.c_str()) != EOK) {
644        TELEPHONY_LOGE(" strcpy_s fail.");
645        return;
646    }
647    response.result = queryResult.result;
648    /*
649     * <status>:0	not active;    1	  active
650     * */
651    response.status = queryResult.status;
652    /*
653     * <classx> is a sum of integers each representing a class of information (default 7):
654     * 1	voice (telephony)
655     * 2	data (refers to all bearer services)
656     * 4	fax (facsimile services)
657     * 8	short message service
658     * 16	data circuit sync
659     * 32	data circuit async
660     * 64	dedicated packet access
661     * 128	dedicated PAD access
662     */
663    response.classx = queryResult.classx;
664    // <type>: type of address octet in integer format (refer GSM 04.08 [8] subclause 10.5.4.7);
665    // default 145 when dialling string includes international access code character "+", otherwise 129
666    response.type = queryResult.type;
667    response.reason = queryResult.reason;
668    response.time = queryResult.time;
669    response.startHour = queryResult.startHour;
670    response.startMinute = queryResult.startMinute;
671    response.endHour = queryResult.endHour;
672    response.endMinute = queryResult.endMinute;
673    if (flag == SS_FROM_MMI_CODE) {
674        std::string successMessage = GET_CALL_TRANSFER_SUCCESS;
675        CreateGetCallTransferResultMessage(successMessage, response);
676        ReportMmiCodeMessage(queryResult.result, successMessage, message.empty() ? GET_CALL_TRANSFER_FAILED : message);
677    } else {
678        auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
679        if (callRegister == nullptr) {
680            TELEPHONY_LOGE("callRegister is null.");
681            return;
682        }
683        callRegister->ReportGetTransferResult(response);
684    }
685}
686
687void CellularCallSupplement::EventSetCallTransferInfo(int32_t result, const std::string &message, int32_t flag)
688{
689    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
690    if (callRegister == nullptr) {
691        TELEPHONY_LOGE("callRegister is null.");
692        return;
693    }
694
695    if (flag == SS_FROM_MMI_CODE) {
696        ReportMmiCodeMessage(result, SET_CALL_TRANSFER_SUCCESS, message.empty() ? SET_CALL_TRANSFER_FAILED : message);
697    } else {
698        callRegister->ReportSetTransferResult(result);
699    }
700}
701
702void CellularCallSupplement::EventGetCallRestriction(
703    const CallRestrictionResult &result, const std::string &message, int32_t flag)
704{
705    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
706    if (callRegister == nullptr) {
707        TELEPHONY_LOGE("callRegister is null.");
708        return;
709    }
710    CallRestrictionResponse response;
711    response.result = result.result.result;
712    if (response.result == IMS_ERROR_UT_NO_CONNECTION) {
713        response.result = CALL_ERR_UT_NO_CONNECTION;
714    }
715
716    /*
717     * <status>:0	not active    1	  active
718     */
719    response.status = result.status;
720    response.classCw = result.classCw;
721
722    if (flag == SS_FROM_MMI_CODE) {
723        std::string successMessage = GET_CALL_RESTRICTION_SUCCESS;
724        CreateSuppSvcQueryResultMessage(successMessage, response.result, response.status);
725        ReportMmiCodeMessage(
726            result.result.result, successMessage, message.empty() ? GET_CALL_RESTRICTION_FAILED : message);
727    } else {
728        callRegister->ReportGetRestrictionResult(response);
729    }
730}
731
732void CellularCallSupplement::EventSetCallRestriction(int32_t result, const std::string &message, int32_t flag)
733{
734    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
735    if (callRegister == nullptr) {
736        TELEPHONY_LOGE("callRegister is null.");
737        return;
738    }
739    if (flag == SS_FROM_MMI_CODE) {
740        ReportMmiCodeMessage(
741            result, SET_CALL_RESTRICTION_SUCCESS, message.empty() ? SET_CALL_RESTRICTION_FAILED : message);
742    } else {
743        callRegister->ReportSetRestrictionResult(result);
744    }
745}
746
747void CellularCallSupplement::EventSetBarringPassword(int32_t result, const std::string &message, int32_t flag)
748{
749    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
750    if (callRegister == nullptr) {
751        TELEPHONY_LOGE("callRegister is null.");
752        return;
753    }
754    if (flag == SS_FROM_MMI_CODE) {
755        ReportMmiCodeMessage(
756            result, SET_SET_BARRING_PASSWORD_SUCCESS, message.empty() ? SET_SET_BARRING_PASSWORD_FAILED : message);
757    } else {
758        callRegister->ReportSetBarringPasswordResult(result);
759    }
760}
761
762int32_t CellularCallSupplement::SetCallTransferInfo(int32_t slotId, const CallTransferInfo &cfInfo)
763{
764    int32_t result = CheckSetCallTransferInfo(cfInfo);
765    RadioResponseInfo responseInfo;
766    responseInfo.error = ErrType::ERR_GENERIC_FAILURE;
767    if (result != TELEPHONY_SUCCESS) {
768        return result;
769    }
770    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
771    if (handler == nullptr) {
772        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
773        return TELEPHONY_ERR_LOCAL_PTR_NULL;
774    }
775
776    std::string dialString(cfInfo.transferNum);
777    auto utCommand = std::make_shared<SsRequestCommand>();
778    utCommand->flag = SS_FROM_SETTING_MENU;
779    utCommand->number = dialString;
780    utCommand->cfAction = static_cast<int32_t>(cfInfo.settingType);
781    utCommand->cfReason = static_cast<int32_t>(cfInfo.type);
782    utCommand->classType = ServiceClassType::VOICE;
783    if (NeedUseImsToHandle(slotId)) {
784        return SetCallTransferInfoByIms(slotId, cfInfo, utCommand);
785    }
786
787    if (!PhoneTypeGsmOrNot(slotId)) {
788        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
789        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
790    }
791
792    CallTransferParam callTransferParam;
793    callTransferParam.mode = static_cast<int32_t>(cfInfo.settingType);
794    callTransferParam.reason = static_cast<int32_t>(cfInfo.type);
795    callTransferParam.number = dialString;
796    callTransferParam.classx = ServiceClassType::VOICE;
797    int32_t index;
798    handler->RequestSsRequestCommandIndex(index);
799    result = supplementRequestCs_.SetCallTransferRequest(slotId, callTransferParam, index);
800    if (result == TELEPHONY_SUCCESS) {
801        handler->SaveSsRequestCommand(utCommand, index);
802    }
803    return result;
804}
805
806int32_t CellularCallSupplement::CheckSetCallTransferInfo(const CallTransferInfo &cfInfo)
807{
808    if (strlen(cfInfo.transferNum) == 0) {
809        TELEPHONY_LOGE("transferNum is empty!");
810        return TELEPHONY_ERR_ARGUMENT_INVALID;
811    }
812
813    /*
814     * <reason>:
815     * 0   unconditional
816     * 1   mobile busy
817     * 2   no reply
818     * 3   not reachable
819     * 4   all call forwarding (refer 3GPP TS 22.030 [19])
820     * 5   all conditional call forwarding (refer 3GPP TS 22.030 [19])
821     * <mode>:
822     * 0   disable
823     * 1   enable
824     * 2   query status
825     * 3   registration
826     * 4   erasure
827     */
828    if (cfInfo.type > CallTransferType::TRANSFER_TYPE_NOT_REACHABLE ||
829        cfInfo.type < CallTransferType::TRANSFER_TYPE_UNCONDITIONAL ||
830        cfInfo.settingType > CallTransferSettingType::CALL_TRANSFER_ERASURE ||
831        cfInfo.settingType < CallTransferSettingType::CALL_TRANSFER_DISABLE) {
832        TELEPHONY_LOGE("parameter out of range!");
833        return CALL_ERR_PARAMETER_OUT_OF_RANGE;
834    }
835    return TELEPHONY_SUCCESS;
836}
837
838int32_t CellularCallSupplement::SetCallTransferInfoByIms(
839    int32_t slotId, const CallTransferInfo &cfInfo, const std::shared_ptr<SsRequestCommand> &command)
840{
841    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
842    RadioResponseInfo responseInfo;
843    responseInfo.error = ErrType::ERR_GENERIC_FAILURE;
844    if (handler == nullptr) {
845        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
846        return TELEPHONY_ERR_LOCAL_PTR_NULL;
847    }
848    int32_t index;
849    handler->RequestSsRequestCommandIndex(index);
850    int32_t result = supplementRequestIms_.SetCallTransferRequest(slotId, cfInfo, ServiceClassType::VOICE, index);
851    if (result == TELEPHONY_SUCCESS) {
852        handler->SaveSsRequestCommand(command, index);
853    }
854    return result;
855}
856
857int32_t CellularCallSupplement::CanSetCallTransferTime(int32_t slotId, bool &result)
858{
859    if (!moduleServiceUtils_.NeedCallImsService()) {
860        return CALL_ERR_RESOURCE_UNAVAILABLE;
861    }
862    int32_t ret = TELEPHONY_SUCCESS;
863    ret = supplementRequestIms_.CanSetCallTransferTime(slotId, result);
864    return ret;
865}
866
867int32_t CellularCallSupplement::GetCallTransferInfo(int32_t slotId, CallTransferType type)
868{
869    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
870    if (handler == nullptr) {
871        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
872        return TELEPHONY_ERR_LOCAL_PTR_NULL;
873    }
874    int32_t result = TELEPHONY_ERROR;
875    auto utCommand = std::make_shared<SsRequestCommand>();
876    utCommand->flag = SS_FROM_SETTING_MENU;
877    utCommand->cfReason = static_cast<int32_t>(type);
878    int32_t index;
879    if (NeedUseImsToHandle(slotId)) {
880        handler->RequestSsRequestCommandIndex(index);
881        result = supplementRequestIms_.GetCallTransferRequest(slotId, static_cast<int32_t>(type), index);
882        if (result == TELEPHONY_SUCCESS) {
883            handler->SaveSsRequestCommand(utCommand, index);
884        }
885        return result;
886    }
887    if (!PhoneTypeGsmOrNot(slotId)) {
888        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
889        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
890    }
891
892    /*
893     * When querying the status of a network service (<mode>=2) the response line for 'not active' case
894     * (<status>=0) should be returned only if service is not active for any <class>
895     */
896    handler->RequestSsRequestCommandIndex(index);
897    result = supplementRequestCs_.GetCallTransferRequest(slotId, static_cast<int32_t>(type), index);
898    if (result == TELEPHONY_SUCCESS) {
899        handler->SaveSsRequestCommand(utCommand, index);
900    }
901    return result;
902}
903
904bool CellularCallSupplement::PhoneTypeGsmOrNot(int32_t slotId)
905{
906    return moduleServiceUtils_.GetNetworkStatus(slotId) == PhoneType::PHONE_TYPE_IS_GSM;
907}
908
909bool CellularCallSupplement::NeedUseImsToHandle(int32_t slotId)
910{
911    return moduleServiceUtils_.NeedCallImsService() && moduleServiceUtils_.GetImsUtSupportState(slotId);
912}
913
914int32_t CellularCallSupplement::SetCallWaiting(int32_t slotId, bool activate)
915{
916    RadioResponseInfo responseInfo;
917    responseInfo.error = ErrType::ERR_GENERIC_FAILURE;
918    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
919    if (handler == nullptr) {
920        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
921        return TELEPHONY_ERR_LOCAL_PTR_NULL;
922    }
923    int32_t classType = ServiceClassType::VOICE;
924    CellularCallConfig config;
925    classType = config.GetCallWaitingServiceClassConfig(slotId);
926    int32_t result = TELEPHONY_ERROR;
927    auto utCommand = std::make_shared<SsRequestCommand>();
928    utCommand->flag = SS_FROM_SETTING_MENU;
929    utCommand->classType = classType;
930    utCommand->enable = activate;
931    int32_t index;
932    if (NeedUseImsToHandle(slotId)) {
933        handler->RequestSsRequestCommandIndex(index);
934        result = supplementRequestIms_.SetCallWaitingRequest(slotId, activate, classType, index);
935        if (result == TELEPHONY_SUCCESS) {
936            handler->SaveSsRequestCommand(utCommand, index);
937        }
938        return result;
939    }
940    /*
941     * <n> (sets/shows the result code presentation status in the TA):
942     * 0	disable
943     * 1	enable
944     */
945    if (!PhoneTypeGsmOrNot(slotId)) {
946        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
947        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
948    }
949    handler->RequestSsRequestCommandIndex(index);
950    result = supplementRequestCs_.SetCallWaitingRequest(slotId, activate, classType, index);
951    if (result == TELEPHONY_SUCCESS) {
952        handler->SaveSsRequestCommand(utCommand, index);
953    }
954    return result;
955}
956
957int32_t CellularCallSupplement::GetCallWaiting(int32_t slotId)
958{
959    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
960    if (handler == nullptr) {
961        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
962        return TELEPHONY_ERR_LOCAL_PTR_NULL;
963    }
964    int32_t result = TELEPHONY_ERROR;
965    auto utCommand = std::make_shared<SsRequestCommand>();
966    utCommand->flag = SS_FROM_SETTING_MENU;
967    int32_t index;
968    if (NeedUseImsToHandle(slotId)) {
969        handler->RequestSsRequestCommandIndex(index);
970        result = supplementRequestIms_.GetCallWaitingRequest(slotId, index);
971        if (result == TELEPHONY_SUCCESS) {
972            handler->SaveSsRequestCommand(utCommand, index);
973        }
974        return result;
975    }
976    if (!PhoneTypeGsmOrNot(slotId)) {
977        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
978        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
979    }
980    handler->RequestSsRequestCommandIndex(index);
981    result = supplementRequestCs_.GetCallWaitingRequest(slotId, index);
982    if (result == TELEPHONY_SUCCESS) {
983        handler->SaveSsRequestCommand(utCommand, index);
984    }
985    return result;
986}
987
988int32_t CellularCallSupplement::SetCallRestriction(int32_t slotId, const CallRestrictionInfo &cRInfo)
989{
990    RadioResponseInfo responseInfo;
991    responseInfo.error = ErrType::ERR_GENERIC_FAILURE;
992    std::string fac;
993    int32_t result = CheckCallRestrictionType(fac, cRInfo.fac);
994    if (result != TELEPHONY_SUCCESS) {
995        return result;
996    }
997    if (cRInfo.mode < CallRestrictionMode::RESTRICTION_MODE_DEACTIVATION ||
998        cRInfo.mode > CallRestrictionMode::RESTRICTION_MODE_ACTIVATION) {
999        TELEPHONY_LOGE("[slot%{public}d] mode parameter out of range!", slotId);
1000        return CALL_ERR_PARAMETER_OUT_OF_RANGE;
1001    }
1002    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
1003    if (handler == nullptr) {
1004        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
1005        return TELEPHONY_ERR_LOCAL_PTR_NULL;
1006    }
1007    std::string info(cRInfo.password);
1008    auto utCommand = std::make_shared<SsRequestCommand>();
1009    utCommand->flag = SS_FROM_SETTING_MENU;
1010    utCommand->facility = fac;
1011    utCommand->enable = static_cast<int32_t>(cRInfo.mode);
1012    size_t cpyLen = strlen(info.c_str()) + 1;
1013    size_t maxCpyLen = sizeof(utCommand->password);
1014    if (strcpy_s(utCommand->password, cpyLen > maxCpyLen ? maxCpyLen : cpyLen, info.c_str()) != EOK) {
1015        TELEPHONY_LOGE("[slot%{public}d] strcpy_s fail.", slotId);
1016        return TELEPHONY_ERR_STRCPY_FAIL;
1017    }
1018    int32_t index;
1019    if (NeedUseImsToHandle(slotId)) {
1020        return SetCallRestrictionByIms(slotId, fac, static_cast<int32_t>(cRInfo.mode), info, utCommand);
1021    }
1022    if (!PhoneTypeGsmOrNot(slotId)) {
1023        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
1024        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
1025    }
1026    handler->RequestSsRequestCommandIndex(index);
1027    result =
1028        supplementRequestCs_.SetCallRestrictionRequest(slotId, fac, static_cast<int32_t>(cRInfo.mode), info, index);
1029    if (result == TELEPHONY_SUCCESS) {
1030        handler->SaveSsRequestCommand(utCommand, index);
1031    }
1032    return result;
1033}
1034
1035int32_t CellularCallSupplement::SetCallRestrictionByIms(
1036    int32_t slotId, std::string &fac, int32_t mode, std::string &pw, const std::shared_ptr<SsRequestCommand> &command)
1037{
1038    RadioResponseInfo responseInfo;
1039    responseInfo.error = ErrType::ERR_GENERIC_FAILURE;
1040    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
1041    if (handler == nullptr) {
1042        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
1043        return TELEPHONY_ERR_LOCAL_PTR_NULL;
1044    }
1045    int32_t index;
1046    handler->RequestSsRequestCommandIndex(index);
1047    int32_t result = supplementRequestIms_.SetCallRestrictionRequest(slotId, fac, mode, pw, index);
1048    if (result == TELEPHONY_SUCCESS) {
1049        handler->SaveSsRequestCommand(command, index);
1050    }
1051    return result;
1052}
1053
1054int32_t CellularCallSupplement::GetCallRestriction(int32_t slotId, CallRestrictionType facType)
1055{
1056    std::string fac;
1057    int32_t result = CheckCallRestrictionType(fac, facType);
1058    if (result != TELEPHONY_SUCCESS) {
1059        return result;
1060    }
1061    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
1062    if (handler == nullptr) {
1063        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
1064        return TELEPHONY_ERR_LOCAL_PTR_NULL;
1065    }
1066    auto utCommand = std::make_shared<SsRequestCommand>();
1067    utCommand->flag = SS_FROM_SETTING_MENU;
1068    utCommand->facility = fac;
1069    int32_t index;
1070    if (NeedUseImsToHandle(slotId)) {
1071        handler->RequestSsRequestCommandIndex(index);
1072        result = supplementRequestIms_.GetCallRestrictionRequest(slotId, fac, index);
1073        if (result == TELEPHONY_SUCCESS) {
1074            handler->SaveSsRequestCommand(utCommand, index);
1075        }
1076        return result;
1077    }
1078    if (!PhoneTypeGsmOrNot(slotId)) {
1079        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
1080        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
1081    }
1082    handler->RequestSsRequestCommandIndex(index);
1083    result = supplementRequestCs_.GetCallRestrictionRequest(slotId, fac, index);
1084    if (result == TELEPHONY_SUCCESS) {
1085        handler->SaveSsRequestCommand(utCommand, index);
1086    }
1087    return result;
1088}
1089
1090int32_t CellularCallSupplement::SetBarringPassword(
1091    int32_t slotId, CallRestrictionType facType, const char *oldPassword, const char *newPassword)
1092{
1093    std::string fac;
1094    int32_t result = CheckCallRestrictionType(fac, facType);
1095    if (result != TELEPHONY_SUCCESS) {
1096        return result;
1097    }
1098    auto handler = DelayedSingleton<CellularCallService>::GetInstance()->GetHandler(slotId);
1099    if (handler == nullptr) {
1100        TELEPHONY_LOGE("[slot%{public}d] handler is nullptr!", slotId);
1101        return TELEPHONY_ERR_LOCAL_PTR_NULL;
1102    }
1103    auto utCommand = std::make_shared<SsRequestCommand>();
1104    utCommand->flag = SS_FROM_SETTING_MENU;
1105    utCommand->facility = fac;
1106    if (!PhoneTypeGsmOrNot(slotId)) {
1107        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
1108        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
1109    }
1110    int32_t index;
1111    handler->RequestSsRequestCommandIndex(index);
1112    result = supplementRequestCs_.SetBarringPasswordRequest(slotId, fac, index, oldPassword, newPassword);
1113    if (result == TELEPHONY_SUCCESS) {
1114        handler->SaveSsRequestCommand(utCommand, index);
1115    }
1116    return result;
1117}
1118
1119int32_t CellularCallSupplement::CheckCallRestrictionType(std::string &fac, const CallRestrictionType &facType)
1120{
1121    /*
1122     * <fac> values reserved by the present document:
1123     * "SC"	SIM (lock SIM/UICC card) (SIM/UICC asks password in ME power up and when this lock command issued)
1124     * "AO"	BAOC (Barr All Outgoing Calls) (refer 3GPP TS 22.088 [6] clause 1)
1125     * "OI"	BOIC (Barr Outgoing International Calls) (refer 3GPP TS 22.088 [6] clause 1)
1126     * "OX"	BOIC exHC (Barr Outgoing International Calls except to Home Country) (refer 3GPP TS 22.088 [6] clause 1)
1127     * "AI"	BAIC (Barr All Incoming Calls) (refer 3GPP TS 22.088 [6] clause 2)
1128     * "IR"	BIC Roam (Barr Incoming Calls when Roaming outside the home country) (refer 3GPP TS 22.088 [6] clause 2)
1129     * "AB"	All Barring services (refer 3GPP TS 22.030 [19]) (applicable only for <mode>=0)
1130     * "AG"	All outGoing barring services (refer 3GPP TS 22.030 [19]) (applicable only for <mode>=0)
1131     * "AC"	All inComing barring services (refer 3GPP TS 22.030 [19]) (applicable only for <mode>=0)
1132     */
1133    switch (facType) {
1134        case CallRestrictionType::RESTRICTION_TYPE_ALL_OUTGOING:
1135            fac = BARR_ALL_OUTGOING_CALLS;
1136            break;
1137        case CallRestrictionType::RESTRICTION_TYPE_INTERNATIONAL:
1138            fac = BARR_OUTGOING_INTERNATIONAL_CALLS;
1139            break;
1140        case CallRestrictionType::RESTRICTION_TYPE_INTERNATIONAL_EXCLUDING_HOME:
1141            fac = BARR_OUTGOING_INTERNATIONAL_CALLS_EXCLUDING_HOME;
1142            break;
1143        case CallRestrictionType::RESTRICTION_TYPE_ALL_INCOMING:
1144            fac = BARR_ALL_INCOMING_CALLS;
1145            break;
1146        case CallRestrictionType::RESTRICTION_TYPE_ROAMING_INCOMING:
1147            fac = BARR_INCOMING_CALLS_OUTSIDE_HOME;
1148            break;
1149        case CallRestrictionType::RESTRICTION_TYPE_ALL_CALLS:
1150            fac = ALL_BARRING_SERVICES;
1151            break;
1152        case CallRestrictionType::RESTRICTION_TYPE_OUTGOING_SERVICES:
1153            fac = ALL_OUTGOING_BARRING_SERVICES;
1154            break;
1155        case CallRestrictionType::RESTRICTION_TYPE_INCOMING_SERVICES:
1156            fac = ALL_INCOMING_BARRING_SERVICES;
1157            break;
1158        default:
1159            TELEPHONY_LOGE("parameter out of range!");
1160            return CALL_ERR_PARAMETER_OUT_OF_RANGE;
1161    }
1162    return TELEPHONY_SUCCESS;
1163}
1164
1165void CellularCallSupplement::EventGetClip(const GetClipResult &getClipResult, const std::string &message, int32_t flag)
1166{
1167    ClipResponse clipResponse;
1168    clipResponse.result = getClipResult.result.result;
1169    if (clipResponse.result == IMS_ERROR_UT_NO_CONNECTION) {
1170        clipResponse.result = CALL_ERR_UT_NO_CONNECTION;
1171    }
1172    clipResponse.action = getClipResult.action;
1173    clipResponse.clipStat = getClipResult.clipStat;
1174    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1175    if (callRegister == nullptr) {
1176        TELEPHONY_LOGE("callRegister is null.");
1177        return;
1178    }
1179
1180    if (flag == SS_FROM_MMI_CODE) {
1181        std::string successMessage = GET_CLIP_SUCCESS;
1182        CreateSuppSvcQueryResultMessage(successMessage, clipResponse.result, clipResponse.clipStat);
1183        ReportMmiCodeMessage(clipResponse.result, successMessage, message.empty() ? GET_CLIP_FAILED : message);
1184    } else {
1185        callRegister->ReportGetClipResult(clipResponse);
1186    }
1187}
1188
1189void CellularCallSupplement::EventSetClip(int32_t result, const std::string &message, int32_t flag)
1190{
1191    if (flag == SS_FROM_MMI_CODE) {
1192        ReportMmiCodeMessage(result, SET_CLIP_SUCCESS, message.empty() ? SET_CLIP_FAILED : message);
1193    } else {
1194        TELEPHONY_LOGE("report the result of GetColp failed since the flag %{public}d was wrong", flag);
1195    }
1196}
1197
1198void CellularCallSupplement::EventGetClir(const GetClirResult &result, const std::string &message, int32_t flag)
1199{
1200    ClirResponse response;
1201    // 3GPP TS 27.007 V3.9.0 (2001-06) 7.7	Calling line identification restriction +CLIR
1202    response.result = result.result.result;
1203    if (response.result == IMS_ERROR_UT_NO_CONNECTION) {
1204        response.result = CALL_ERR_UT_NO_CONNECTION;
1205    }
1206    response.action = result.action;
1207    response.clirStat = result.clirStat;
1208    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1209    if (callRegister == nullptr) {
1210        TELEPHONY_LOGE("callRegister is null.");
1211        return;
1212    }
1213    if (flag == SS_FROM_MMI_CODE) {
1214        std::string successMessage = GET_CLIR_SUCCESS;
1215        CreateGetClirResultMessage(successMessage, response);
1216        ReportMmiCodeMessage(response.result, successMessage, message.empty() ? GET_CLIR_FAILED : message);
1217    } else {
1218        callRegister->ReportGetClirResult(response);
1219    }
1220}
1221
1222void CellularCallSupplement::EventSetClir(int32_t result, const std::string &message, int32_t flag)
1223{
1224    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1225    if (callRegister == nullptr) {
1226        TELEPHONY_LOGE("callRegister is null.");
1227        return;
1228    }
1229    if (flag == SS_FROM_MMI_CODE) {
1230        ReportMmiCodeMessage(result, SET_CLIR_SUCCESS, message.empty() ? SET_CLIR_FAILED : message);
1231    } else {
1232        callRegister->ReportSetClirResult(result);
1233    }
1234}
1235
1236void CellularCallSupplement::EventGetColr(const GetColrResult &result, const std::string &message, int32_t flag)
1237{
1238    ColrResponse response;
1239    response.result = result.result.result;
1240    if (response.result == IMS_ERROR_UT_NO_CONNECTION) {
1241        response.result = CALL_ERR_UT_NO_CONNECTION;
1242    }
1243    response.action = result.action;
1244    response.colrStat = result.colrStat;
1245    if (flag == SS_FROM_MMI_CODE) {
1246        std::string successMessage = GET_COLR_SUCCESS;
1247        CreateSuppSvcQueryResultMessage(successMessage, response.result, response.colrStat);
1248        ReportMmiCodeMessage(response.result, successMessage, message.empty() ? GET_COLR_FAILED : message);
1249    } else {
1250        TELEPHONY_LOGE("report the result of GetColp failed since the flag %{public}d was wrong", flag);
1251    }
1252}
1253
1254void CellularCallSupplement::EventSetColr(int32_t result, const std::string &message, int32_t flag)
1255{
1256    if (flag == SS_FROM_MMI_CODE) {
1257        ReportMmiCodeMessage(result, SET_COLR_SUCCESS, message.empty() ? SET_COLR_FAILED : message);
1258    } else {
1259        TELEPHONY_LOGE("report the result of GetColp failed since the flag %{public}d was wrong", flag);
1260    }
1261}
1262
1263void CellularCallSupplement::EventGetColp(const GetColpResult &result, const std::string &message, int32_t flag)
1264{
1265    ColpResponse response;
1266    response.result = result.result.result;
1267    if (response.result == IMS_ERROR_UT_NO_CONNECTION) {
1268        response.result = CALL_ERR_UT_NO_CONNECTION;
1269    }
1270    response.action = result.action;
1271    response.colpStat = result.colpStat;
1272    if (flag == SS_FROM_MMI_CODE) {
1273        std::string successMessage = GET_COLP_SUCCESS;
1274        CreateSuppSvcQueryResultMessage(successMessage, response.result, response.colpStat);
1275        ReportMmiCodeMessage(response.result, successMessage, message.empty() ? GET_COLP_FAILED : message);
1276    } else {
1277        TELEPHONY_LOGE("report the result of GetColp failed since the flag %{public}d was wrong", flag);
1278    }
1279}
1280
1281void CellularCallSupplement::EventSetColp(int32_t result, const std::string &message, int32_t flag)
1282{
1283    if (flag == SS_FROM_MMI_CODE) {
1284        ReportMmiCodeMessage(result, SET_COLP_SUCCESS, message.empty() ? SET_COLP_FAILED : message);
1285    } else {
1286        TELEPHONY_LOGE("report the result of GetColp failed since the flag %{public}d was wrong", flag);
1287    }
1288}
1289
1290int32_t CellularCallSupplement::SendUssd(int32_t slotId, const std::string &msg)
1291{
1292    if (!PhoneTypeGsmOrNot(slotId)) {
1293        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
1294        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
1295        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
1296    }
1297    int32_t result = TELEPHONY_SUCCESS;
1298    result = supplementRequestCs_.SendUssdRequest(slotId, msg);
1299    if (result != TELEPHONY_SUCCESS) {
1300        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
1301    }
1302    return result;
1303}
1304
1305void CellularCallSupplement::EventSendUssd(const RadioResponseInfo &responseInfo)
1306{
1307    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1308    if (callRegister == nullptr) {
1309        TELEPHONY_LOGE("callRegister is null.");
1310        return;
1311    }
1312    callRegister->ReportSendUssdResult(static_cast<int32_t>(responseInfo.error));
1313    ReportMmiCodeMessage(static_cast<int32_t>(responseInfo.error), SEND_USSD_SUCCESS, INVALID_MMI_CODE);
1314}
1315
1316void CellularCallSupplement::EventSsNotify(SsNoticeInfo &ssNoticeInfo)
1317{
1318    MmiCodeInfo mmiCodeInfo;
1319    mmiCodeInfo.result = ssNoticeInfo.result;
1320    switch (ssNoticeInfo.requestType) {
1321        case static_cast<int32_t>(SsRequestType::SS_ACTIVATION):
1322        case static_cast<int32_t>(SsRequestType::SS_DEACTIVATION):
1323        case static_cast<int32_t>(SsRequestType::SS_REGISTRATION):
1324        case static_cast<int32_t>(SsRequestType::SS_ERASURE):
1325        case static_cast<int32_t>(SsRequestType::SS_INTERROGATION):
1326            GetMessage(mmiCodeInfo, ssNoticeInfo);
1327            break;
1328        default:
1329            TELEPHONY_LOGE("Invaid requestType in SS Data!");
1330            return;
1331    }
1332
1333    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1334    if (callRegister == nullptr) {
1335        TELEPHONY_LOGE("callRegister is null.");
1336        return;
1337    }
1338    callRegister->ReportMmiCodeResult(mmiCodeInfo);
1339}
1340
1341void CellularCallSupplement::GetMessage(MmiCodeInfo &mmiCodeInfo, const SsNoticeInfo &ssNoticeInfo)
1342{
1343    if (ssNoticeInfo.result != 0) {
1344        if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), QUERY_SS_FAILED.c_str()) != EOK) {
1345            TELEPHONY_LOGE("strcpy_s QUERY_SS_FAILED fail.");
1346        }
1347        return;
1348    }
1349    switch (ssNoticeInfo.serviceType) {
1350        case (unsigned int)CallTransferType::TRANSFER_TYPE_UNCONDITIONAL: {
1351            if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message),
1352                TRANSFER_UNCONDITIONAL_SUCCESS.c_str()) != EOK) {
1353                TELEPHONY_LOGE("strcpy_s TRANSFER_UNCONDITIONAL_SUCCESS fail.");
1354                return;
1355            }
1356            break;
1357        }
1358        case (unsigned int)CallTransferType::TRANSFER_TYPE_BUSY: {
1359            if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), TRANSFER_BUSY_SUCCESS.c_str()) != EOK) {
1360                TELEPHONY_LOGE("strcpy_s TRANSFER_BUSY_SUCCESS fail.");
1361                return;
1362            }
1363            break;
1364        }
1365        case (unsigned int)CallTransferType::TRANSFER_TYPE_NO_REPLY: {
1366            if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), TRANSFER_NO_REPLYL_SUCCESS.c_str()) != EOK) {
1367                TELEPHONY_LOGE("strcpy_s TRANSFER_NO_REPLYL_SUCCESS fail.");
1368                return;
1369            }
1370            break;
1371        }
1372        case (unsigned int)CallTransferType::TRANSFER_TYPE_NOT_REACHABLE: {
1373            if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message),
1374                TRANSFER_NOT_REACHABLE_SUCCESS.c_str()) != EOK) {
1375                TELEPHONY_LOGE("strcpy_s TRANSFER_NOT_REACHABLE_SUCCESS fail.");
1376                return;
1377            }
1378            break;
1379        }
1380        default: {
1381            if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), QUERY_SS_SUCCESS.c_str()) != EOK) {
1382                TELEPHONY_LOGE("strcpy_s QUERY_SS_SUCCESS fail.");
1383                return;
1384            }
1385        }
1386    }
1387}
1388
1389void CellularCallSupplement::EventUssdNotify(UssdNoticeInfo &ussdNoticeInfo)
1390{
1391    MmiCodeInfo mmiCodeInfo;
1392    bool isUssdError = ussdNoticeInfo.m != USSD_MODE_NOTIFY && ussdNoticeInfo.m != USSD_MODE_REQUEST;
1393    if (!isUssdError && !ussdNoticeInfo.str.empty()) {
1394        mmiCodeInfo.result = USSD_SUCCESS;
1395        if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), ussdNoticeInfo.str.c_str()) != EOK) {
1396            TELEPHONY_LOGE("strcpy_s ussdNoticeInfo.str fail.");
1397            return;
1398        }
1399    } else if (isUssdError && !(ussdNoticeInfo.m == USSD_MODE_NW_RELEASE)) {
1400        mmiCodeInfo.result = USSD_FAILED;
1401        if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), INVALID_MMI_CODE.c_str()) != EOK) {
1402            TELEPHONY_LOGE("strcpy_s INVALID_MMI_CODE fail.");
1403            return;
1404        }
1405    } else {
1406        TELEPHONY_LOGE("Invaild ussd notify.");
1407    }
1408
1409    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1410    if (callRegister == nullptr) {
1411        TELEPHONY_LOGE("callRegister is null.");
1412        return;
1413    }
1414    callRegister->ReportMmiCodeResult(mmiCodeInfo);
1415}
1416
1417void CellularCallSupplement::EventSetPinPuk(const PinPukResponse &pinPukResponse)
1418{
1419    MmiCodeInfo mmiCodeInfo;
1420    mmiCodeInfo.result = pinPukResponse.result;
1421    std::string messageTemp = std::to_string(pinPukResponse.remain);
1422    if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), messageTemp.c_str()) != EOK) {
1423        TELEPHONY_LOGE("strcpy_s messageTemp fail.");
1424    }
1425    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1426    if (callRegister == nullptr) {
1427        TELEPHONY_LOGE("callRegister is null.");
1428        return;
1429    }
1430    callRegister->ReportMmiCodeResult(mmiCodeInfo);
1431}
1432
1433void CellularCallSupplement::AlterPinPassword(int32_t slotId, const MMIData &mmiData)
1434{
1435    if (mmiData.actionString.empty()) {
1436        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
1437        return;
1438    }
1439
1440    std::string oldPin = mmiData.serviceInfoA;
1441    std::string newPin = mmiData.serviceInfoB;
1442    std::string newPinCheck = mmiData.serviceInfoC;
1443    if (!IsVaildPinOrPuk(newPin, newPinCheck)) {
1444        return;
1445    }
1446    int32_t result = TELEPHONY_SUCCESS;
1447    result = supplementRequestCs_.AlterPinPassword(slotId, newPin, oldPin);
1448    if (result != TELEPHONY_SUCCESS) {
1449        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
1450    }
1451}
1452
1453void CellularCallSupplement::UnlockPuk(int32_t slotId, const MMIData &mmiData)
1454{
1455    if (mmiData.actionString.empty()) {
1456        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
1457        return;
1458    }
1459    std::string puk = mmiData.serviceInfoA;
1460    std::string newPin = mmiData.serviceInfoB;
1461    std::string newPinCheck = mmiData.serviceInfoC;
1462    if (!IsVaildPinOrPuk(newPin, newPinCheck)) {
1463        return;
1464    }
1465    int32_t result = TELEPHONY_SUCCESS;
1466    result = supplementRequestCs_.UnlockPuk(slotId, newPin, puk);
1467    if (result != TELEPHONY_SUCCESS) {
1468        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
1469    }
1470}
1471
1472void CellularCallSupplement::AlterPin2Password(int32_t slotId, const MMIData &mmiData)
1473{
1474    if (mmiData.actionString.empty()) {
1475        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
1476        return;
1477    }
1478
1479    std::string oldPin2 = mmiData.serviceInfoA;
1480    std::string newPin2 = mmiData.serviceInfoB;
1481    std::string newPin2Check = mmiData.serviceInfoC;
1482    if (!IsVaildPinOrPuk(newPin2, newPin2Check)) {
1483        return;
1484    }
1485    int32_t result = TELEPHONY_SUCCESS;
1486    result = supplementRequestCs_.AlterPin2Password(slotId, newPin2, oldPin2);
1487    if (result != TELEPHONY_SUCCESS) {
1488        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
1489    }
1490}
1491
1492void CellularCallSupplement::UnlockPuk2(int32_t slotId, const MMIData &mmiData)
1493{
1494    if (mmiData.actionString.empty()) {
1495        TELEPHONY_LOGE("[slot%{public}d] actionString is empty!", slotId);
1496        return;
1497    }
1498
1499    std::string puk2 = mmiData.serviceInfoA;
1500    std::string newPin2 = mmiData.serviceInfoB;
1501    std::string newPin2Check = mmiData.serviceInfoC;
1502    if (!IsVaildPinOrPuk(newPin2, newPin2Check)) {
1503        return;
1504    }
1505    int32_t result = TELEPHONY_SUCCESS;
1506    result = supplementRequestCs_.UnlockPuk2(slotId, newPin2, puk2);
1507    if (result != TELEPHONY_SUCCESS) {
1508        ReportMmiCodeMessage(MMI_CODE_FAILED, "", GENERIC_FAILURE);
1509    }
1510}
1511
1512bool CellularCallSupplement::IsVaildPinOrPuk(std::string newPinOrPuk, std::string newPinOrPukCheck)
1513{
1514    if (newPinOrPuk != newPinOrPukCheck) {
1515        ReportMmiCodeMessage(MMI_CODE_FAILED, "", MIS_MATCH_PIN_PUK);
1516        return false;
1517    } else if (static_cast<int32_t>(newPinOrPuk.length()) < PIN_PUK_MIN ||
1518               static_cast<int32_t>(newPinOrPuk.length()) > PIN_PUK_MAX) {
1519        ReportMmiCodeMessage(MMI_CODE_FAILED, "", INVAILD_PIN_PUK);
1520        return false;
1521    } else {
1522        TELEPHONY_LOGI("Check Pin or Puk success.");
1523    }
1524    return true;
1525}
1526
1527void CellularCallSupplement::ReportMmiCodeMessage(
1528    int32_t result, const std::string successMsg, const std::string failedMsg)
1529{
1530    MmiCodeInfo mmiCodeInfo;
1531    mmiCodeInfo.result = result;
1532    if (result == RESULT_SUCCESS) {
1533        if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), successMsg.c_str()) != EOK) {
1534            TELEPHONY_LOGE("strcpy_s fail.");
1535            return;
1536        }
1537    } else {
1538        if (strcpy_s(mmiCodeInfo.message, sizeof(mmiCodeInfo.message), failedMsg.c_str()) != EOK) {
1539            TELEPHONY_LOGE("strcpy_s fail.");
1540            return;
1541        }
1542    }
1543    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1544    if (callRegister == nullptr) {
1545        TELEPHONY_LOGE("callRegister is null.");
1546        return;
1547    }
1548    callRegister->ReportMmiCodeResult(mmiCodeInfo);
1549}
1550
1551int32_t CellularCallSupplement::CloseUnFinishedUssd(int32_t slotId)
1552{
1553    if (!PhoneTypeGsmOrNot(slotId)) {
1554        TELEPHONY_LOGE("[slot%{public}d] network type is not supported!", slotId);
1555        return CALL_ERR_UNSUPPORTED_NETWORK_TYPE;
1556    }
1557    return supplementRequestCs_.CloseUnFinishedUssdRequest(slotId);
1558}
1559
1560void CellularCallSupplement::EventCloseUnFinishedUssd(const RadioResponseInfo &responseInfo)
1561{
1562    auto callRegister = DelayedSingleton<CellularCallRegister>::GetInstance();
1563    if (callRegister == nullptr) {
1564        TELEPHONY_LOGE("callRegister is null.");
1565        return;
1566    }
1567    int32_t result = TELEPHONY_ERROR;
1568    if (responseInfo.error == ErrType::NONE) {
1569        result = TELEPHONY_SUCCESS;
1570    } else {
1571        result = TELEPHONY_ERR_RIL_CMD_FAIL;
1572    }
1573    callRegister->ReportCloseUnFinishedUssdResult(result);
1574}
1575} // namespace Telephony
1576} // namespace OHOS
1577