/* * Copyright (C) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "call_status_manager.h" #include #include "audio_control_manager.h" #include "bluetooth_call_service.h" #include "call_control_manager.h" #include "call_manager_errors.h" #include "call_manager_hisysevent.h" #include "call_number_utils.h" #include "call_request_event_handler_helper.h" #include "core_service_client.h" #include "cs_call.h" #include "datashare_predicates.h" #include "hitrace_meter.h" #include "ims_call.h" #include "os_account_manager.h" #include "ott_call.h" #include "report_call_info_handler.h" #include "satellite_call.h" #include "satellite_call_control.h" #include "settings_datashare_helper.h" #include "telephony_log_wrapper.h" #include "call_number_utils.h" #include "voip_call.h" #include "uri.h" #include "ffrt.h" #include "parameters.h" #include "spam_call_adapter.h" #include "call_superprivacy_control_manager.h" #include "notification_helper.h" #include "call_voice_assistant_manager.h" namespace OHOS { namespace Telephony { constexpr int32_t INIT_INDEX = 0; CallStatusManager::CallStatusManager() { (void)memset_s(&callReportInfo_, sizeof(CallDetailInfo), 0, sizeof(CallDetailInfo)); for (int32_t i = 0; i < SLOT_NUM; i++) { (void)memset_s(&callDetailsInfo_[i], sizeof(CallDetailsInfo), 0, sizeof(CallDetailsInfo)); } } CallStatusManager::~CallStatusManager() { UnInit(); } int32_t CallStatusManager::Init() { for (int32_t i = 0; i < SLOT_NUM; i++) { callDetailsInfo_[i].callVec.clear(); } for (int32_t i = 0; i < SLOT_NUM; i++) { priorVideoState_[i] = VideoStateType::TYPE_VOICE; } mEventIdTransferMap_.clear(); mOttEventIdTransferMap_.clear(); InitCallBaseEvent(); CallIncomingFilterManagerPtr_ = (std::make_unique()).release(); return TELEPHONY_SUCCESS; } void CallStatusManager::InitCallBaseEvent() { mEventIdTransferMap_[RequestResultEventId::RESULT_DIAL_NO_CARRIER] = CallAbilityEventId::EVENT_DIAL_NO_CARRIER; mEventIdTransferMap_[RequestResultEventId::RESULT_HOLD_SEND_FAILED] = CallAbilityEventId::EVENT_HOLD_CALL_FAILED; mEventIdTransferMap_[RequestResultEventId::RESULT_SWAP_SEND_FAILED] = CallAbilityEventId::EVENT_SWAP_CALL_FAILED; mOttEventIdTransferMap_[OttCallEventId::OTT_CALL_EVENT_FUNCTION_UNSUPPORTED] = CallAbilityEventId::EVENT_OTT_FUNCTION_UNSUPPORTED; mEventIdTransferMap_[RequestResultEventId::RESULT_COMBINE_SEND_FAILED] = CallAbilityEventId::EVENT_COMBINE_CALL_FAILED; mEventIdTransferMap_[RequestResultEventId::RESULT_SPLIT_SEND_FAILED] = CallAbilityEventId::EVENT_SPLIT_CALL_FAILED; } int32_t CallStatusManager::UnInit() { for (int32_t i = 0; i < SLOT_NUM; i++) { callDetailsInfo_[i].callVec.clear(); } mEventIdTransferMap_.clear(); mOttEventIdTransferMap_.clear(); return TELEPHONY_SUCCESS; } int32_t CallStatusManager::HandleCallReportInfo(const CallDetailInfo &info) { int32_t ret = TELEPHONY_ERR_FAIL; callReportInfo_ = info; if (info.callType == CallType::TYPE_VOIP) { ret = HandleVoipCallReportInfo(info); return ret; } switch (info.state) { case TelCallState::CALL_STATUS_ACTIVE: ret = ActiveHandle(info); break; case TelCallState::CALL_STATUS_HOLDING: ret = HoldingHandle(info); break; case TelCallState::CALL_STATUS_DIALING: { ret = DialingHandle(info); FinishAsyncTrace(HITRACE_TAG_OHOS, "DialCall", getpid()); DelayedSingleton::GetInstance()->JudgingDialTimeOut( info.accountId, static_cast(info.callType), static_cast(info.callMode)); break; } case TelCallState::CALL_STATUS_ALERTING: ret = AlertHandle(info); break; case TelCallState::CALL_STATUS_INCOMING: { DelayedSingleton::GetInstance()->AcquireIncomingLock(); ret = IncomingHandle(info); DelayedSingleton::GetInstance()->ReleaseIncomingLock(); FinishAsyncTrace(HITRACE_TAG_OHOS, "InComingCall", getpid()); DelayedSingleton::GetInstance()->JudgingIncomingTimeOut( info.accountId, static_cast(info.callType), static_cast(info.callMode)); break; } case TelCallState::CALL_STATUS_WAITING: ret = WaitingHandle(info); break; case TelCallState::CALL_STATUS_DISCONNECTED: ret = DisconnectedHandle(info); break; case TelCallState::CALL_STATUS_DISCONNECTING: ret = DisconnectingHandle(info); break; default: TELEPHONY_LOGE("Invalid call state!"); break; } TELEPHONY_LOGI("Entry CallStatusManager HandleCallReportInfo"); HandleDsdaInfo(info.accountId); DelayedSingleton::GetInstance()->GetCallState(); TELEPHONY_LOGI("End CallStatusManager HandleCallReportInfo"); return ret; } void CallStatusManager::HandleDsdaInfo(int32_t slotId) { int32_t dsdsMode = DSDS_MODE_V2; bool noOtherCall = true; std::list callIdList; GetCarrierCallList(callIdList); int32_t currentCallNum = GetCurrentCallNum(); DelayedSingleton::GetInstance()->IsExistCallOtherSlot(callIdList, slotId, noOtherCall); DelayedRefSingleton::GetInstance().GetDsdsMode(dsdsMode); TELEPHONY_LOGI("dsdsMode:%{public}d", dsdsMode); if ((dsdsMode == static_cast(DsdsMode::DSDS_MODE_V5_DSDA) || dsdsMode == static_cast(DsdsMode::DSDS_MODE_V5_TDM)) && !noOtherCall) { TELEPHONY_LOGI("Handle DsdaCallInfo"); sptr holdCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD); if (holdCall != nullptr && currentCallNum > CALL_NUMBER) { holdCall->SetCanUnHoldState(false); } } } // handle call state changes, incoming call, outgoing call. int32_t CallStatusManager::HandleCallsReportInfo(const CallDetailsInfo &info) { bool flag = false; TELEPHONY_LOGI("call list size:%{public}zu,slotId:%{public}d", info.callVec.size(), info.slotId); int32_t curSlotId = info.slotId; if (!DelayedSingleton::GetInstance()->IsValidSlotId(curSlotId)) { TELEPHONY_LOGE("invalid slotId!"); return CALL_ERR_INVALID_SLOT_ID; } for (auto &it : info.callVec) { for (const auto &it1 : callDetailsInfo_[curSlotId].callVec) { if (it.index == it1.index) { // call state changes if (it.state != it1.state || it.mpty != it1.mpty || it.callType != it1.callType || it.callMode != it1.callMode || it.state == TelCallState::CALL_STATUS_ALERTING) { TELEPHONY_LOGI("handle updated call state:%{public}d", it.state); HandleCallReportInfo(it); } flag = true; break; } } // incoming/outgoing call handle if (!flag || callDetailsInfo_[curSlotId].callVec.empty()) { TELEPHONY_LOGI("handle new call state:%{public}d", it.state); HandleCallReportInfo(it); } flag = false; } // disconnected calls handle for (auto &it2 : callDetailsInfo_[curSlotId].callVec) { for (const auto &it3 : info.callVec) { if (it2.index == it3.index) { TELEPHONY_LOGI("state:%{public}d", it2.state); flag = true; break; } } if (!flag) { it2.state = TelCallState::CALL_STATUS_DISCONNECTED; HandleCallReportInfo(it2); } flag = false; } callDetailsInfo_[curSlotId].callVec.clear(); callDetailsInfo_[curSlotId] = info; auto condition = [](CallDetailInfo i) { return i.state == TelCallState::CALL_STATUS_DISCONNECTED; }; auto it_end = std::remove_if(callDetailsInfo_[curSlotId].callVec.begin(), callDetailsInfo_[curSlotId].callVec.end(), condition); callDetailsInfo_[curSlotId].callVec.erase(it_end, callDetailsInfo_[curSlotId].callVec.end()); TELEPHONY_LOGI("End CallStatusManager HandleCallsReportInfo slotId:%{public}d, " "callDetailsInfo_ size:%{public}zu", info.slotId, callDetailsInfo_[curSlotId].callVec.size()); return TELEPHONY_SUCCESS; } int32_t CallStatusManager::HandleVoipCallReportInfo(const CallDetailInfo &info) { TELEPHONY_LOGI("Entry CallStatusManager HandleVoipCallReportInfo"); int32_t ret = TELEPHONY_ERR_FAIL; switch (info.state) { case TelCallState::CALL_STATUS_ACTIVE: ret = ActiveVoipCallHandle(info); break; case TelCallState::CALL_STATUS_INCOMING: { ret = IncomingVoipCallHandle(info); break; } case TelCallState::CALL_STATUS_DISCONNECTED: ret = DisconnectedVoipCallHandle(info); break; case TelCallState::CALL_STATUS_DIALING: ret = OutgoingVoipCallHandle(info); break; case TelCallState::CALL_STATUS_ANSWERED: ret = AnsweredVoipCallHandle(info); break; case TelCallState::CALL_STATUS_DISCONNECTING: ret = DisconnectingVoipCallHandle(info); break; default: TELEPHONY_LOGE("Invalid call state!"); break; } return ret; } int32_t CallStatusManager::HandleDisconnectedCause(const DisconnectedDetails &details) { bool ret = DelayedSingleton::GetInstance()->NotifyCallDestroyed(details); if (!ret) { TELEPHONY_LOGI("NotifyCallDestroyed failed!"); return CALL_ERR_PHONE_CALLSTATE_NOTIFY_FAILED; } return TELEPHONY_SUCCESS; } int32_t CallStatusManager::HandleEventResultReportInfo(const CellularCallEventInfo &info) { if (info.eventType != CellularCallEventType::EVENT_REQUEST_RESULT_TYPE) { TELEPHONY_LOGE("unexpected type event occurs, eventId:%{public}d", info.eventId); return CALL_ERR_PHONE_TYPE_UNEXPECTED; } TELEPHONY_LOGI("recv one Event, eventId:%{public}d", info.eventId); sptr call = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_DIALING); if (call != nullptr) { int32_t ret = DealFailDial(call); TELEPHONY_LOGI("DealFailDial ret:%{public}d", ret); } CallEventInfo eventInfo; (void)memset_s(&eventInfo, sizeof(CallEventInfo), 0, sizeof(CallEventInfo)); if (mEventIdTransferMap_.find(info.eventId) != mEventIdTransferMap_.end()) { eventInfo.eventId = mEventIdTransferMap_[info.eventId]; DialParaInfo dialInfo; if (eventInfo.eventId == CallAbilityEventId::EVENT_DIAL_NO_CARRIER) { DelayedSingleton::GetInstance()->GetDialParaInfo(dialInfo); if (dialInfo.number.length() > static_cast(kMaxNumberLen)) { TELEPHONY_LOGE("Number out of limit!"); return CALL_ERR_NUMBER_OUT_OF_RANGE; } if (memcpy_s(eventInfo.phoneNum, kMaxNumberLen, dialInfo.number.c_str(), dialInfo.number.length()) != EOK) { TELEPHONY_LOGE("memcpy_s failed!"); return TELEPHONY_ERR_MEMCPY_FAIL; } } else if (eventInfo.eventId == CallAbilityEventId::EVENT_COMBINE_CALL_FAILED) { sptr activeCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_ACTIVE); if (activeCall != nullptr) { activeCall->HandleCombineConferenceFailEvent(); } } else if (eventInfo.eventId == CallAbilityEventId::EVENT_HOLD_CALL_FAILED) { needWaitHold_ = false; } DelayedSingleton::GetInstance()->NotifyCallEventUpdated(eventInfo); } else { TELEPHONY_LOGW("unknown type Event, eventid %{public}d", info.eventId); } return TELEPHONY_SUCCESS; } int32_t CallStatusManager::HandleOttEventReportInfo(const OttCallEventInfo &info) { TELEPHONY_LOGI("recv one Event, eventId:%{public}d", info.ottCallEventId); CallEventInfo eventInfo; (void)memset_s(&eventInfo, sizeof(CallEventInfo), 0, sizeof(CallEventInfo)); if (mOttEventIdTransferMap_.find(info.ottCallEventId) != mOttEventIdTransferMap_.end()) { eventInfo.eventId = mOttEventIdTransferMap_[info.ottCallEventId]; if (strlen(info.bundleName) > static_cast(kMaxNumberLen)) { TELEPHONY_LOGE("Number out of limit!"); return CALL_ERR_NUMBER_OUT_OF_RANGE; } if (memcpy_s(eventInfo.bundleName, kMaxNumberLen, info.bundleName, strlen(info.bundleName)) != EOK) { TELEPHONY_LOGE("memcpy_s failed!"); return TELEPHONY_ERR_MEMCPY_FAIL; } DelayedSingleton::GetInstance()->NotifyCallEventUpdated(eventInfo); } else { TELEPHONY_LOGW("unknown type Event, eventid %{public}d", info.ottCallEventId); } return TELEPHONY_SUCCESS; } int32_t CallStatusManager::HandleVoipEventReportInfo(const VoipCallEventInfo &info) { TELEPHONY_LOGI("recv one Event, eventId:%{public}d", info.voipCallEvent); sptr call = GetOneCallObjectByVoipCallId(info.voipCallId, info.bundleName, info.uid); if (call == nullptr) { TELEPHONY_LOGE("voip call is null"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (call->GetCallRunningState() != CallRunningState::CALL_RUNNING_STATE_ACTIVE && call->GetCallRunningState() != CallRunningState::CALL_RUNNING_STATE_DIALING) { return TELEPHONY_ERR_FAIL; } if (info.voipCallEvent == VoipCallEvent::VOIP_CALL_EVENT_MUTED) { call->SetMicPhoneState(true); } else if (info.voipCallEvent == VoipCallEvent::VOIP_CALL_EVENT_UNMUTED) { call->SetMicPhoneState(false); } DelayedSingleton::GetInstance()->ReportAudioDeviceInfo(call); return TELEPHONY_SUCCESS; } int32_t CallStatusManager::IncomingHandle(const CallDetailInfo &info) { sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call != nullptr) { auto oldCallType = call->GetCallType(); auto videoState = call->GetVideoStateType(); if (oldCallType != info.callType || call->GetTelCallState() != info.state || videoState != info.callMode) { call = RefreshCallIfNecessary(call, info); if (oldCallType != info.callType || videoState != info.callMode) { return UpdateCallState(call, info.state); } } return TELEPHONY_SUCCESS; } int32_t ret = TELEPHONY_SUCCESS; if (info.callType == CallType::TYPE_CS || info.callType == CallType::TYPE_IMS || info.callType == CallType::TYPE_SATELLITE) { ret = IncomingFilterPolicy(info); if (ret != TELEPHONY_SUCCESS) { return ret; } } call = CreateNewCall(info, CallDirection::CALL_DIRECTION_IN); if (call == nullptr) { TELEPHONY_LOGE("CreateNewCall failed!"); return CALL_ERR_CALL_OBJECT_IS_NULL; } SetContactInfo(call, std::string(info.phoneNum)); bool block = false; if (IsRejectCall(call, info, block)) { return HandleRejectCall(call, block); } if (info.callType != CallType::TYPE_VOIP && IsRingOnceCall(call, info)) { return HandleRingOnceCall(call); } AddOneCallObject(call); DelayedSingleton::GetInstance()->NotifyNewCallCreated(call); CarrierAndVoipConflictProcess(call->GetCallID()); ret = UpdateCallState(call, info.state); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed!"); return ret; } ret = FilterResultsDispose(call); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("FilterResultsDispose failed!"); } return ret; } void CallStatusManager::CarrierAndVoipConflictProcess(int32_t callId) { DelayedSingleton::GetInstance()->CarrierAndVoipConflictProcess(callId, TelCallState::CALL_STATUS_INCOMING); } void CallStatusManager::SetContactInfo(sptr &call, std::string phoneNum) { if (call == nullptr) { TELEPHONY_LOGE("CreateVoipCall failed!"); return; } ffrt::submit([=, &call]() { sptr callObjectPtr = call; // allow list filtering // Get the contact data from the database ContactInfo contactInfo = { .name = "", .number = phoneNum, .isContacterExists = false, .ringtonePath = "", .isSendToVoicemail = false, .isEcc = false, .isVoiceMail = false, .isQueryComplete = true, }; QueryCallerInfo(contactInfo, phoneNum); callObjectPtr->SetCallerInfo(contactInfo); CallVoiceAssistantManager::GetInstance()->UpdateContactInfo(contactInfo, callObjectPtr->GetCallID()); }); } int32_t CallStatusManager::HandleRejectCall(sptr &call, bool isBlock) { if (call == nullptr) { TELEPHONY_LOGE("call is nullptr!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } int32_t ret = call->SetTelCallState(TelCallState::CALL_STATUS_INCOMING); if (ret != TELEPHONY_SUCCESS && ret != CALL_ERR_NOT_NEW_STATE) { TELEPHONY_LOGE("Set CallState failed!"); return ret; } ret = call->RejectCall(); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("RejectCall failed!"); return ret; } if (isBlock) { return DelayedSingleton::GetInstance()->AddBlockLogAndNotification(call); } return DelayedSingleton::GetInstance()->AddCallLogAndNotification(call); } int32_t CallStatusManager::IncomingVoipCallHandle(const CallDetailInfo &info) { int32_t ret = TELEPHONY_ERROR; sptr call = GetOneCallObjectByVoipCallId( info.voipCallInfo.voipCallId, info.voipCallInfo.voipBundleName, info.voipCallInfo.uid); if (call != nullptr) { return TELEPHONY_SUCCESS; } call = CreateNewCall(info, CallDirection::CALL_DIRECTION_IN); if (call == nullptr) { TELEPHONY_LOGE("CreateVoipCall failed!"); return CALL_ERR_CALL_OBJECT_IS_NULL; } AddOneCallObject(call); DelayedSingleton::GetInstance()->NotifyNewCallCreated(call); ret = UpdateCallState(call, info.state); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed!"); return ret; } return ret; } int32_t CallStatusManager::OutgoingVoipCallHandle(const CallDetailInfo &info) { int32_t ret = TELEPHONY_ERROR; sptr call = GetOneCallObjectByVoipCallId( info.voipCallInfo.voipCallId, info.voipCallInfo.voipBundleName, info.voipCallInfo.uid); if (call != nullptr) { VideoStateType originalType = call->GetVideoStateType(); if (originalType != info.callMode) { TELEPHONY_LOGI("change VideoStateType from %{public}d to %{public}d", static_cast(originalType), static_cast(info.callMode)); call->SetVideoStateType(info.callMode); return UpdateCallState(call, info.state); } return TELEPHONY_SUCCESS; } call = CreateNewCall(info, CallDirection::CALL_DIRECTION_OUT); if (call == nullptr) { TELEPHONY_LOGE("CreateVoipCall failed!"); return CALL_ERR_CALL_OBJECT_IS_NULL; } AddOneCallObject(call); DelayedSingleton::GetInstance()->NotifyNewCallCreated(call); ret = UpdateCallState(call, info.state); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed!"); return ret; } return ret; } int32_t CallStatusManager::AnsweredVoipCallHandle(const CallDetailInfo &info) { int32_t ret = TELEPHONY_ERROR; sptr call = GetOneCallObjectByVoipCallId( info.voipCallInfo.voipCallId, info.voipCallInfo.voipBundleName, info.voipCallInfo.uid); if (call == nullptr) { return ret; } if (DelayedSingleton::GetInstance()->NotifyCallStateUpdated( call, TelCallState::CALL_STATUS_INCOMING, TelCallState::CALL_STATUS_ANSWERED)) { return TELEPHONY_SUCCESS; } else { return ret; } } int32_t CallStatusManager::DisconnectingVoipCallHandle(const CallDetailInfo &info) { sptr call = GetOneCallObjectByVoipCallId( info.voipCallInfo.voipCallId, info.voipCallInfo.voipBundleName, info.voipCallInfo.uid); if (call == nullptr) { return TELEPHONY_ERROR; } return UpdateCallState(call, TelCallState::CALL_STATUS_DISCONNECTING); } void CallStatusManager::QueryCallerInfo(ContactInfo &contactInfo, std::string phoneNum) { TELEPHONY_LOGI("Entry CallStatusManager QueryCallerInfo"); std::shared_ptr callDataPtr = DelayedSingleton::GetInstance(); if (callDataPtr == nullptr) { TELEPHONY_LOGE("callDataPtr is nullptr!"); return; } DataShare::DataSharePredicates predicates; predicates.EqualTo(DETAIL_INFO, phoneNum); predicates.And(); predicates.EqualTo(CONTENT_TYPE, PHONE); bool ret = callDataPtr->Query(contactInfo, predicates); if (!ret) { TELEPHONY_LOGE("Query contact database fail!"); } } int32_t CallStatusManager::IncomingFilterPolicy(const CallDetailInfo &info) { if (CallIncomingFilterManagerPtr_ == nullptr) { TELEPHONY_LOGE("CallIncomingFilterManagerPtr_ is null"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } return CallIncomingFilterManagerPtr_->DoIncomingFilter(info); } void CallStatusManager::CallFilterCompleteResult(const CallDetailInfo &info) { int32_t ret = TELEPHONY_ERR_FAIL; sptr call = CreateNewCall(info, CallDirection::CALL_DIRECTION_IN); if (call == nullptr) { TELEPHONY_LOGE("CreateNewCall failed!"); return; } AddOneCallObject(call); #ifdef ABILITY_DATABASE_SUPPORT // allow list filtering // Get the contact data from the database GetCallerInfoDate(ContactInfo); SetCallerInfo(contactInfo); #endif DelayedSingleton::GetInstance()->NotifyNewCallCreated(call); ret = UpdateCallState(call, info.state); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed!"); return; } ret = FilterResultsDispose(call); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("FilterResultsDispose failed!"); return; } } int32_t CallStatusManager::UpdateDialingCallInfo(const CallDetailInfo &info) { sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call != nullptr) { call = RefreshCallIfNecessary(call, info); return TELEPHONY_SUCCESS; } call = GetOneCallObjectByIndex(INIT_INDEX); if (call == nullptr) { TELEPHONY_LOGE("call is nullptr"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } std::string oriNum = call->GetAccountNumber(); call = RefreshCallIfNecessary(call, info); call->SetCallIndex(info.index); call->SetBundleName(info.bundleName); call->SetSlotId(info.accountId); call->SetTelCallState(info.state); call->SetVideoStateType(info.callMode); call->SetCallType(info.callType); call->SetAccountNumber(oriNum); return TELEPHONY_SUCCESS; } int32_t CallStatusManager::DialingHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle dialing state"); if (info.index > 0) { sptr call = GetOneCallObjectByIndexAndSlotId(INIT_INDEX, info.accountId); if (call == nullptr) { call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); } if (call != nullptr) { TELEPHONY_LOGI("need update call info"); return UpdateDialingCallInfo(info); } } sptr call = CreateNewCall(info, CallDirection::CALL_DIRECTION_OUT); if (call == nullptr) { TELEPHONY_LOGE("CreateNewCall failed!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } AddOneCallObject(call); auto callRequestEventHandler = DelayedSingleton::GetInstance(); callRequestEventHandler->RestoreDialingFlag(false); callRequestEventHandler->RemoveEventHandlerTask(); int32_t ret = call->DialingProcess(); if (ret != TELEPHONY_SUCCESS) { return ret; } DelayedSingleton::GetInstance()->NotifyNewCallCreated(call); ret = UpdateCallState(call, TelCallState::CALL_STATUS_DIALING); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); } return ret; } int32_t CallStatusManager::ActiveHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle active state"); std::string tmpStr(info.phoneNum); sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } call = RefreshCallIfNecessary(call, info); SetOriginalCallTypeForActiveState(call); // call state change active, need to judge if launching a conference if (info.mpty == 1) { int32_t mainCallId = ERR_ID; call->LaunchConference(); call->GetMainCallId(mainCallId); sptr mainCall = GetOneCallObject(mainCallId); if (mainCall != nullptr) { mainCall->SetTelConferenceState(TelConferenceState::TEL_CONFERENCE_ACTIVE); } } else if (call->ExitConference() == TELEPHONY_SUCCESS) { TELEPHONY_LOGI("SubCallSeparateFromConference success!"); } else { TELEPHONY_LOGI("SubCallSeparateFromConference fail!"); } int32_t ret = UpdateCallState(call, TelCallState::CALL_STATUS_ACTIVE); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); return ret; } sptr holdCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD); if (holdCall != nullptr) { holdCall->SetCanSwitchCallState(true); TELEPHONY_LOGI("holdcall:%{public}d can swap", holdCall->GetCallID()); } #ifdef AUDIO_SUPPORT ToSpeakerPhone(call); DelayedSingleton::GetInstance()->SetVolumeAudible(); #endif TELEPHONY_LOGI("handle active state success"); return ret; } int32_t CallStatusManager::ActiveVoipCallHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle active state"); sptr call = GetOneCallObjectByVoipCallId( info.voipCallInfo.voipCallId, info.voipCallInfo.voipBundleName, info.voipCallInfo.uid); if (call == nullptr) { TELEPHONY_LOGE("voip Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } VideoStateType originalType = call->GetVideoStateType(); if (originalType != info.callMode) { TELEPHONY_LOGI("change VideoStateType from %{public}d to %{public}d", static_cast(originalType), static_cast(info.callMode)); call->SetVideoStateType(info.callMode); } int32_t ret = UpdateCallState(call, TelCallState::CALL_STATUS_ACTIVE); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); return ret; } TELEPHONY_LOGI("handle active state success"); return ret; } int32_t CallStatusManager::HoldingHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle holding state"); std::string tmpStr(info.phoneNum); sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } // if the call is in a conference, it will exit, otherwise just set it holding call = RefreshCallIfNecessary(call, info); if (info.mpty == 1) { int32_t ret = call->HoldConference(); if (ret == TELEPHONY_SUCCESS) { TELEPHONY_LOGI("HoldConference success"); } } TelCallState priorState = call->GetTelCallState(); int32_t ret = UpdateCallState(call, TelCallState::CALL_STATUS_HOLDING); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); } int32_t callId = call->GetCallID(); int32_t dsdsMode = DSDS_MODE_V2; DelayedRefSingleton::GetInstance().GetDsdsMode(dsdsMode); TELEPHONY_LOGE("HoldingHandle dsdsMode:%{public}d", dsdsMode); bool canSwitchCallState = call->GetCanSwitchCallState(); if (dsdsMode == static_cast(DsdsMode::DSDS_MODE_V5_DSDA) || dsdsMode == static_cast(DsdsMode::DSDS_MODE_V5_TDM)) { int32_t activeCallNum = GetCallNum(TelCallState::CALL_STATUS_ACTIVE); if (needWaitHold_ && activeCallNum == 0) { needWaitHold_ = false; int32_t result = DelayedSingleton::GetInstance()->Dial(GetDialCallInfo()); sptr dialCall = GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_DIALING); if (result != TELEPHONY_SUCCESS && dialCall != nullptr) { DealFailDial(call); TELEPHONY_LOGI("Dial call fail"); } } else { TelConferenceState confState = call->GetTelConferenceState(); int32_t conferenceId = ERR_ID; call->GetMainCallId(conferenceId); if (confState != TelConferenceState::TEL_CONFERENCE_IDLE && conferenceId == callId) { AutoHandleForDsda(canSwitchCallState, priorState, activeCallNum, call->GetSlotId(), false); } else if (confState == TelConferenceState::TEL_CONFERENCE_IDLE) { AutoHandleForDsda(canSwitchCallState, priorState, activeCallNum, call->GetSlotId(), false); } } } return ret; } int32_t CallStatusManager::WaitingHandle(const CallDetailInfo &info) { DelayedSingleton::GetInstance()->AcquireIncomingLock(); int32_t ret = IncomingHandle(info); DelayedSingleton::GetInstance()->ReleaseIncomingLock(); return ret; } int32_t CallStatusManager::AlertHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle alerting state"); std::string tmpStr(info.phoneNum); sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } call = RefreshCallIfNecessary(call, info); int32_t ret = UpdateCallState(call, TelCallState::CALL_STATUS_ALERTING); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); return ret; } #ifdef AUDIO_SUPPORT ToSpeakerPhone(call); TurnOffMute(call); DelayedSingleton::GetInstance()->SetVolumeAudible(); #endif return ret; } int32_t CallStatusManager::DisconnectingHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle disconnecting state"); std::string tmpStr(info.phoneNum); sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } call = RefreshCallIfNecessary(call, info); SetOriginalCallTypeForDisconnectState(call); int32_t ret = UpdateCallState(call, TelCallState::CALL_STATUS_DISCONNECTING); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); } return ret; } int32_t CallStatusManager::DisconnectedVoipCallHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle disconnected voip call state"); sptr call = GetOneCallObjectByVoipCallId( info.voipCallInfo.voipCallId, info.voipCallInfo.voipBundleName, info.voipCallInfo.uid); if (call == nullptr) { TELEPHONY_LOGE("voip Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } int32_t ret = UpdateCallState(call, TelCallState::CALL_STATUS_DISCONNECTED); if (ret != TELEPHONY_SUCCESS) { TELEPHONY_LOGE("UpdateCallState failed, errCode:%{public}d", ret); return ret; } DeleteOneCallObject(call->GetCallID()); TELEPHONY_LOGI("handle disconnected voip call state success"); return ret; } int32_t CallStatusManager::DisconnectedHandle(const CallDetailInfo &info) { TELEPHONY_LOGI("handle disconnected state"); if (timeWaitHelper_ != nullptr) { TELEPHONY_LOGI("ringtone once"); timeWaitHelper_->NotifyAll(); timeWaitHelper_ = nullptr; } std::string tmpStr(info.phoneNum); sptr call = GetOneCallObjectByIndexAndSlotId(info.index, info.accountId); if (call == nullptr) { TELEPHONY_LOGE("call is null"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } call = RefreshCallIfNecessary(call, info); SetOriginalCallTypeForDisconnectState(call); std::vector callIdList; call->GetSubCallIdList(callIdList); CallRunningState previousState = call->GetCallRunningState(); call->ExitConference(); TelCallState priorState = call->GetTelCallState(); UpdateCallState(call, TelCallState::CALL_STATUS_DISCONNECTED); HandleHoldCallOrAutoAnswerCall(call, callIdList, previousState, priorState); int32_t currentCallNum = CallObjectManager::GetCurrentCallNum(); if (currentCallNum <= 0) { DelayedSingleton::GetInstance()->RestoreSuperPrivacyMode(); } return TELEPHONY_SUCCESS; } void CallStatusManager::HandleHoldCallOrAutoAnswerCall(const sptr call, std::vector callIdList, CallRunningState previousState, TelCallState priorState) { if (call == nullptr) { TELEPHONY_LOGE("call is null"); return; } bool canUnHold = false; size_t size = callIdList.size(); int32_t activeCallNum = GetCallNum(TelCallState::CALL_STATUS_ACTIVE); int32_t waitingCallNum = GetCallNum(TelCallState::CALL_STATUS_WAITING); IsCanUnHold(activeCallNum, waitingCallNum, size, canUnHold); sptr holdCall = CallObjectManager::GetOneCallObject(CallRunningState::CALL_RUNNING_STATE_HOLD); if (previousState != CallRunningState::CALL_RUNNING_STATE_HOLD && previousState != CallRunningState::CALL_RUNNING_STATE_ACTIVE && priorState == TelCallState::CALL_STATUS_DISCONNECTING) { if (holdCall != nullptr && canUnHold && holdCall->GetCanUnHoldState()) { if (holdCall->GetSlotId() == call->GetSlotId()) { TELEPHONY_LOGI("release call and recover the held call"); holdCall->UnHoldCall(); } } } DeleteOneCallObject(call->GetCallID()); int32_t dsdsMode = DSDS_MODE_V2; DelayedRefSingleton::GetInstance().GetDsdsMode(dsdsMode); if (dsdsMode == DSDS_MODE_V3) { AutoAnswer(activeCallNum, waitingCallNum); } else if (dsdsMode == static_cast(DsdsMode::DSDS_MODE_V5_DSDA) || dsdsMode == static_cast(DsdsMode::DSDS_MODE_V5_TDM)) { bool canSwitchCallState = call->GetCanSwitchCallState(); AutoHandleForDsda(canSwitchCallState, priorState, activeCallNum, call->GetSlotId(), true); } } void CallStatusManager::IsCanUnHold(int32_t activeCallNum, int32_t waitingCallNum, int32_t size, bool &canUnHold) { int32_t incomingCallNum = GetCallNum(TelCallState::CALL_STATUS_INCOMING); int32_t answeredCallNum = GetCallNum(TelCallState::CALL_STATUS_ANSWERED); int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING); if (answeredCallNum == 0 && incomingCallNum == 0 && (size == 0 || size == 1) && activeCallNum == 0 && waitingCallNum == 0 && dialingCallNum == 0) { canUnHold = true; } TELEPHONY_LOGI("CanUnHold state: %{public}d", canUnHold); } void CallStatusManager::AutoHandleForDsda( bool canSwitchCallState, TelCallState priorState, int32_t activeCallNum, int32_t slotId, bool continueAnswer) { int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING); int32_t alertingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING); std::list callIdList; GetCarrierCallList(callIdList); for (int32_t ringCallId : callIdList) { sptr ringCall = GetOneCallObject(ringCallId); if (ringCall != nullptr && ringCall->GetAutoAnswerState()) { TELEPHONY_LOGI("ringCall is not nullptr"); int32_t videoState = static_cast(ringCall->GetVideoStateType()); if (videoState == static_cast(VideoStateType::TYPE_VIDEO)) { TELEPHONY_LOGI("AutoAnswer VideoCall for Dsda"); AutoAnswerForVideoCall(activeCallNum); AutoUnHoldForDsda(canSwitchCallState, priorState, activeCallNum, slotId); return; } if (dialingCallNum == 0 && alertingCallNum == 0 && activeCallNum == 0 && ringCall->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_RINGING) { TELEPHONY_LOGI("AutoAnswer VoiceCall for Dsda"); AutoAnswerForVoiceCall(ringCall, slotId, continueAnswer); AutoUnHoldForDsda(canSwitchCallState, priorState, activeCallNum, slotId); return; } } } AutoUnHoldForDsda(canSwitchCallState, priorState, activeCallNum, slotId); } void CallStatusManager::AutoUnHoldForDsda( bool canSwitchCallState, TelCallState priorState, int32_t activeCallNum, int32_t slotId) { int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING); int32_t waitingCallNum = GetCallNum(TelCallState::CALL_STATUS_WAITING); int32_t callNum = 2; std::list callIdList; GetCarrierCallList(callIdList); int32_t currentCallNum = GetCurrentCallNum(); for (int32_t otherCallId : callIdList) { sptr otherCall = GetOneCallObject(otherCallId); if (otherCall == nullptr) { TELEPHONY_LOGE("otherCall is nullptr"); continue; } TelCallState state = otherCall->GetTelCallState(); TelConferenceState confState = otherCall->GetTelConferenceState(); int32_t conferenceId = ERR_ID; otherCall->GetMainCallId(conferenceId); if (slotId != otherCall->GetSlotId() && state == TelCallState::CALL_STATUS_HOLDING && otherCall->GetCanUnHoldState() && activeCallNum == 0 && waitingCallNum == 0 && dialingCallNum == 0 && ((confState != TelConferenceState::TEL_CONFERENCE_IDLE && conferenceId == otherCallId) || confState == TelConferenceState::TEL_CONFERENCE_IDLE)) { // Actively hang up the processing unhold state or exchange call if (priorState == TelCallState::CALL_STATUS_DISCONNECTING || (!canSwitchCallState && currentCallNum == callNum)) { otherCall->UnHoldCall(); return; } } } for (int32_t otherCallId : callIdList) { sptr holdCall = GetOneCallObject(otherCallId); if (holdCall != nullptr && holdCall->GetTelCallState() == TelCallState::CALL_STATUS_HOLDING) { if (currentCallNum == callNum) { holdCall->SetCanUnHoldState(true); } } } } void CallStatusManager::AutoAnswerForVoiceCall(sptr ringCall, int32_t slotId, bool continueAnswer) { /* Need to check whether the autoAnswer call and the holding call are on the same slotid * To prevent repeated AT command delivery. */ if (continueAnswer || slotId != ringCall->GetSlotId()) { DelayedSingleton::GetInstance()->NotifyCallStateUpdated( ringCall, TelCallState::CALL_STATUS_INCOMING, TelCallState::CALL_STATUS_ANSWERED); int ret = ringCall->AnswerCall(ringCall->GetAnswerVideoState()); if (ret == TELEPHONY_SUCCESS) { DelayedSingleton::GetInstance()->NotifyIncomingCallAnswered(ringCall); } TELEPHONY_LOGI("ret = %{public}d", ret); } ringCall->SetAutoAnswerState(false); } void CallStatusManager::AutoAnswerForVideoCall(int32_t activeCallNum) { int32_t holdingCallNum = GetCallNum(TelCallState::CALL_STATUS_HOLDING); int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING); int32_t alertingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING); if (activeCallNum == 0 && holdingCallNum == 0 && dialingCallNum == 0 && alertingCallNum == 0) { std::list ringCallIdList; GetCarrierCallList(ringCallIdList); for (int32_t ringingCallId : ringCallIdList) { sptr ringingCall = GetOneCallObject(ringingCallId); if (ringingCall == nullptr) { TELEPHONY_LOGE("ringingCall is nullptr"); return; } CallRunningState ringingCallState = ringingCall->GetCallRunningState(); if ((ringingCallState == CallRunningState::CALL_RUNNING_STATE_RINGING && (ringingCall->GetAutoAnswerState()))) { ringingCall->SetAutoAnswerState(false); int ret = ringingCall->AnswerCall(ringingCall->GetAnswerVideoState()); TELEPHONY_LOGI("ret = %{public}d", ret); break; } } } } void CallStatusManager::AutoAnswer(int32_t activeCallNum, int32_t waitingCallNum) { int32_t holdingCallNum = GetCallNum(TelCallState::CALL_STATUS_HOLDING); int32_t dialingCallNum = GetCallNum(TelCallState::CALL_STATUS_DIALING); int32_t alertingCallNum = GetCallNum(TelCallState::CALL_STATUS_ALERTING); if (activeCallNum == 0 && waitingCallNum == 0 && holdingCallNum == 0 && dialingCallNum == 0 && alertingCallNum == 0) { std::list ringCallIdList; GetCarrierCallList(ringCallIdList); for (int32_t ringingCallId : ringCallIdList) { sptr ringingCall = GetOneCallObject(ringingCallId); if (ringingCall == nullptr) { TELEPHONY_LOGE("ringingCall is nullptr"); return; } CallRunningState ringingCallState = ringingCall->GetCallRunningState(); if ((ringingCallState == CallRunningState::CALL_RUNNING_STATE_RINGING && (ringingCall->GetAutoAnswerState()))) { ringingCall->SetAutoAnswerState(false); int ret = ringingCall->AnswerCall(ringingCall->GetAnswerVideoState()); TELEPHONY_LOGI("ret = %{public}d", ret); break; } } } } int32_t CallStatusManager::UpdateCallState(sptr &call, TelCallState nextState) { TELEPHONY_LOGI("UpdateCallState start"); if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } TelCallState priorState = call->GetTelCallState(); VideoStateType videoState = call->GetVideoStateType(); TELEPHONY_LOGI( "callIndex:%{public}d, callId:%{public}d, priorState:%{public}d, nextState:%{public}d, videoState:%{public}d", call->GetCallIndex(), call->GetCallID(), priorState, nextState, videoState); if (call->GetCallType() == CallType::TYPE_SATELLITE) { DelayedSingleton::GetInstance()-> HandleSatelliteCallStateUpdate(call, priorState, nextState); } if (priorState == TelCallState::CALL_STATUS_INCOMING && nextState == TelCallState::CALL_STATUS_ACTIVE) { DelayedSingleton::GetInstance()->JudgingAnswerTimeOut( call->GetSlotId(), call->GetCallID(), static_cast(call->GetVideoStateType())); } int32_t ret = call->SetTelCallState(nextState); UpdateOneCallObjectByCallId(call->GetCallID(), nextState); if (ret != TELEPHONY_SUCCESS && ret != CALL_ERR_NOT_NEW_STATE) { TELEPHONY_LOGE("SetTelCallState failed"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (!DelayedSingleton::GetInstance()->NotifyCallStateUpdated(call, priorState, nextState)) { TELEPHONY_LOGE( "NotifyCallStateUpdated failed! priorState:%{public}d,nextState:%{public}d", priorState, nextState); if (nextState == TelCallState::CALL_STATUS_INCOMING) { CallManagerHisysevent::WriteIncomingCallFaultEvent(call->GetSlotId(), static_cast(call->GetCallType()), static_cast(call->GetVideoStateType()), ret, "NotifyCallStateUpdated failed"); } return CALL_ERR_PHONE_CALLSTATE_NOTIFY_FAILED; } SetVideoCallState(call, nextState); return TELEPHONY_SUCCESS; } void CallStatusManager::SetVideoCallState(sptr &call, TelCallState nextState) { if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return; } int slotId = call->GetSlotId(); bool isSlotIdValid = false; if (slotId < SLOT_NUM && slotId >= 0) { isSlotIdValid = true; } VideoStateType videoState = call->GetVideoStateType(); TELEPHONY_LOGI("nextVideoState:%{public}d, priorVideoState:%{public}d, isSlotIdValid:%{public}d", videoState, priorVideoState_[slotId], isSlotIdValid); if (isSlotIdValid && (priorVideoState_[slotId] != videoState)) { DelayedSingleton::GetInstance()->VideoStateUpdated( call, priorVideoState_[slotId], videoState); priorVideoState_[slotId] = videoState; } if (isSlotIdValid && (nextState == TelCallState::CALL_STATUS_DISCONNECTED)) { priorVideoState_[slotId] = VideoStateType::TYPE_VOICE; } } sptr CallStatusManager::RefreshCallIfNecessary(const sptr &call, const CallDetailInfo &info) { TELEPHONY_LOGI("RefreshCallIfNecessary"); if (call->GetCallType() == CallType::TYPE_IMS && call->GetVideoStateType() != info.callMode) { call->SetVideoStateType(info.callMode); sptr imsCall = reinterpret_cast(call.GetRefPtr()); imsCall->InitVideoCall(); } if (call->GetCallType() == CallType::TYPE_IMS) { call->SetCrsType(info.crsType); } if (call->GetCallType() == info.callType) { TELEPHONY_LOGI("RefreshCallIfNecessary not need Refresh"); return call; } TelCallState priorState = call->GetTelCallState(); CallAttributeInfo attrInfo; (void)memset_s(&attrInfo, sizeof(CallAttributeInfo), 0, sizeof(CallAttributeInfo)); call->GetCallAttributeBaseInfo(attrInfo); sptr newCall = CreateNewCall(info, attrInfo.callDirection); if (newCall == nullptr) { TELEPHONY_LOGE("RefreshCallIfNecessary createCallFail"); return call; } AddOneCallObject(newCall); newCall->SetCallRunningState(call->GetCallRunningState()); newCall->SetTelConferenceState(call->GetTelConferenceState()); newCall->SetStartTime(attrInfo.startTime); newCall->SetPolicyFlag(PolicyFlag(call->GetPolicyFlag())); newCall->SetSpeakerphoneOn(call->IsSpeakerphoneOn()); newCall->SetCallEndedType(call->GetCallEndedType()); newCall->SetCallBeginTime(attrInfo.callBeginTime); newCall->SetCallCreateTime(attrInfo.callCreateTime); newCall->SetCallEndTime(attrInfo.callEndTime); newCall->SetRingBeginTime(attrInfo.ringBeginTime); newCall->SetRingEndTime(attrInfo.ringEndTime); newCall->SetAnswerType(attrInfo.answerType); newCall->SetMicPhoneState(call->IsMuted()); DeleteOneCallObject(call->GetCallID()); newCall->SetCallId(call->GetCallID()); newCall->SetTelCallState(priorState); if (call->GetNumberLocation() != "default") { newCall->SetNumberLocation(call->GetNumberLocation()); } NumberMarkInfo numberMarkInfo = call->GetNumberMarkInfo(); if (numberMarkInfo.markType != MarkType::MARK_TYPE_NONE) { newCall->SetNumberMarkInfo(numberMarkInfo); } return newCall; } void CallStatusManager::SetOriginalCallTypeForActiveState(sptr &call) { if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return; } TelCallState priorState = call->GetTelCallState(); VideoStateType videoState = call->GetVideoStateType(); int32_t videoStateHistory = call->GetOriginalCallType(); if (priorState == TelCallState::CALL_STATUS_ALERTING || priorState == TelCallState::CALL_STATUS_INCOMING || priorState == TelCallState::CALL_STATUS_WAITING) { // outgoing/incoming video call, but accepted/answered with voice call if (videoStateHistory != static_cast(videoState)) { TELEPHONY_LOGD("set videoState:%{public}d as original call type", static_cast(videoState)); call->SetOriginalCallType(static_cast(videoState)); } } else if (priorState == TelCallState::CALL_STATUS_ACTIVE || priorState == TelCallState::CALL_STATUS_HOLDING) { int32_t videoStateCurrent = static_cast(static_cast(videoStateHistory) | static_cast(videoState)); TELEPHONY_LOGD("maybe upgrade/downgrade operation, keep video record always, videoStateCurrent:%{public}d", videoStateCurrent); call->SetOriginalCallType(videoStateCurrent); } } void CallStatusManager::SetOriginalCallTypeForDisconnectState(sptr &call) { if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return; } TelCallState priorState = call->GetTelCallState(); CallAttributeInfo attrInfo; (void)memset_s(&attrInfo, sizeof(CallAttributeInfo), 0, sizeof(CallAttributeInfo)); call->GetCallAttributeBaseInfo(attrInfo); if (priorState == TelCallState::CALL_STATUS_DIALING || priorState == TelCallState::CALL_STATUS_ALERTING || ((priorState == TelCallState::CALL_STATUS_INCOMING || priorState == TelCallState::CALL_STATUS_WAITING) && attrInfo.answerType != CallAnswerType::CALL_ANSWER_REJECT)) { // outgoing/incoming video call, but canceled or missed TELEPHONY_LOGD("canceled or missed call, set voice type as original call type"); call->SetOriginalCallType(static_cast(VideoStateType::TYPE_VOICE)); } } int32_t CallStatusManager::ToSpeakerPhone(sptr &call) { int32_t ret = TELEPHONY_ERR_FAIL; if (call == nullptr) { TELEPHONY_LOGE("Call is NULL"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } if (call->GetCallRunningState() == CallRunningState::CALL_RUNNING_STATE_DIALING) { TELEPHONY_LOGI("Call is CALL_STATUS_DIALING"); return ret; } if (call->IsSpeakerphoneOn()) { AudioDevice device = { .deviceType = AudioDeviceType::DEVICE_SPEAKER, .address = { 0 }, }; DelayedSingleton::GetInstance()->SetAudioDevice(device); ret = call->SetSpeakerphoneOn(false); } return ret; } int32_t CallStatusManager::TurnOffMute(sptr &call) { bool enabled = true; if (HasEmergencyCall(enabled) != TELEPHONY_SUCCESS) { TELEPHONY_LOGI("CallStatusManager::TurnOffMute HasEmergencyCall failed."); } if (call->GetEmergencyState() || enabled) { DelayedSingleton::GetInstance()->SetMute(false); } else { DelayedSingleton::GetInstance()->SetMute(true); } return TELEPHONY_SUCCESS; } sptr CallStatusManager::CreateNewCall(const CallDetailInfo &info, CallDirection dir) { TELEPHONY_LOGI("CreateNewCall"); DialParaInfo paraInfo; AppExecFwk::PacMap extras; extras.Clear(); PackParaInfo(paraInfo, info, dir, extras); sptr callPtr = CreateNewCallByCallType(paraInfo, info, dir, extras); if (callPtr == nullptr) { TELEPHONY_LOGE("CreateNewCall failed!"); return nullptr; } DialScene dialScene = (DialScene)extras.GetIntValue("dialScene"); if (dialScene == DialScene::CALL_EMERGENCY) { callPtr->SetIsEccContact(true); } callPtr->SetOriginalCallType(info.originalCallType); TELEPHONY_LOGD("originalCallType:%{public}d", info.originalCallType); if (info.callType == CallType::TYPE_VOIP) { return callPtr; } if (info.state == TelCallState::CALL_STATUS_INCOMING || info.state == TelCallState::CALL_STATUS_WAITING || (info.state == TelCallState::CALL_STATUS_DIALING && info.index == 0)) { TELEPHONY_LOGI("NumberLocationUpdate start"); ffrt::submit([=]() { DelayedSingleton::GetInstance()->NumberLocationUpdate(callPtr); if (info.state == TelCallState::CALL_STATUS_DIALING) { DelayedSingleton::GetInstance()->YellowPageAndMarkUpdate(callPtr); } }); } time_t createTime = time(nullptr); if (createTime < 0) { createTime = 0; } callPtr->SetCallCreateTime(createTime); return callPtr; } sptr CallStatusManager::CreateNewCallByCallType( DialParaInfo ¶Info, const CallDetailInfo &info, CallDirection dir, AppExecFwk::PacMap &extras) { sptr callPtr = nullptr; switch (info.callType) { case CallType::TYPE_CS: { if (dir == CallDirection::CALL_DIRECTION_OUT) { callPtr = (std::make_unique(paraInfo, extras)).release(); } else { callPtr = (std::make_unique(paraInfo)).release(); } break; } case CallType::TYPE_IMS: { if (dir == CallDirection::CALL_DIRECTION_OUT) { callPtr = (std::make_unique(paraInfo, extras)).release(); } else { callPtr = (std::make_unique(paraInfo)).release(); } if (callPtr->GetCallType() == CallType::TYPE_IMS) { sptr imsCall = reinterpret_cast(callPtr.GetRefPtr()); imsCall->InitVideoCall(); } break; } case CallType::TYPE_OTT: { if (dir == CallDirection::CALL_DIRECTION_OUT) { callPtr = (std::make_unique(paraInfo, extras)).release(); } else { callPtr = (std::make_unique(paraInfo)).release(); } break; } case CallType::TYPE_VOIP: { callPtr = (std::make_unique(paraInfo)).release(); break; } case CallType::TYPE_SATELLITE: { if (dir == CallDirection::CALL_DIRECTION_OUT) { callPtr = (std::make_unique(paraInfo, extras)).release(); } else { callPtr = (std::make_unique(paraInfo)).release(); } break; } default: return nullptr; } return callPtr; } bool CallStatusManager::ShouldRejectIncomingCall() { bool hasEcc = false; if (HasEmergencyCall(hasEcc) == TELEPHONY_SUCCESS && hasEcc) { TELEPHONY_LOGI("HasEmergencyCall reject incoming call."); return true; } auto datashareHelper = SettingsDataShareHelper::GetInstance(); std::string device_provisioned {"0"}; OHOS::Uri uri( "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true&key=device_provisioned"); int resp = datashareHelper->Query(uri, "device_provisioned", device_provisioned); if (resp == TELEPHONY_SUCCESS && (device_provisioned == "0" || device_provisioned.empty())) { TELEPHONY_LOGI("ShouldRejectIncomingCall: device_provisioned = 0"); return true; } std::string user_setup_complete {"1"}; std::vector activedOsAccountIds; OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(activedOsAccountIds); if (activedOsAccountIds.empty()) { TELEPHONY_LOGI("ShouldRejectIncomingCall: activedOsAccountIds is empty"); return false; } int userId = activedOsAccountIds[0]; OHOS::Uri uri_setup( "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_" + std::to_string(userId) + "?Proxy=true&key=user_setup_complete"); int resp_userSetup = datashareHelper->Query(uri_setup, "user_setup_complete", user_setup_complete); if (resp_userSetup == TELEPHONY_SUCCESS && (user_setup_complete == "0" || user_setup_complete.empty())) { TELEPHONY_LOGI("ShouldRejectIncomingCall: user_setup_complete = 0"); return true; } return false; } bool CallStatusManager::ShouldBlockIncomingCall(const sptr &call, const CallDetailInfo &info) { bool isEcc = false; DelayedSingleton::GetInstance()->IsEmergencyPhoneNumber( info.phoneNum, info.accountId, isEcc); if (isEcc) { TELEPHONY_LOGI("incoming phoneNumber is ecc."); return false; } std::shared_ptr spamCallAdapterPtr_ = std::make_shared(); if (spamCallAdapterPtr_ == nullptr) { TELEPHONY_LOGE("create SpamCallAdapter object failed!"); return false; } bool isSpamCall = spamCallAdapterPtr_->DetectSpamCall(std::string(info.phoneNum), info.accountId); if (!isSpamCall) { TELEPHONY_LOGE("DetectSpamCall failed!"); return false; } if (spamCallAdapterPtr_->WaitForDetectResult()) { TELEPHONY_LOGI("DetectSpamCall no time out"); NumberMarkInfo numberMarkInfo = { .markType = MarkType::MARK_TYPE_NONE, .markContent = "", .markCount = -1, .markSource = "", .isCloud = false, }; bool isBlock = false; int32_t blockReason; spamCallAdapterPtr_->GetParseResult(isBlock, numberMarkInfo, blockReason); call->SetNumberMarkInfo(numberMarkInfo); call->SetBlockReason(blockReason); if (isBlock) { return true; } } return false; } bool CallStatusManager::IsRingOnceCall(const sptr &call, const CallDetailInfo &info) { NumberMarkInfo numberMarkInfo = call->GetNumberMarkInfo(); ContactInfo contactInfo = call->GetCallerInfo(); if (numberMarkInfo.markType == MarkType::MARK_TYPE_YELLOW_PAGE || std::string(contactInfo.name) != "") { return false; } auto datashareHelper = SettingsDataShareHelper::GetInstance(); std::string is_check_ring_once {"0"}; std::string key = "spamshield_sim" + std::to_string(info.accountId + 1) + "_phone_switch_ring_once"; OHOS::Uri uri( "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true&key=" + key); int32_t ret = datashareHelper->Query(uri, key, is_check_ring_once); if (ret != TELEPHONY_SUCCESS || is_check_ring_once == "0") { TELEPHONY_LOGI("is_check_ring_once = 0, not need check ring once call"); return false; } if (timeWaitHelper_ == nullptr) { timeWaitHelper_ = std::make_unique(WAIT_TIME_THREE_SECOND); } if (!timeWaitHelper_->WaitForResult()) { TELEPHONY_LOGI("is not ring once"); return false; } return true; } int32_t CallStatusManager::HandleRingOnceCall(sptr &call) { if (call == nullptr) { TELEPHONY_LOGE("call is nullptr!"); return TELEPHONY_ERR_LOCAL_PTR_NULL; } int32_t ret = call->SetTelCallState(TelCallState::CALL_STATUS_INCOMING); if (ret != TELEPHONY_SUCCESS && ret != CALL_ERR_NOT_NEW_STATE) { TELEPHONY_LOGE("Set CallState failed!"); return ret; } return DelayedSingleton::GetInstance()->AddCallLogAndNotification(call); } void CallStatusManager::PackParaInfo( DialParaInfo ¶Info, const CallDetailInfo &info, CallDirection dir, AppExecFwk::PacMap &extras) { paraInfo.isEcc = false; paraInfo.dialType = DialType::DIAL_CARRIER_TYPE; if (dir == CallDirection::CALL_DIRECTION_OUT) { DelayedSingleton::GetInstance()->GetDialParaInfo(paraInfo, extras); } if (info.callType == CallType::TYPE_VOIP) { paraInfo.voipCallInfo.voipCallId = info.voipCallInfo.voipCallId; paraInfo.voipCallInfo.userName = info.voipCallInfo.userName; (paraInfo.voipCallInfo.userProfile).assign( (info.voipCallInfo.userProfile).begin(), (info.voipCallInfo.userProfile).end()); paraInfo.voipCallInfo.abilityName = info.voipCallInfo.abilityName; paraInfo.voipCallInfo.extensionId = info.voipCallInfo.extensionId; paraInfo.voipCallInfo.voipBundleName = info.voipCallInfo.voipBundleName; paraInfo.voipCallInfo.showBannerForIncomingCall = info.voipCallInfo.showBannerForIncomingCall; paraInfo.voipCallInfo.isConferenceCall = info.voipCallInfo.isConferenceCall; paraInfo.voipCallInfo.isVoiceAnswerSupported = info.voipCallInfo.isVoiceAnswerSupported; paraInfo.voipCallInfo.hasMicPermission = info.voipCallInfo.hasMicPermission; paraInfo.voipCallInfo.uid = info.voipCallInfo.uid; } paraInfo.number = info.phoneNum; paraInfo.callId = GetNewCallId(); paraInfo.index = info.index; paraInfo.videoState = info.callMode; paraInfo.accountId = info.accountId; paraInfo.callType = info.callType; paraInfo.callState = info.state; paraInfo.bundleName = info.bundleName; paraInfo.crsType = info.crsType; paraInfo.originalCallType = info.originalCallType; } bool CallStatusManager::IsFocusModeOpen() { auto datashareHelper = SettingsDataShareHelper::GetInstance(); std::string focusModeEnable {"0"}; std::vector activedOsAccountIds; OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(activedOsAccountIds); if (activedOsAccountIds.empty()) { TELEPHONY_LOGW("ShouldRejectIncomingCall: activedOsAccountIds is empty"); return false; } int userId = activedOsAccountIds[0]; OHOS::Uri uri( "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_" + std::to_string(userId) + "?Proxy=true&key=focus_mode_enable"); int resp = datashareHelper->Query(uri, "focus_mode_enable", focusModeEnable); if (resp == TELEPHONY_SUCCESS && focusModeEnable == "1") { TELEPHONY_LOGI("IsFocusModeOpen: focus_mode_enable = 1"); return true; } return false; } bool CallStatusManager::IsRejectCall(sptr &call, const CallDetailInfo &info, bool &block) { int32_t state; DelayedSingleton::GetInstance()->GetVoIPCallState(state); if (ShouldRejectIncomingCall() || state == (int32_t)CallStateToApp::CALL_STATE_RINGING) { CallManagerHisysevent::HiWriteBehaviorEventPhoneUE( CALL_INCOMING_REJECT_BY_SYSTEM, PNAMEID_KEY, KEY_CALL_MANAGER, PVERSIONID_KEY, "", ACTION_TYPE, REJECT_BY_OOBE); block = false; return true; } if (info.callType != CallType::TYPE_VOIP && ShouldBlockIncomingCall(call, info)) { CallManagerHisysevent::HiWriteBehaviorEventPhoneUE( CALL_INCOMING_REJECT_BY_SYSTEM, PNAMEID_KEY, KEY_CALL_MANAGER, PVERSIONID_KEY, "", ACTION_TYPE, REJECT_BY_NUM_BLOCK); block = true; return true; } if (IsFocusModeOpen()) { int ret = Notification::NotificationHelper::IsNeedSilentInDoNotDisturbMode(info.phoneNum, 0); TELEPHONY_LOGI("IsRejectCall IsNeedSilentInDoNotDisturbMode ret:%{public}d", ret); if (ret == 0) { CallManagerHisysevent::HiWriteBehaviorEventPhoneUE( CALL_INCOMING_REJECT_BY_SYSTEM, PNAMEID_KEY, KEY_CALL_MANAGER, PVERSIONID_KEY, "", ACTION_TYPE, REJECT_IN_FOCUSMODE); block = false; return true; } } return false; } } // namespace Telephony } // namespace OHOS