1 /*
2  * Copyright (C) 2021-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 "concrete_manager_state_machine.h"
17 #include "wifi_controller_define.h"
18 #include "wifi_manager.h"
19 #include "wifi_config_center.h"
20 #include "wifi_internal_msg.h"
21 #include "wifi_sta_hal_interface.h"
22 #include "wifi_common_event_helper.h"
23 #include "wifi_service_scheduler.h"
24 #ifndef OHOS_ARCH_LITE
25 #include "wifi_country_code_manager.h"
26 #include "wifi_common_util.h"
27 #include "app_network_speed_limit_service.h"
28 #include "wifi_internal_event_dispatcher.h"
29 #else
30 #include "wifi_internal_event_dispatcher_lite.h"
31 #endif
32 #ifdef HDI_CHIP_INTERFACE_SUPPORT
33 #include "hal_device_manage.h"
34 #endif
35 
36 namespace OHOS {
37 namespace Wifi {
38 DEFINE_WIFILOG_LABEL("ConcreteMangerMachine");
39 int ConcreteMangerMachine::mTargetRole{static_cast<int>(ConcreteManagerRole::ROLE_UNKNOW)};
40 using TimeOutCallback = std::function<void()>;
41 int ConcreteMangerMachine::mid{0};
42 std::string ConcreteMangerMachine::ifaceName{""};
43 
ConcreteMangerMachine()44 ConcreteMangerMachine::ConcreteMangerMachine()
45     : StateMachine("ConcreteMangerMachine"), pDefaultState(nullptr), pIdleState(nullptr), pConnectState(nullptr),
46       pScanonlyState(nullptr), pSemiActiveState(nullptr)
47 {}
48 
~ConcreteMangerMachine()49 ConcreteMangerMachine::~ConcreteMangerMachine()
50 {
51     WIFI_LOGE("~ConcreteMangerMachine");
52     StopHandlerThread();
53     ParsePointer(pDefaultState);
54     ParsePointer(pIdleState);
55     ParsePointer(pConnectState);
56     ParsePointer(pScanonlyState);
57     ParsePointer(pSemiActiveState);
58     WIFI_LOGE("set wifi stoping state is false");
59     WifiConfigCenter::GetInstance().SetWifiStopState(false);
60 #ifdef HDI_CHIP_INTERFACE_SUPPORT
61     if (!ifaceName.empty()) {
62         WIFI_LOGW("destroy ConcreteMangerMachine RemoveStaIface ifaceName:%{public}s, instId:%{public}d",
63             ifaceName.c_str(), mid);
64         DelayedSingleton<HalDeviceManager>::GetInstance()->RemoveStaIface(ifaceName);
65         ifaceName.clear();
66         WifiServiceScheduler::GetInstance().ClearStaIfaceNameMap(mid);
67         WifiConfigCenter::GetInstance().SetStaIfaceName("", mid);
68     }
69 #endif
70 }
71 
72 /* --------------------------Initialization functions--------------------------*/
InitConcreteMangerMachine()73 ErrCode ConcreteMangerMachine::InitConcreteMangerMachine()
74 {
75     WIFI_LOGE("Enter InitConcreteMangerMachine.\n");
76     if (!InitialStateMachine("ConcreteManagerMachine")) {
77         WIFI_LOGE("Initial StateMachine failed.\n");
78         return WIFI_OPT_FAILED;
79     }
80     WifiConfigCenter::GetInstance().SetWifiStopState(false);
81     if (InitConcreteMangerStates() == WIFI_OPT_FAILED) {
82         return WIFI_OPT_FAILED;
83     }
84     BuildStateTree();
85     SetFirstState(pIdleState);
86     StartStateMachine();
87     return WIFI_OPT_SUCCESS;
88 }
89 
BuildStateTree()90 void ConcreteMangerMachine::BuildStateTree()
91 {
92     StatePlus(pDefaultState, nullptr);
93     StatePlus(pIdleState, pDefaultState);
94     StatePlus(pConnectState, pDefaultState);
95     StatePlus(pScanonlyState, pDefaultState);
96     StatePlus(pSemiActiveState, pDefaultState);
97 }
98 
InitConcreteMangerStates()99 ErrCode ConcreteMangerMachine::InitConcreteMangerStates()
100 {
101     int tmpErrNumber;
102 
103     WIFI_LOGE("Enter InitConcreteMangerStates.\n");
104     pDefaultState = new (std::nothrow) DefaultState(this);
105     tmpErrNumber = JudgmentEmpty(pDefaultState);
106     pIdleState = new (std::nothrow) IdleState(this);
107     tmpErrNumber += JudgmentEmpty(pIdleState);
108     pConnectState = new (std::nothrow) ConnectState(this);
109     tmpErrNumber += JudgmentEmpty(pConnectState);
110     pScanonlyState = new (std::nothrow) ScanonlyState(this);
111     tmpErrNumber += JudgmentEmpty(pScanonlyState);
112     pSemiActiveState = new (std::nothrow) SemiActiveState(this);
113     tmpErrNumber += JudgmentEmpty(pSemiActiveState);
114     if (tmpErrNumber != 0) {
115         WIFI_LOGE("InitConcreteMangerStates some one state is null\n");
116         return WIFI_OPT_FAILED;
117     }
118     return WIFI_OPT_SUCCESS;
119 }
120 
RegisterCallback(ConcreteModeCallback & callback)121 void ConcreteMangerMachine::RegisterCallback(ConcreteModeCallback &callback)
122 {
123     mcb = callback;
124 }
125 
SetTargetRole(ConcreteManagerRole role)126 void ConcreteMangerMachine::SetTargetRole(ConcreteManagerRole role)
127 {
128     WIFI_LOGI("SetTargetRole:%{public}d", static_cast<int>(role));
129     mTargetRole = static_cast<int>(role);
130 }
131 
DefaultState(ConcreteMangerMachine * concreteMangerMachine)132 ConcreteMangerMachine::DefaultState::DefaultState(ConcreteMangerMachine *concreteMangerMachine)
133     : State("DefaultState"), pConcreteMangerMachine(concreteMangerMachine)
134 {}
135 
~DefaultState()136 ConcreteMangerMachine::DefaultState::~DefaultState()
137 {}
138 
GoInState()139 void ConcreteMangerMachine::DefaultState::GoInState()
140 {
141     WIFI_LOGE("DefaultState  GoInState function.\n");
142 }
143 
GoOutState()144 void ConcreteMangerMachine::DefaultState::GoOutState()
145 {
146     WIFI_LOGE("DefaultState  GoOutState function.\n");
147 }
148 
ExecuteStateMsg(InternalMessagePtr msg)149 bool ConcreteMangerMachine::DefaultState::ExecuteStateMsg(InternalMessagePtr msg)
150 {
151     if (msg == nullptr || pConcreteMangerMachine == nullptr) {
152         return false;
153     }
154     WIFI_LOGE("DefaultState-msgCode=%{public}d is received.\n", msg->GetMessageName());
155     switch (msg->GetMessageName()) {
156         case CONCRETE_CMD_STOP:
157             pConcreteMangerMachine->CheckAndContinueToStopWifi(msg);
158             break;
159         case CONCRETE_CMD_STA_STOP:
160             pConcreteMangerMachine->HandleStaStop();
161             break;
162         default:
163             break;
164     }
165     return true;
166 }
167 
IdleState(ConcreteMangerMachine * concreteMangerMachine)168 ConcreteMangerMachine::IdleState::IdleState(ConcreteMangerMachine *concreteMangerMachine)
169     : State("IdleState"), pConcreteMangerMachine(concreteMangerMachine)
170 {}
171 
~IdleState()172 ConcreteMangerMachine::IdleState::~IdleState()
173 {}
174 
GoInState()175 void ConcreteMangerMachine::IdleState::GoInState()
176 {
177     WIFI_LOGE("IdleState  GoInState function.\n");
178 }
179 
GoOutState()180 void ConcreteMangerMachine::IdleState::GoOutState()
181 {
182     WIFI_LOGE("IdleState  GoOutState function.\n");
183 }
184 
ExecuteStateMsg(InternalMessagePtr msg)185 bool ConcreteMangerMachine::IdleState::ExecuteStateMsg(InternalMessagePtr msg) __attribute__((no_sanitize("cfi")))
186 {
187     if (msg == nullptr) {
188         return false;
189     }
190     WIFI_LOGE("IdleState-msgCode=%{public}d is received.\n", msg->GetMessageName());
191     if (pConcreteMangerMachine->HandleCommonMessage(msg)) {
192         return true;
193     }
194     switch (msg->GetMessageName()) {
195         case CONCRETE_CMD_START:
196             HandleStartInIdleState(msg);
197             break;
198         case CONCRETE_CMD_SWITCH_TO_CONNECT_MODE:
199             HandleSwitchToConnectMode(msg);
200             break;
201         case CONCRETE_CMD_SWITCH_TO_SCAN_ONLY_MODE:
202             HandleSwitchToScanOnlyMode(msg);
203             break;
204         case CONCRETE_CMD_SWITCH_TO_SEMI_ACTIVE_MODE:
205             HandleSwitchToSemiActiveMode(msg);
206             break;
207         default:
208             break;
209     }
210     return true;
211 }
212 
HandleSwitchToConnectMode(InternalMessagePtr msg)213 void ConcreteMangerMachine::IdleState::HandleSwitchToConnectMode(InternalMessagePtr msg)
214 {
215     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartStaService(mid, ifaceName);
216     if (ret != WIFI_OPT_SUCCESS) {
217         WifiConfigCenter::GetInstance().SetWifiStopState(true);
218         pConcreteMangerMachine->mcb.onStartFailure(mid);
219         return;
220     }
221     pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pConnectState);
222 }
223 
HandleSwitchToScanOnlyMode(InternalMessagePtr msg)224 void ConcreteMangerMachine::IdleState::HandleSwitchToScanOnlyMode(InternalMessagePtr msg)
225 {
226     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartScanOnly(mid, ifaceName);
227     if (ret != WIFI_OPT_SUCCESS) {
228         WifiConfigCenter::GetInstance().SetWifiStopState(true);
229         pConcreteMangerMachine->mcb.onStartFailure(mid);
230         return;
231     }
232     pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pScanonlyState);
233 }
234 
HandleSwitchToSemiActiveMode(InternalMessagePtr msg)235 void ConcreteMangerMachine::IdleState::HandleSwitchToSemiActiveMode(InternalMessagePtr msg)
236 {
237     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartSemiStaService(mid, ifaceName);
238     if (ret != WIFI_OPT_SUCCESS) {
239         WifiConfigCenter::GetInstance().SetWifiStopState(true);
240         pConcreteMangerMachine->mcb.onStartFailure(mid);
241         return;
242     }
243     pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pSemiActiveState);
244 }
245 
HandleStartInIdleState(InternalMessagePtr msg)246 void ConcreteMangerMachine::IdleState::HandleStartInIdleState(InternalMessagePtr msg)
247 {
248     mid = msg->GetParam1();
249     WIFI_LOGI("HandleStartInIdleState targetRole:%{public}d mid:%{public}d", mTargetRole, mid);
250     ErrCode res = WifiServiceScheduler::GetInstance().AutoStartScanOnly(mid, ifaceName);
251     if (res != WIFI_OPT_SUCCESS) {
252         WifiConfigCenter::GetInstance().SetWifiStopState(true);
253         pConcreteMangerMachine->mcb.onStartFailure(mid);
254         return;
255     }
256     if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA)) {
257         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartStaService(mid, ifaceName);
258         if (ret != WIFI_OPT_SUCCESS) {
259             WifiConfigCenter::GetInstance().SetWifiStopState(true);
260             pConcreteMangerMachine->mcb.onStartFailure(mid);
261             return;
262         }
263         pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pConnectState);
264     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_SCAN_ONLY)) {
265         WIFI_LOGI("HandleStartInIdleState, current role is %{public}d, start scan only success.", mTargetRole);
266         pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pScanonlyState);
267     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_MIX_SEMI_ACTIVE) ||
268         mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA_SEMI_ACTIVE)) {
269         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartSemiStaService(mid, ifaceName);
270         if (ret != WIFI_OPT_SUCCESS) {
271             WifiConfigCenter::GetInstance().SetWifiStopState(true);
272             pConcreteMangerMachine->mcb.onStartFailure(mid);
273             return;
274         }
275         pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pSemiActiveState);
276     } else {
277         WIFI_LOGE("idlestate start role is error");
278     }
279 }
280 
ConnectState(ConcreteMangerMachine * concreteMangerMachine)281 ConcreteMangerMachine::ConnectState::ConnectState(ConcreteMangerMachine *concreteMangerMachine)
282     : State("ConnectState"), pConcreteMangerMachine(concreteMangerMachine)
283 {}
284 
~ConnectState()285 ConcreteMangerMachine::ConnectState::~ConnectState()
286 {}
287 
GoInState()288 void ConcreteMangerMachine::ConnectState::GoInState()
289 {
290     WIFI_LOGE("ConnectState  GoInState function.\n");
291 }
292 
GoOutState()293 void ConcreteMangerMachine::ConnectState::GoOutState()
294 {
295     WIFI_LOGE("ConnectState  GoOutState function.\n");
296 }
297 
ExecuteStateMsg(InternalMessagePtr msg)298 bool ConcreteMangerMachine::ConnectState::ExecuteStateMsg(InternalMessagePtr msg)
299 {
300     if (msg == nullptr) {
301         return false;
302     }
303     WIFI_LOGE("ConnectState-msgCode=%{public}d is received.\n", msg->GetMessageName());
304     if (pConcreteMangerMachine->HandleCommonMessage(msg)) {
305         return true;
306     }
307     switch (msg->GetMessageName()) {
308         case CONCRETE_CMD_SWITCH_TO_SCAN_ONLY_MODE:
309             SwitchScanOnlyInConnectState();
310             break;
311         case CONCRETE_CMD_SWITCH_TO_SEMI_ACTIVE_MODE:
312             SwitchSemiActiveInConnectState();
313             break;
314         default:
315             break;
316     }
317     return true;
318 }
319 
SwitchScanOnlyInConnectState()320 void ConcreteMangerMachine::ConnectState::SwitchScanOnlyInConnectState()
321 {
322     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
323     if (ret != WIFI_OPT_SUCCESS) {
324         WIFI_LOGE("stop sta failed ret =%{public}d \n", ret);
325     }
326 }
327 
SwitchSemiActiveInConnectState()328 void ConcreteMangerMachine::ConnectState::SwitchSemiActiveInConnectState()
329 {
330     ErrCode ret = pConcreteMangerMachine->SwitchSemiFromEnable();
331     if (ret != WIFI_OPT_SUCCESS) {
332         WIFI_LOGE("switch semi wifi failed ret = %{public}d \n", ret);
333     }
334 }
335 
ScanonlyState(ConcreteMangerMachine * concreteMangerMachine)336 ConcreteMangerMachine::ScanonlyState::ScanonlyState(ConcreteMangerMachine *concreteMangerMachine)
337     : State("ScanonlyState"), pConcreteMangerMachine(concreteMangerMachine)
338 {}
339 
~ScanonlyState()340 ConcreteMangerMachine::ScanonlyState::~ScanonlyState()
341 {}
342 
GoInState()343 void ConcreteMangerMachine::ScanonlyState::GoInState()
344 {
345     WIFI_LOGE("ScanonlyState  GoInState function.\n");
346 }
347 
GoOutState()348 void ConcreteMangerMachine::ScanonlyState::GoOutState()
349 {
350     WIFI_LOGE("ScanonlyState  GoOutState function.\n");
351 }
352 
ExecuteStateMsg(InternalMessagePtr msg)353 bool ConcreteMangerMachine::ScanonlyState::ExecuteStateMsg(InternalMessagePtr msg)
354 {
355     if (msg == nullptr) {
356         return false;
357     }
358     WIFI_LOGE("ScanonlyState-msgCode=%{public}d is received.\n", msg->GetMessageName());
359     if (pConcreteMangerMachine->HandleCommonMessage(msg)) {
360         return true;
361     }
362     switch (msg->GetMessageName()) {
363         case CONCRETE_CMD_SWITCH_TO_CONNECT_MODE:
364             SwitchConnectInScanOnlyState();
365             break;
366         case CONCRETE_CMD_SWITCH_TO_SEMI_ACTIVE_MODE:
367             SwitchSemiActiveInScanOnlyState();
368             break;
369         default:
370             break;
371     }
372     return true;
373 }
374 
SwitchConnectInScanOnlyState()375 void ConcreteMangerMachine::ScanonlyState::SwitchConnectInScanOnlyState()
376 {
377     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartStaService(mid, ifaceName);
378     if (ret != WIFI_OPT_SUCCESS) {
379         pConcreteMangerMachine->mcb.onStartFailure(mid);
380         return;
381     }
382     pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pConnectState);
383 }
384 
SwitchSemiActiveInScanOnlyState()385 void ConcreteMangerMachine::ScanonlyState::SwitchSemiActiveInScanOnlyState()
386 {
387     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartSemiStaService(mid, ifaceName);
388     if (ret != WIFI_OPT_SUCCESS) {
389         pConcreteMangerMachine->mcb.onStartFailure(mid);
390         return;
391     }
392     pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pSemiActiveState);
393 }
394 
SemiActiveState(ConcreteMangerMachine * concreteMangerMachine)395 ConcreteMangerMachine::SemiActiveState::SemiActiveState(ConcreteMangerMachine *concreteMangerMachine)
396     : State("SemiActiveState"), pConcreteMangerMachine(concreteMangerMachine)
397 {}
398 
~SemiActiveState()399 ConcreteMangerMachine::SemiActiveState::~SemiActiveState()
400 {}
401 
GoInState()402 void ConcreteMangerMachine::SemiActiveState::GoInState()
403 {
404     WIFI_LOGI("SemiActiveState  GoInState function.\n");
405 }
406 
GoOutState()407 void ConcreteMangerMachine::SemiActiveState::GoOutState()
408 {
409     WIFI_LOGI("SemiActiveState  GoOutState function.\n");
410 }
411 
ExecuteStateMsg(InternalMessagePtr msg)412 bool ConcreteMangerMachine::SemiActiveState::ExecuteStateMsg(InternalMessagePtr msg)
413 {
414     if (msg == nullptr) {
415         return false;
416     }
417     WIFI_LOGI("SemiActiveState-msgCode=%{public}d is received.\n", msg->GetMessageName());
418     if (pConcreteMangerMachine->HandleCommonMessage(msg)) {
419         return true;
420     }
421     switch (msg->GetMessageName()) {
422         case CONCRETE_CMD_SWITCH_TO_CONNECT_MODE:
423             SwitchConnectInSemiActiveState();
424             break;
425         case CONCRETE_CMD_SWITCH_TO_SCAN_ONLY_MODE:
426             SwitchScanOnlyInSemiActiveState();
427             break;
428         case CONCRETE_CMD_SWITCH_TO_SEMI_ACTIVE_MODE:
429             if (pConcreteMangerMachine->mTargetRole ==
430                 static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA_SEMI_ACTIVE)) {
431                 WIFI_LOGI("switch ROLE_CLIENT_STA_SEMI_ACTIVE");
432                 WifiManager::GetInstance().GetWifiScanManager()->CheckAndStopScanService(mid);
433             } else {
434                 WIFI_LOGI("switch ROLE_CLIENT_MIX_SEMI_ACTIVE");
435                 WifiServiceScheduler::GetInstance().AutoStartScanOnly(mid, ifaceName);
436             }
437             WifiManager::GetInstance().GetWifiTogglerManager()->StopSemiWifiToggledTimer();
438             break;
439         default:
440             break;
441     }
442     return true;
443 }
444 
SwitchConnectInSemiActiveState()445 void ConcreteMangerMachine::SemiActiveState::SwitchConnectInSemiActiveState()
446 {
447     WifiServiceScheduler::GetInstance().AutoStartScanOnly(mid, ifaceName);
448     ErrCode ret = pConcreteMangerMachine->SwitchEnableFromSemi();
449     if (ret != WIFI_OPT_SUCCESS) {
450         WIFI_LOGE("SemiActiveState SwitchEnableFromSemi failed");
451         pConcreteMangerMachine->mcb.onStartFailure(mid);
452         return;
453     }
454     pConcreteMangerMachine->SwitchState(pConcreteMangerMachine->pConnectState);
455 }
456 
SwitchScanOnlyInSemiActiveState()457 void ConcreteMangerMachine::SemiActiveState::SwitchScanOnlyInSemiActiveState()
458 {
459     WIFI_LOGI("SwitchScanOnlyInSemiActiveState");
460     ErrCode ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
461     if (ret != WIFI_OPT_SUCCESS) {
462         WIFI_LOGE("Stop sta failed ret = %{public}d", ret);
463     }
464 }
465 
HandleCommonMessage(InternalMessagePtr msg)466 bool ConcreteMangerMachine::HandleCommonMessage(InternalMessagePtr msg)
467 {
468     switch (msg->GetMessageName()) {
469         case CONCRETE_CMD_STA_STOP:
470             HandleStaStop();
471             return true;
472         case CONCRETE_CMD_STA_START:
473             HandleStaStart();
474             return true;
475         case CONCRETE_CMD_STOP:
476             DelayMessage(msg);
477             SwitchState(pDefaultState);
478             return true;
479         case CONCRETE_CMD_STA_SEMI_ACTIVE:
480             HandleStaSemiActive();
481             return true;
482         case CONCRETE_CMD_STA_REMOVED:
483             ClearIfaceName();
484             return true;
485         default:
486             return false;
487     }
488 }
489 
HandleStaStop()490 void ConcreteMangerMachine::HandleStaStop()
491 {
492     if (WifiConfigCenter::GetInstance().GetWifiStopState()) {
493         WIFI_LOGE("Sta stoped remove manager.");
494         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStopScanOnly(mid, true);
495         if (ret != WIFI_OPT_SUCCESS) {
496             WIFI_LOGE("Stop scanonly failed ret = %{public}d", ret);
497         }
498         return ReportClose();
499     }
500     if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_SCAN_ONLY)) {
501 #ifdef HDI_CHIP_INTERFACE_SUPPORT
502         DelayedSingleton<HalDeviceManager>::GetInstance()->SetNetworkUpDown(
503             WifiConfigCenter::GetInstance().GetStaIfaceName(), true);
504 #endif
505         SwitchState(pScanonlyState);
506     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA)) {
507         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartStaService(mid, ifaceName);
508         if (ret != WIFI_OPT_SUCCESS) {
509             mcb.onStartFailure(mid);
510             return;
511         }
512         SwitchState(pConnectState);
513     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_MIX_SEMI_ACTIVE) ||
514         mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA_SEMI_ACTIVE)) {
515         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStartSemiStaService(mid, ifaceName);
516         if (ret != WIFI_OPT_SUCCESS) {
517             mcb.onStartFailure(mid);
518             return;
519         }
520         SwitchState(pSemiActiveState);
521     } else {
522         WIFI_LOGE("Now targetrole is unknow, stop concrete.");
523         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStopScanOnly(mid, true);
524         if (ret != WIFI_OPT_SUCCESS) {
525             WIFI_LOGE("Stop scanonly failed ret = %{public}d", ret);
526         }
527         return ReportClose();
528     }
529 }
530 
ReportClose()531 void ConcreteMangerMachine::ReportClose()
532 {
533 #ifdef HDI_CHIP_INTERFACE_SUPPORT
534     if (!ifaceName.empty()) {
535         mcb.onStopped(mid);
536     } else {
537         mcb.onRemoved(mid);
538     }
539 #else
540     mcb.onStopped(mid);
541 #endif
542 }
543 
HandleStaStart()544 void ConcreteMangerMachine::HandleStaStart()
545 {
546     ErrCode ret;
547 
548     if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_SCAN_ONLY)) {
549         ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
550         if (ret != WIFI_OPT_SUCCESS) {
551             WIFI_LOGE("Stop sta failed ret = %{public}d", ret);
552         }
553     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA)) {
554         SwitchState(pConnectState);
555     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_MIX_SEMI_ACTIVE) ||
556         mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA_SEMI_ACTIVE)) {
557         ret = SwitchSemiFromEnable();
558         if (ret != WIFI_OPT_SUCCESS) {
559             WIFI_LOGE("switch semi wifi failed ret = %{public}d", ret);
560         }
561     } else {
562         WIFI_LOGE("Now targetrole is unknow.");
563         ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
564         if (ret != WIFI_OPT_SUCCESS) {
565             WIFI_LOGE("Stop sta failed ret = %{public}d", ret);
566         }
567     }
568 }
569 
HandleStaSemiActive()570 void ConcreteMangerMachine::HandleStaSemiActive()
571 {
572     ErrCode ret;
573 
574     if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA)) {
575         ret = SwitchEnableFromSemi();
576         if (ret != WIFI_OPT_SUCCESS) {
577             WIFI_LOGE("switch enable failed ret = %{public}d", ret);
578             mcb.onStartFailure(mid);
579             return;
580         }
581         WifiServiceScheduler::GetInstance().AutoStartScanOnly(mid, ifaceName);
582     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_SCAN_ONLY)) {
583         ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
584         if (ret != WIFI_OPT_SUCCESS) {
585             WIFI_LOGE("Stop sta failed ret = %{public}d", ret);
586         }
587     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_MIX_SEMI_ACTIVE)) {
588         WifiManager::GetInstance().GetWifiScanManager()->CheckAndStartScanService(mid);
589         SwitchState(pSemiActiveState);
590     } else if (mTargetRole == static_cast<int>(ConcreteManagerRole::ROLE_CLIENT_STA_SEMI_ACTIVE)) {
591         WifiManager::GetInstance().GetWifiScanManager()->CheckAndStopScanService(mid);
592         SwitchState(pSemiActiveState);
593     } else {
594         WIFI_LOGE("Now targetrole is unknow.");
595         ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
596         if (ret != WIFI_OPT_SUCCESS) {
597             WIFI_LOGE("Stop sta failed ret = %{public}d", ret);
598         }
599     }
600 }
601 
SwitchSemiFromEnable()602 ErrCode ConcreteMangerMachine::SwitchSemiFromEnable()
603 {
604     auto detailState = WifiConfigCenter::GetInstance().GetWifiDetailState(mid);
605     WIFI_LOGI("SwitchSemiFromEnable: current sta detailState:%{public}d", detailState);
606     if (detailState == WifiDetailState::STATE_SEMI_ACTIVE || detailState == WifiDetailState::STATE_SEMI_ACTIVATING) {
607         return WIFI_OPT_SUCCESS;
608     }
609     IStaService *pService = WifiServiceManager::GetInstance().GetStaServiceInst(mid);
610     if (pService == nullptr) {
611         WIFI_LOGE("SwitchSemiFromEnable, Instance get sta service is null!");
612         WifiConfigCenter::GetInstance().SetWifiMidState(WifiOprMidState::CLOSED, mid);
613         WifiServiceManager::GetInstance().UnloadService(WIFI_SERVICE_STA, mid);
614 #ifdef FEATURE_WIFI_PRO_SUPPORT
615         WifiServiceManager::GetInstance().UnloadService(WIFI_SERVICE_WIFIPRO, mid);
616 #endif
617 #ifdef FEATURE_SELF_CURE_SUPPORT
618         WifiServiceManager::GetInstance().UnloadService(WIFI_SERVICE_SELFCURE, mid);
619 #endif
620         return WIFI_OPT_FAILED;
621     }
622     WifiServiceScheduler::GetInstance().DispatchWifiSemiActiveRes(OperateResState::ENABLE_SEMI_WIFI_OPENING, mid);
623     ErrCode ret = pService->DisableStaService();
624     if (ret != static_cast<int>(WIFI_OPT_SUCCESS)) {
625         WIFI_LOGE("DisableStaService failed!");
626         return WIFI_OPT_FAILED;
627     }
628     WifiServiceScheduler::GetInstance().DispatchWifiSemiActiveRes(OperateResState::ENABLE_SEMI_WIFI_SUCCEED, mid);
629     auto &ins = WifiManager::GetInstance().GetWifiTogglerManager()->GetControllerMachine();
630     ins->HandleStaSemiActive(mid);
631     return WIFI_OPT_SUCCESS;
632 }
633 
SwitchEnableFromSemi()634 ErrCode ConcreteMangerMachine::SwitchEnableFromSemi()
635 {
636     auto detailState = WifiConfigCenter::GetInstance().GetWifiDetailState(mid);
637     WIFI_LOGI("SwitchEnableFromSemi, current sta detailState:%{public}d", detailState);
638     if (detailState == WifiDetailState::STATE_ACTIVATED) {
639         auto &ins = WifiManager::GetInstance().GetWifiTogglerManager()->GetControllerMachine();
640         ins->HandleStaStart(mid);
641         return WIFI_OPT_SUCCESS;
642     }
643     WifiOprMidState staState = WifiConfigCenter::GetInstance().GetWifiMidState(mid);
644     if (!WifiConfigCenter::GetInstance().SetWifiMidState(staState, WifiOprMidState::OPENING, mid)) {
645         WIFI_LOGE("SwitchEnableFromSemi, set wifi mid state opening failed!");
646         return WIFI_OPT_FAILED;
647     }
648     ErrCode errCode = WIFI_OPT_FAILED;
649     IStaService *pService = WifiServiceManager::GetInstance().GetStaServiceInst(mid);
650     if (pService == nullptr) {
651         WIFI_LOGE("Get %{public}s service failed!", WIFI_SERVICE_STA);
652         return WIFI_OPT_FAILED;
653     }
654     WifiServiceScheduler::GetInstance().DispatchWifiOpenRes(OperateResState::OPEN_WIFI_OPENING, mid);
655     errCode = pService->EnableStaService();
656     if (errCode != WIFI_OPT_SUCCESS) {
657         WIFI_LOGE("Service enable sta failed ,ret %{public}d!", static_cast<int>(errCode));
658         return WIFI_OPT_FAILED;
659     }
660     WifiServiceScheduler::GetInstance().DispatchWifiOpenRes(OperateResState::OPEN_WIFI_SUCCEED, mid);
661     WifiManager::GetInstance().PushServiceCloseMsg(WifiCloseServiceCode::STA_MSG_OPENED, mid);
662     auto &ins = WifiManager::GetInstance().GetWifiTogglerManager()->GetControllerMachine();
663     ins->HandleStaStart(mid);
664     return WIFI_OPT_SUCCESS;
665 }
666 
CheckAndContinueToStopWifi(InternalMessagePtr msg)667 void ConcreteMangerMachine::CheckAndContinueToStopWifi(InternalMessagePtr msg)
668 {
669     if (WifiConfigCenter::GetInstance().GetWifiStopState()) {
670         WIFI_LOGE("CheckAndContinueToStopWifi: wifi is stoping");
671         return;
672     }
673 
674     mTargetRole = static_cast<int>(ConcreteManagerRole::ROLE_UNKNOW);
675     WifiOprMidState staState = WifiConfigCenter::GetInstance().GetWifiMidState(mid);
676     auto detailState = WifiConfigCenter::GetInstance().GetWifiDetailState(mid);
677     WIFI_LOGI("CheckAndContinueToStopWifi: current sta state: %{public}d detailState:%{public}d", staState,
678         detailState);
679     if (detailState != WifiDetailState::STATE_SEMI_ACTIVE && detailState != WifiDetailState::STATE_SEMI_ACTIVATING &&
680         (staState == WifiOprMidState::CLOSING || staState == WifiOprMidState::OPENING)) {
681         return;
682     }
683 
684     WifiConfigCenter::GetInstance().SetWifiStopState(true);
685     WIFI_LOGI("Set WifiStopState is true.");
686     if (staState == WifiOprMidState::RUNNING || detailState == WifiDetailState::STATE_SEMI_ACTIVE ||
687         detailState == WifiDetailState::STATE_SEMI_ACTIVATING) {
688         ErrCode ret = WifiServiceScheduler::GetInstance().AutoStopStaService(mid);
689         if (ret != WIFI_OPT_SUCCESS) {
690             WIFI_LOGE("stop sta failed in timer ret = %{public}d", ret);
691             WifiConfigCenter::GetInstance().SetWifiStopState(false);
692             auto &ins = WifiManager::GetInstance().GetWifiTogglerManager()->GetControllerMachine();
693             ins->HandleStaClose(mid);
694         }
695     } else {
696         auto &ins = WifiManager::GetInstance().GetWifiTogglerManager()->GetControllerMachine();
697         ins->HandleStaClose(mid);
698     }
699 }
700 
ClearIfaceName()701 void ConcreteMangerMachine::ClearIfaceName()
702 {
703     ifaceName.clear();
704 }
705 } // namespace Wifi
706 } // namespace OHOS
707