1/*
2 * Copyright (C) 2021 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 "carrier_call.h"
17
18#include <securec.h>
19
20#include "call_manager_errors.h"
21#include "call_manager_hisysevent.h"
22#include "telephony_log_wrapper.h"
23
24#include "call_number_utils.h"
25
26namespace OHOS {
27namespace Telephony {
28CarrierCall::CarrierCall(DialParaInfo &info)
29    : CallBase(info), dialScene_(DialScene::CALL_NORMAL), slotId_(info.accountId), index_(info.index),
30    isEcc_(info.isEcc), cellularCallConnectionPtr_(DelayedSingleton<CellularCallConnection>::GetInstance())
31{}
32
33CarrierCall::CarrierCall(DialParaInfo &info, AppExecFwk::PacMap &extras)
34    : CallBase(info, extras), dialScene_((DialScene)extras.GetIntValue("dialScene")), slotId_(info.accountId),
35    index_(info.index), isEcc_(info.isEcc),
36    cellularCallConnectionPtr_(DelayedSingleton<CellularCallConnection>::GetInstance())
37{}
38
39CarrierCall::~CarrierCall() {}
40
41int32_t CarrierCall::CarrierDialingProcess()
42{
43    TELEPHONY_LOGI("CarrierDialingProcess start");
44    int32_t ret = DialCallBase();
45    if (ret != TELEPHONY_SUCCESS) {
46        CarrierHangUpCall();
47    }
48    return ret;
49}
50
51int32_t CarrierCall::CarrierAnswerCall(int32_t videoState)
52{
53    CellularCallInfo callInfo;
54    int32_t ret = AnswerCallBase();
55    if (ret != TELEPHONY_SUCCESS) {
56        TELEPHONY_LOGE("answer call failed!");
57        CallManagerHisysevent::WriteAnswerCallFaultEvent(
58            slotId_, INVALID_PARAMETER, videoState, ret, "the device is currently not ringing");
59        return CALL_ERR_ANSWER_FAILED;
60    }
61    ret = PackCellularCallInfo(callInfo);
62    callInfo.videoState = videoState;
63    if (ret != TELEPHONY_SUCCESS) {
64        TELEPHONY_LOGW("PackCellularCallInfo failed!");
65        CallManagerHisysevent::WriteAnswerCallFaultEvent(
66            slotId_, INVALID_PARAMETER, videoState, ret, "PackCellularCallInfo failed");
67    }
68    if (cellularCallConnectionPtr_ == nullptr) {
69        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
70        return TELEPHONY_ERR_LOCAL_PTR_NULL;
71    }
72    ret = cellularCallConnectionPtr_->Answer(callInfo);
73    if (ret != TELEPHONY_SUCCESS) {
74        TELEPHONY_LOGE("answer call failed!");
75        return CALL_ERR_ANSWER_FAILED;
76    }
77    return TELEPHONY_SUCCESS;
78}
79
80int32_t CarrierCall::CarrierRejectCall()
81{
82    CellularCallInfo callInfo;
83    int32_t ret = RejectCallBase();
84    if (ret != TELEPHONY_SUCCESS) {
85        return ret;
86    }
87    ret = PackCellularCallInfo(callInfo);
88    if (ret != TELEPHONY_SUCCESS) {
89        TELEPHONY_LOGW("PackCellularCallInfo failed!");
90        CallManagerHisysevent::WriteHangUpFaultEvent(
91            slotId_, callInfo.callId, ret, "Reject PackCellularCallInfo failed");
92    }
93    if (cellularCallConnectionPtr_ == nullptr) {
94        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
95        return TELEPHONY_ERR_LOCAL_PTR_NULL;
96    }
97    ret = cellularCallConnectionPtr_->HangUp(callInfo, CallSupplementType::TYPE_DEFAULT);
98    if (ret != TELEPHONY_SUCCESS) {
99        TELEPHONY_LOGE("Reject failed!");
100        return CALL_ERR_REJECT_FAILED;
101    }
102    return TELEPHONY_SUCCESS;
103}
104
105int32_t CarrierCall::CarrierHangUpCall()
106{
107    int32_t ret = CALL_ERR_HANGUP_FAILED;
108    CellularCallInfo callInfo;
109    ret = PackCellularCallInfo(callInfo);
110    if (ret != TELEPHONY_SUCCESS) {
111        TELEPHONY_LOGW("PackCellularCallInfo failed!");
112        CallManagerHisysevent::WriteHangUpFaultEvent(
113            callInfo.accountId, callInfo.callId, ret, "HangUp PackCellularCallInfo failed");
114    }
115    uint64_t policyFlag = GetPolicyFlag();
116    if (cellularCallConnectionPtr_ == nullptr) {
117        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
118        return TELEPHONY_ERR_LOCAL_PTR_NULL;
119    }
120    if (policyFlag & POLICY_FLAG_HANG_UP_ACTIVE) {
121        ret = cellularCallConnectionPtr_->HangUp(callInfo, CallSupplementType::TYPE_HANG_UP_ACTIVE);
122    } else if (policyFlag & POLICY_FLAG_HANG_UP_HOLD_WAIT) {
123        ret = cellularCallConnectionPtr_->HangUp(callInfo, CallSupplementType::TYPE_HANG_UP_HOLD_WAIT);
124    } else {
125        ret = cellularCallConnectionPtr_->HangUp(callInfo, CallSupplementType::TYPE_DEFAULT);
126    }
127    if (ret != TELEPHONY_SUCCESS) {
128        TELEPHONY_LOGE("End failed!");
129        return CALL_ERR_HANGUP_FAILED;
130    }
131    return TELEPHONY_SUCCESS;
132}
133
134int32_t CarrierCall::CarrierHoldCall()
135{
136    CellularCallInfo callInfo;
137    int32_t ret = PackCellularCallInfo(callInfo);
138    if (ret != TELEPHONY_SUCCESS) {
139        TELEPHONY_LOGW("PackCellularCallInfo failed!");
140    }
141    if (cellularCallConnectionPtr_ == nullptr) {
142        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
143        return TELEPHONY_ERR_LOCAL_PTR_NULL;
144    }
145    ret = cellularCallConnectionPtr_->HoldCall(callInfo);
146    if (ret != TELEPHONY_SUCCESS) {
147        TELEPHONY_LOGE("Hold failed!");
148        return CALL_ERR_HOLD_FAILED;
149    }
150    return TELEPHONY_SUCCESS;
151}
152
153int32_t CarrierCall::CarrierUnHoldCall()
154{
155    CellularCallInfo callInfo;
156    int32_t ret = PackCellularCallInfo(callInfo);
157    if (ret != TELEPHONY_SUCCESS) {
158        TELEPHONY_LOGW("PackCellularCallInfo failed!");
159    }
160    if (cellularCallConnectionPtr_ == nullptr) {
161        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
162        return TELEPHONY_ERR_LOCAL_PTR_NULL;
163    }
164    ret = cellularCallConnectionPtr_->UnHoldCall(callInfo);
165    if (ret != TELEPHONY_SUCCESS) {
166        TELEPHONY_LOGE("UnHold failed!");
167        return CALL_ERR_UNHOLD_FAILED;
168    }
169    return TELEPHONY_SUCCESS;
170}
171
172int32_t CarrierCall::CarrierSetMute(int32_t mute, int32_t slotId)
173{
174    if (cellularCallConnectionPtr_ == nullptr) {
175        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
176        return TELEPHONY_ERR_LOCAL_PTR_NULL;
177    }
178    int32_t ret = cellularCallConnectionPtr_->SetMute(mute, slotId);
179    if (ret != TELEPHONY_SUCCESS) {
180        TELEPHONY_LOGE("SetMute failed!");
181        return CALL_ERR_UNHOLD_FAILED;
182    }
183    return TELEPHONY_SUCCESS;
184}
185
186void CarrierCall::GetCallAttributeCarrierInfo(CallAttributeInfo &info)
187{
188    std::lock_guard<std::mutex> lock(mutex_);
189    info.isEcc = isEcc_;
190    info.accountId = slotId_;
191    info.index = index_;
192    GetCallAttributeBaseInfo(info);
193}
194
195bool CarrierCall::GetEmergencyState()
196{
197    std::lock_guard<std::mutex> lock(mutex_);
198    return isEcc_;
199}
200
201int32_t CarrierCall::CarrierSwitchCall()
202{
203    CellularCallInfo callInfo;
204    int32_t ret = PackCellularCallInfo(callInfo);
205    if (ret != TELEPHONY_SUCCESS) {
206        TELEPHONY_LOGW("PackCellularCallInfo failed!");
207    }
208    if (cellularCallConnectionPtr_ == nullptr) {
209        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
210        return TELEPHONY_ERR_LOCAL_PTR_NULL;
211    }
212    ret = cellularCallConnectionPtr_->SwitchCall(callInfo);
213    if (ret != TELEPHONY_SUCCESS) {
214        TELEPHONY_LOGE("SwitchCall failed!");
215        return CALL_ERR_UNHOLD_FAILED;
216    }
217    return TELEPHONY_SUCCESS;
218}
219
220int32_t CarrierCall::GetSlotId()
221{
222    return slotId_;
223}
224
225int32_t CarrierCall::CarrierCombineConference()
226{
227    CellularCallInfo callInfo;
228    int32_t ret = PackCellularCallInfo(callInfo);
229    if (ret != TELEPHONY_SUCCESS) {
230        TELEPHONY_LOGW("PackCellularCallInfo failed!");
231    }
232    if (cellularCallConnectionPtr_ == nullptr) {
233        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
234        return TELEPHONY_ERR_LOCAL_PTR_NULL;
235    }
236    return cellularCallConnectionPtr_->CombineConference(callInfo);
237}
238
239int32_t CarrierCall::CarrierSeparateConference()
240{
241    CellularCallInfo callInfo;
242    int32_t ret = PackCellularCallInfo(callInfo);
243    if (ret != TELEPHONY_SUCCESS) {
244        TELEPHONY_LOGW("PackCellularCallInfo failed!");
245    }
246    if (cellularCallConnectionPtr_ == nullptr) {
247        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
248        return TELEPHONY_ERR_LOCAL_PTR_NULL;
249    }
250    return cellularCallConnectionPtr_->SeparateConference(callInfo);
251}
252
253int32_t CarrierCall::CarrierKickOutFromConference()
254{
255    CellularCallInfo callInfo;
256    int32_t ret = PackCellularCallInfo(callInfo);
257    if (ret != TELEPHONY_SUCCESS) {
258        TELEPHONY_LOGW("PackCellularCallInfo failed!");
259    }
260    if (cellularCallConnectionPtr_ == nullptr) {
261        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
262        return TELEPHONY_ERR_LOCAL_PTR_NULL;
263    }
264    return cellularCallConnectionPtr_->KickOutFromConference(callInfo);
265}
266
267int32_t CarrierCall::IsSupportConferenceable()
268{
269    // emergency call not allowed to join conference
270    return GetEmergencyState() != true ? TELEPHONY_SUCCESS : CALL_ERR_EMERGENCY_UNSUPPORT_CONFERENCEABLE;
271}
272
273int32_t CarrierCall::PackCellularCallInfo(CellularCallInfo &callInfo)
274{
275    callInfo.callId = callId_;
276    callInfo.callType = callType_;
277    callInfo.videoState = static_cast<int32_t>(videoState_);
278    callInfo.index = index_;
279    callInfo.slotId = slotId_;
280    callInfo.accountId = slotId_;
281    if (memset_s(callInfo.phoneNum, kMaxNumberLen, 0, kMaxNumberLen) != EOK) {
282        TELEPHONY_LOGW("memset_s failed!");
283        return TELEPHONY_ERR_MEMSET_FAIL;
284    }
285    if (accountNumber_.length() > static_cast<size_t>(kMaxNumberLen)) {
286        TELEPHONY_LOGE("Number out of limit!");
287        return CALL_ERR_NUMBER_OUT_OF_RANGE;
288    }
289    if (memcpy_s(callInfo.phoneNum, kMaxNumberLen, accountNumber_.c_str(), accountNumber_.length()) != EOK) {
290        TELEPHONY_LOGW("memcpy_s failed!");
291        return TELEPHONY_ERR_MEMCPY_FAIL;
292    }
293    return TELEPHONY_SUCCESS;
294}
295
296int32_t CarrierCall::StartDtmf(char str)
297{
298    CellularCallInfo callInfo;
299    int32_t ret = PackCellularCallInfo(callInfo);
300    if (ret != TELEPHONY_SUCCESS) {
301        TELEPHONY_LOGW("PackCellularCallInfo failed!");
302    }
303    if (cellularCallConnectionPtr_ == nullptr) {
304        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
305        return TELEPHONY_ERR_LOCAL_PTR_NULL;
306    }
307    return cellularCallConnectionPtr_->StartDtmf(str, callInfo);
308}
309
310int32_t CarrierCall::StopDtmf()
311{
312    CellularCallInfo callInfo;
313    int32_t ret = PackCellularCallInfo(callInfo);
314    if (ret != TELEPHONY_SUCCESS) {
315        TELEPHONY_LOGW("PackCellularCallInfo failed!");
316    }
317    if (cellularCallConnectionPtr_ == nullptr) {
318        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
319        return TELEPHONY_ERR_LOCAL_PTR_NULL;
320    }
321    return cellularCallConnectionPtr_->StopDtmf(callInfo);
322}
323
324int32_t CarrierCall::PostDialProceed(bool proceed)
325{
326    CellularCallInfo callInfo;
327    int32_t ret = PackCellularCallInfo(callInfo);
328    if (ret != TELEPHONY_SUCCESS) {
329        TELEPHONY_LOGW("PackCellularCallInfo failed!");
330    }
331    if (cellularCallConnectionPtr_ == nullptr) {
332        TELEPHONY_LOGE("cellularCallConnectionPtr_ is nullptr!");
333        return TELEPHONY_ERR_LOCAL_PTR_NULL;
334    }
335    return cellularCallConnectionPtr_->PostDialProceed(callInfo, proceed);
336}
337
338void CarrierCall::SetSlotId(int32_t slotId)
339{
340    slotId_ = slotId;
341}
342
343void CarrierCall::SetCallIndex(int32_t index)
344{
345    index_ = index;
346}
347
348int32_t CarrierCall::GetCallIndex()
349{
350    return index_;
351}
352} // namespace Telephony
353} // namespace OHOS
354