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