1 /*
2  * Copyright (C) 2023 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 "incall_data_state_machine.h"
17 
18 #include "cellular_data_settings_rdb_helper.h"
19 #include "core_manager_inner.h"
20 #include "telephony_log_wrapper.h"
21 #include "telephony_types.h"
22 
23 namespace OHOS {
24 namespace Telephony {
UpdateCallState(int32_t state)25 void IncallDataStateMachine::UpdateCallState(int32_t state)
26 {
27     callState_ = state;
28 }
29 
GetCallState() const30 int32_t IncallDataStateMachine::GetCallState() const
31 {
32     return callState_;
33 }
34 
HasAnyConnectedState() const35 bool IncallDataStateMachine::HasAnyConnectedState() const
36 {
37     if (apnManager_ != nullptr) {
38         return apnManager_->HasAnyConnectedState();
39     }
40     return false;
41 }
42 
GetSlotId() const43 int32_t IncallDataStateMachine::GetSlotId() const
44 {
45     return slotId_;
46 }
47 
IsIncallDataSwitchOn()48 bool IncallDataStateMachine::IsIncallDataSwitchOn()
49 {
50     std::shared_ptr<CellularDataSettingsRdbHelper> settingHelper = CellularDataSettingsRdbHelper::GetInstance();
51     if (settingHelper == nullptr) {
52         return true;
53     }
54     Uri uri(CELLULAR_DATA_SETTING_DATA_INCALL_URI);
55     int value = static_cast<int32_t>(DataSwitchCode::CELLULAR_DATA_ENABLED);
56     if (settingHelper->GetValue(uri, CELLULAR_DATA_COLUMN_INCALL, value) != TELEPHONY_SUCCESS) {
57         TELEPHONY_LOGE("GetValue failed!");
58         return true;
59     }
60     TELEPHONY_LOGI("Slot%{public}d: value=%{public}d", slotId_, value);
61     return value == static_cast<int32_t>(DataSwitchCode::CELLULAR_DATA_ENABLED);
62 }
63 
IsSecondaryCanActiveData()64 bool IncallDataStateMachine::IsSecondaryCanActiveData()
65 {
66     int32_t dsdsMode = DSDS_MODE_V2;
67     CoreManagerInner::GetInstance().GetDsdsMode(dsdsMode);
68     if (dsdsMode >= DSDS_MODE_V3) {
69         TELEPHONY_LOGI("Slot%{public}d: not dsds 2.0", slotId_);
70         return false;
71     }
72     int32_t primarySlotId = INVALID_SLOT_ID;
73     CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
74     if (primarySlotId == INVALID_SLOT_ID || primarySlotId == slotId_) {
75         TELEPHONY_LOGI("Slot%{public}d: not secondary sim card", slotId_);
76         return false;
77     }
78     bool hasPrimarySimCard = false;
79     CoreManagerInner::GetInstance().HasSimCard(primarySlotId, hasPrimarySimCard);
80     if (!hasPrimarySimCard) {
81         TELEPHONY_LOGI("Slot%{public}d: no primary sim card", slotId_);
82         return false;
83     }
84     ImsRegInfo voiceInfo;
85     CoreManagerInner::GetInstance().GetImsRegStatus(slotId_, ImsServiceType::TYPE_VOICE, voiceInfo);
86     ImsRegInfo videoInfo;
87     CoreManagerInner::GetInstance().GetImsRegStatus(slotId_, ImsServiceType::TYPE_VIDEO, videoInfo);
88     if (voiceInfo.imsRegState != ImsRegState::IMS_REGISTERED && videoInfo.imsRegState != ImsRegState::IMS_REGISTERED) {
89         TELEPHONY_LOGI("Slot%{public}d: not ims call", slotId_);
90         return false;
91     }
92     if (callState_ == static_cast<int32_t>(TelCallStatus::CALL_STATUS_IDLE) ||
93         callState_ == static_cast<int32_t>(TelCallStatus::CALL_STATUS_DISCONNECTED)) {
94         TELEPHONY_LOGI("Slot%{public}d: not in call", slotId_);
95         return false;
96     }
97     return CanActiveDataByRadioTech();
98 }
99 
CanActiveDataByRadioTech()100 bool IncallDataStateMachine::CanActiveDataByRadioTech()
101 {
102     int32_t radioTech = static_cast<int32_t>(RadioTech::RADIO_TECHNOLOGY_INVALID);
103     CoreManagerInner::GetInstance().GetPsRadioTech(slotId_, radioTech);
104     switch (static_cast<RadioTech>(radioTech)) {
105         case RadioTech::RADIO_TECHNOLOGY_WCDMA:
106             // fall_through
107         case RadioTech::RADIO_TECHNOLOGY_HSPA:
108             // fall_through
109         case RadioTech::RADIO_TECHNOLOGY_HSPAP:
110             // fall_through
111         case RadioTech::RADIO_TECHNOLOGY_LTE:
112             // fall_through
113         case RadioTech::RADIO_TECHNOLOGY_LTE_CA:
114             // fall_through
115         case RadioTech::RADIO_TECHNOLOGY_NR:
116             return true;
117         default:
118             return false;
119     }
120 }
121 
Init(int32_t callState)122 void IncallDataStateMachine::Init(int32_t callState)
123 {
124     idleState_ = new (std::nothrow) IdleState(std::weak_ptr<IncallDataStateMachine>(shared_from_this()), "IdleState");
125     secondaryActiveState_ = new (std::nothrow)
126         SecondaryActiveState(std::weak_ptr<IncallDataStateMachine>(shared_from_this()), "SecondaryActiveState");
127     activatingSecondaryState_ = new (std::nothrow)
128         ActivatingSecondaryState(std::weak_ptr<IncallDataStateMachine>(shared_from_this()), "ActivatingSecondaryState");
129     activatedSecondaryState_ = new (std::nothrow)
130         ActivatedSecondaryState(std::weak_ptr<IncallDataStateMachine>(shared_from_this()), "ActivatedSecondaryState");
131     deactivatingSecondaryState_ = new (std::nothrow) DeactivatingSecondaryState(
132         std::weak_ptr<IncallDataStateMachine>(shared_from_this()), "DeactivatingSecondaryState");
133     if (idleState_ == nullptr || secondaryActiveState_ == nullptr || activatingSecondaryState_ == nullptr ||
134         activatedSecondaryState_ == nullptr || deactivatingSecondaryState_ == nullptr) {
135         TELEPHONY_LOGE("memory allocation failed");
136         return;
137     }
138     secondaryActiveState_->SetParentState(idleState_);
139     activatingSecondaryState_->SetParentState(secondaryActiveState_);
140     activatedSecondaryState_->SetParentState(secondaryActiveState_);
141     deactivatingSecondaryState_->SetParentState(idleState_);
142     callState_ = callState;
143     StateMachine::SetOriginalState(idleState_);
144     StateMachine::Start();
145 }
146 
SetCurrentState(const sptr<State> && state)147 void IncallDataStateMachine::SetCurrentState(const sptr<State> &&state)
148 {
149     currentState_ = std::move(state);
150 }
151 
GetCurrentState() const152 sptr<State> IncallDataStateMachine::GetCurrentState() const
153 {
154     return currentState_;
155 }
156 
StateBegin()157 void IdleState::StateBegin()
158 {
159     TELEPHONY_LOGI("Enter Idle State");
160     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
161     if (stateMachine == nullptr) {
162         TELEPHONY_LOGE("stateMachine is null");
163         return;
164     }
165     isActive_ = true;
166     stateMachine->SetCurrentState(sptr<State>(this));
167     if (stateMachine->GetCallState() == static_cast<int32_t>(TelCallStatus::CALL_STATUS_IDLE) ||
168         stateMachine->GetCallState() == static_cast<int32_t>(TelCallStatus::CALL_STATUS_DISCONNECTED)) {
169         std::shared_ptr<TelEventHandler> eventHandler = stateMachine->cellularDataHandler_.lock();
170         if (eventHandler != nullptr) {
171             eventHandler->SendEvent(CellularDataEventCode::MSG_INCALL_DATA_COMPLETE);
172         }
173     }
174 }
175 
StateEnd()176 void IdleState::StateEnd()
177 {
178     TELEPHONY_LOGI("Exit Idle State");
179     isActive_ = false;
180 }
181 
StateProcess(const AppExecFwk::InnerEvent::Pointer & event)182 bool IdleState::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
183 {
184     if (event == nullptr) {
185         TELEPHONY_LOGE("event is null");
186         return NOT_PROCESSED;
187     }
188     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
189     if (stateMachine == nullptr) {
190         TELEPHONY_LOGE("stateMachine is null");
191         return NOT_PROCESSED;
192     }
193     uint32_t eventCode = event->GetInnerEventId();
194     std::map<uint32_t, Fun>::iterator it = eventIdFunMap_.find(eventCode);
195     if (it != eventIdFunMap_.end()) {
196         return it->second(event);
197     }
198     return NOT_PROCESSED;
199 }
200 
ProcessCallStarted(const AppExecFwk::InnerEvent::Pointer & event)201 bool IdleState::ProcessCallStarted(const AppExecFwk::InnerEvent::Pointer &event)
202 {
203     TELEPHONY_LOGI("IdleState::MSG_SM_INCALL_DATA_CALL_STARTED");
204     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
205     if (stateMachine == nullptr) {
206         TELEPHONY_LOGE("stateMachine is null");
207         return NOT_PROCESSED;
208     }
209     if (stateMachine->IsIncallDataSwitchOn() && stateMachine->IsSecondaryCanActiveData()) {
210         int32_t defaultSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
211         if (defaultSlotId != stateMachine->GetSlotId()) {
212             stateMachine->TransitionTo(stateMachine->activatingSecondaryState_);
213             CoreManagerInner::GetInstance().SetDefaultCellularDataSlotId(stateMachine->GetSlotId());
214         }
215     }
216     return PROCESSED;
217 }
218 
ProcessCallEnded(const AppExecFwk::InnerEvent::Pointer & event)219 bool IdleState::ProcessCallEnded(const AppExecFwk::InnerEvent::Pointer &event)
220 {
221     TELEPHONY_LOGI("IdleState::MSG_SM_INCALL_DATA_CALL_ENDED");
222     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
223     if (stateMachine == nullptr) {
224         TELEPHONY_LOGE("stateMachine is null");
225         return NOT_PROCESSED;
226     }
227     if (stateMachine->stateMachineEventHandler_ == nullptr) {
228         TELEPHONY_LOGE("stateMachineEventHandler_ is null");
229         return NOT_PROCESSED;
230     }
231     if (stateMachine->stateMachineEventHandler_->HasInnerEvent(
232         CellularDataEventCode::MSG_SM_INCALL_DATA_DSDS_CHANGED)) {
233         stateMachine->stateMachineEventHandler_->RemoveEvent(CellularDataEventCode::MSG_SM_INCALL_DATA_DSDS_CHANGED);
234     }
235     std::shared_ptr<TelEventHandler> eventHandler = stateMachine->cellularDataHandler_.lock();
236     if (eventHandler != nullptr) {
237         eventHandler->SendEvent(CellularDataEventCode::MSG_INCALL_DATA_COMPLETE);
238     }
239     return PROCESSED;
240 }
241 
ProcessSettingsOn(const AppExecFwk::InnerEvent::Pointer & event)242 bool IdleState::ProcessSettingsOn(const AppExecFwk::InnerEvent::Pointer &event)
243 {
244     TELEPHONY_LOGI("IdleState::MSG_SM_INCALL_DATA_SETTINGS_ON");
245     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
246     if (stateMachine == nullptr) {
247         TELEPHONY_LOGE("stateMachine is null");
248         return NOT_PROCESSED;
249     }
250     if (stateMachine->IsIncallDataSwitchOn() && stateMachine->IsSecondaryCanActiveData()) {
251         int32_t defaultSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
252         if (defaultSlotId != stateMachine->GetSlotId()) {
253             stateMachine->TransitionTo(stateMachine->activatingSecondaryState_);
254             CoreManagerInner::GetInstance().SetDefaultCellularDataSlotId(stateMachine->GetSlotId());
255         }
256     }
257     return PROCESSED;
258 }
259 
ProcessDsdsChanged(const AppExecFwk::InnerEvent::Pointer & event)260 bool IdleState::ProcessDsdsChanged(const AppExecFwk::InnerEvent::Pointer &event)
261 {
262     TELEPHONY_LOGI("IdleState::MSG_SM_INCALL_DATA_DSDS_CHANGED");
263     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
264     if (stateMachine == nullptr) {
265         TELEPHONY_LOGE("stateMachine is null");
266         return NOT_PROCESSED;
267     }
268     if (stateMachine->IsIncallDataSwitchOn() && stateMachine->IsSecondaryCanActiveData()) {
269         int32_t defaultSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
270         if (defaultSlotId != stateMachine->GetSlotId()) {
271             stateMachine->TransitionTo(stateMachine->activatingSecondaryState_);
272             CoreManagerInner::GetInstance().SetDefaultCellularDataSlotId(stateMachine->GetSlotId());
273         }
274     }
275     return PROCESSED;
276 }
277 
StateBegin()278 void SecondaryActiveState::StateBegin()
279 {
280     TELEPHONY_LOGI("Enter SecondaryActive State");
281     isActive_ = true;
282 }
283 
StateEnd()284 void SecondaryActiveState::StateEnd()
285 {
286     TELEPHONY_LOGI("Exit SecondaryActive State");
287     isActive_ = false;
288 }
289 
StateProcess(const AppExecFwk::InnerEvent::Pointer & event)290 bool SecondaryActiveState::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
291 {
292     if (event == nullptr) {
293         TELEPHONY_LOGE("event is null");
294         return NOT_PROCESSED;
295     }
296     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
297     if (stateMachine == nullptr) {
298         TELEPHONY_LOGE("stateMachine is null");
299         return NOT_PROCESSED;
300     }
301     uint32_t eventCode = event->GetInnerEventId();
302     std::map<uint32_t, Fun>::iterator it = eventIdFunMap_.find(eventCode);
303     if (it != eventIdFunMap_.end()) {
304         return it->second(event);
305     }
306     return NOT_PROCESSED;
307 }
308 
ProcessSettingsOn(const AppExecFwk::InnerEvent::Pointer & event)309 bool SecondaryActiveState::ProcessSettingsOn(const AppExecFwk::InnerEvent::Pointer &event)
310 {
311     TELEPHONY_LOGI("SecondaryActiveState::MSG_SM_INCALL_DATA_SETTINGS_ON");
312     return PROCESSED;
313 }
314 
ProcessCallEnded(const AppExecFwk::InnerEvent::Pointer & event)315 bool SecondaryActiveState::ProcessCallEnded(const AppExecFwk::InnerEvent::Pointer &event)
316 {
317     TELEPHONY_LOGI("SecondaryActiveState::MSG_SM_INCALL_DATA_CALL_ENDED");
318     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
319     if (stateMachine == nullptr) {
320         TELEPHONY_LOGE("stateMachine is null");
321         return NOT_PROCESSED;
322     }
323     if (stateMachine->GetCallState() == static_cast<int32_t>(TelCallStatus::CALL_STATUS_IDLE) ||
324         stateMachine->GetCallState() == static_cast<int32_t>(TelCallStatus::CALL_STATUS_DISCONNECTED)) {
325         int32_t defaultSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
326         int32_t primarySlotId = INVALID_SLOT_ID;
327         CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
328         if (defaultSlotId != primarySlotId) {
329             stateMachine->TransitionTo(stateMachine->deactivatingSecondaryState_);
330         } else {
331             stateMachine->TransitionTo(stateMachine->idleState_);
332         }
333     }
334     return PROCESSED;
335 }
336 
ProcessSettingsOff(const AppExecFwk::InnerEvent::Pointer & event)337 bool SecondaryActiveState::ProcessSettingsOff(const AppExecFwk::InnerEvent::Pointer &event)
338 {
339     TELEPHONY_LOGI("SecondaryActiveState::MSG_SM_INCALL_DATA_SETTINGS_OFF");
340     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
341     if (stateMachine == nullptr) {
342         TELEPHONY_LOGE("stateMachine is null");
343         return NOT_PROCESSED;
344     }
345     if (!stateMachine->IsIncallDataSwitchOn()) {
346         int32_t defaultSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
347         int32_t primarySlotId = INVALID_SLOT_ID;
348         CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
349         if (defaultSlotId != primarySlotId) {
350             stateMachine->TransitionTo(stateMachine->deactivatingSecondaryState_);
351         } else {
352             stateMachine->TransitionTo(stateMachine->idleState_);
353         }
354     }
355     return PROCESSED;
356 }
357 
ProcessDsdsChanged(const AppExecFwk::InnerEvent::Pointer & event)358 bool SecondaryActiveState::ProcessDsdsChanged(const AppExecFwk::InnerEvent::Pointer &event)
359 {
360     TELEPHONY_LOGI("SecondaryActiveState::MSG_SM_INCALL_DATA_DSDS_CHANGED");
361     return PROCESSED;
362 }
363 
StateBegin()364 void ActivatingSecondaryState::StateBegin()
365 {
366     TELEPHONY_LOGI("Enter ActivatingSecondary State");
367     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
368     if (stateMachine == nullptr) {
369         TELEPHONY_LOGE("stateMachine is null");
370         return;
371     }
372     isActive_ = true;
373     stateMachine->SetCurrentState(sptr<State>(this));
374 }
375 
StateEnd()376 void ActivatingSecondaryState::StateEnd()
377 {
378     TELEPHONY_LOGI("Exit ActivatingSecondary State");
379     isActive_ = false;
380 }
381 
StateProcess(const AppExecFwk::InnerEvent::Pointer & event)382 bool ActivatingSecondaryState::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
383 {
384     if (event == nullptr) {
385         TELEPHONY_LOGE("event is null");
386         return NOT_PROCESSED;
387     }
388     uint32_t eventCode = event->GetInnerEventId();
389     if (eventCode == CellularDataEventCode::MSG_SM_INCALL_DATA_DATA_CONNECTED) {
390         std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
391         if (stateMachine == nullptr) {
392             TELEPHONY_LOGE("stateMachine is null");
393             return NOT_PROCESSED;
394         }
395         stateMachine->TransitionTo(stateMachine->activatedSecondaryState_);
396         return PROCESSED;
397     }
398     return NOT_PROCESSED;
399 }
400 
StateBegin()401 void ActivatedSecondaryState::StateBegin()
402 {
403     TELEPHONY_LOGI("Enter ActivatedSecondary State");
404     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
405     if (stateMachine == nullptr) {
406         TELEPHONY_LOGE("stateMachine is null");
407         return;
408     }
409     isActive_ = true;
410     stateMachine->SetCurrentState(sptr<State>(this));
411 }
412 
StateEnd()413 void ActivatedSecondaryState::StateEnd()
414 {
415     TELEPHONY_LOGI("Exit ActivatedSecondary State");
416     isActive_ = false;
417 }
418 
StateProcess(const AppExecFwk::InnerEvent::Pointer & event)419 bool ActivatedSecondaryState::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
420 {
421     return NOT_PROCESSED;
422 }
423 
StateBegin()424 void DeactivatingSecondaryState::StateBegin()
425 {
426     TELEPHONY_LOGI("Enter DeactivatingSecondary State");
427     std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
428     if (stateMachine == nullptr) {
429         TELEPHONY_LOGE("stateMachine is null");
430         return;
431     }
432     isActive_ = true;
433     stateMachine->SetCurrentState(sptr<State>(this));
434     int32_t defaultSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
435     int32_t primarySlotId = INVALID_SLOT_ID;
436     CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
437     if (defaultSlotId != primarySlotId) {
438         CoreManagerInner::GetInstance().SetDefaultCellularDataSlotId(primarySlotId);
439     } else {
440         stateMachine->TransitionTo(stateMachine->idleState_);
441     }
442     if (!stateMachine->HasAnyConnectedState()) {
443         stateMachine->TransitionTo(stateMachine->idleState_);
444     }
445 }
446 
StateEnd()447 void DeactivatingSecondaryState::StateEnd()
448 {
449     TELEPHONY_LOGI("Exit DeactivatingSecondary State");
450     isActive_ = false;
451 }
452 
StateProcess(const AppExecFwk::InnerEvent::Pointer & event)453 bool DeactivatingSecondaryState::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
454 {
455     if (event == nullptr) {
456         TELEPHONY_LOGE("event is null");
457         return NOT_PROCESSED;
458     }
459     uint32_t eventCode = event->GetInnerEventId();
460     if (eventCode == CellularDataEventCode::MSG_SM_INCALL_DATA_DATA_DISCONNECTED) {
461         std::shared_ptr<IncallDataStateMachine> stateMachine = stateMachine_.lock();
462         if (stateMachine == nullptr) {
463             TELEPHONY_LOGE("stateMachine is null");
464             return NOT_PROCESSED;
465         }
466         int32_t primarySlotId = INVALID_SLOT_ID;
467         CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
468         if (stateMachine->GetSlotId() != primarySlotId) {
469             stateMachine->TransitionTo(stateMachine->idleState_);
470         }
471         return PROCESSED;
472     }
473     if (eventCode == CellularDataEventCode::MSG_SM_INCALL_DATA_SETTINGS_ON) {
474         return PROCESSED;
475     }
476     return NOT_PROCESSED;
477 }
478 } // namespace Telephony
479 } // namespace OHOS
480