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 #include "widget_schedule_node_impl.h"
16 
17 #include <mutex>
18 #include <sstream>
19 
20 #include "nocopyable.h"
21 
22 #include "iam_check.h"
23 #include "iam_logger.h"
24 #include "iam_ptr.h"
25 #include "iam_para2str.h"
26 #include "iam_common_defines.h"
27 #include "relative_timer.h"
28 #include "user_auth_common_defines.h"
29 
30 #define LOG_TAG "USER_AUTH_SA"
31 namespace OHOS {
32 namespace UserIam {
33 namespace UserAuth {
WidgetScheduleNodeImpl()34 WidgetScheduleNodeImpl::WidgetScheduleNodeImpl()
35 {
36     machine_ = MakeFiniteStateMachine();
37     if (machine_ == nullptr) {
38         IAM_LOGE("Failed to create make FSM of widget schedule");
39         return;
40     }
41     threadHandler_ = ThreadHandler::GetSingleThreadInstance();
42     machine_->SetThreadHandler(threadHandler_);
43 }
44 
MakeFiniteStateMachine()45 std::shared_ptr<FiniteStateMachine> WidgetScheduleNodeImpl::MakeFiniteStateMachine()
46 {
47     auto builder = FiniteStateMachine::Builder::New("widget_schedule", S_WIDGET_INIT);
48     if (builder == nullptr) {
49         return nullptr;
50     }
51     builder->MakeTransition(S_WIDGET_INIT, E_START_WIDGET, S_WIDGET_WAITING,
52         [this](FiniteStateMachine &machine, uint32_t event) { OnStartSchedule(machine, event); });
53     builder->MakeTransition(S_WIDGET_WAITING, E_START_AUTH, S_WIDGET_AUTH_RUNNING,
54         [this](FiniteStateMachine &machine, uint32_t event) { OnStartAuth(machine, event); });
55     builder->MakeTransition(S_WIDGET_WAITING, E_CANCEL_AUTH, S_WIDGET_AUTH_FINISHED,
56         [this](FiniteStateMachine &machine, uint32_t event) { OnStopSchedule(machine, event); });
57     builder->MakeTransition(S_WIDGET_WAITING, E_NAVI_PIN_AUTH, S_WIDGET_AUTH_FINISHED,
58         [this](FiniteStateMachine &machine, uint32_t event) { OnNaviPinAuth(machine, event); });
59     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_COMPLETE_AUTH, S_WIDGET_AUTH_FINISHED,
60         [this](FiniteStateMachine &machine, uint32_t event) { OnSuccessAuth(machine, event); });
61     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_CANCEL_AUTH, S_WIDGET_AUTH_FINISHED,
62         [this](FiniteStateMachine &machine, uint32_t event) { OnStopSchedule(machine, event); });
63     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_NAVI_PIN_AUTH, S_WIDGET_AUTH_FINISHED,
64         [this](FiniteStateMachine &machine, uint32_t event) { OnNaviPinAuth(machine, event); });
65     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_START_AUTH, S_WIDGET_AUTH_RUNNING,
66         [this](FiniteStateMachine &machine, uint32_t event) { OnStartAuth(machine, event); });
67     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_UPDATE_AUTH, S_WIDGET_AUTH_RUNNING,
68         [this](FiniteStateMachine &machine, uint32_t event) { OnStopAuthList(machine, event); });
69     builder->MakeTransition(S_WIDGET_WAITING, E_WIDGET_PARA_INVALID, S_WIDGET_AUTH_FINISHED,
70         [this](FiniteStateMachine &machine, uint32_t event) { OnWidgetParaInvalid(machine, event); });
71     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_WIDGET_PARA_INVALID, S_WIDGET_AUTH_FINISHED,
72         [this](FiniteStateMachine &machine, uint32_t event) { OnWidgetParaInvalid(machine, event); });
73     // Add for AuthWidget rotate
74     builder->MakeTransition(S_WIDGET_AUTH_RUNNING, E_WIDGET_RELOAD, S_WIDGET_RELOAD_WAITING,
75         [this](FiniteStateMachine &machine, uint32_t event) { OnWidgetReloadInit(machine, event); });
76     builder->MakeTransition(S_WIDGET_WAITING, E_WIDGET_RELOAD, S_WIDGET_RELOAD_WAITING,
77         [this](FiniteStateMachine &machine, uint32_t event) { OnWidgetReloadInit(machine, event); });
78     builder->MakeTransition(S_WIDGET_RELOAD_WAITING, E_CANCEL_AUTH, S_WIDGET_WAITING,
79         [this](FiniteStateMachine &machine, uint32_t event) { OnWidgetReload(machine, event); });
80 
81     return builder->Build();
82 }
83 
TryKickMachine(Event event)84 bool WidgetScheduleNodeImpl::TryKickMachine(Event event)
85 {
86     if (machine_ == nullptr) {
87         IAM_LOGE("Invalid FSM of widget schedule");
88         return false;
89     }
90     machine_->Schedule(event);
91     return true;
92 }
93 
StartSchedule()94 bool WidgetScheduleNodeImpl::StartSchedule()
95 {
96     iamHitraceHelper_ = Common::MakeShared<IamHitraceHelper>("widget_schedule");
97     {
98         std::lock_guard<std::mutex> lock(mutex_);
99         if (!TryKickMachine(E_START_WIDGET)) {
100             return false;
101         }
102     }
103     return true;
104 }
105 
StopSchedule()106 bool WidgetScheduleNodeImpl::StopSchedule()
107 {
108     std::lock_guard<std::mutex> lock(mutex_);
109     return TryKickMachine(E_CANCEL_AUTH);
110 }
111 
StartAuthList(const std::vector<AuthType> & authTypeList,bool endAfterFirstFail,AuthIntent authIntent)112 bool WidgetScheduleNodeImpl::StartAuthList(const std::vector<AuthType> &authTypeList, bool endAfterFirstFail,
113     AuthIntent authIntent)
114 {
115     std::lock_guard<std::mutex> lock(mutex_);
116     startAuthTypeList_.clear();
117     for (auto authType : authTypeList) {
118         startAuthTypeList_.emplace_back(authType);
119         IAM_LOGI("Command(type:%{public}d) on result start.", authType);
120     }
121     endAfterFirstFail_ = endAfterFirstFail;
122     authIntent_ = authIntent;
123     return TryKickMachine(E_START_AUTH);
124 }
125 
StopAuthList(const std::vector<AuthType> & authTypeList)126 bool WidgetScheduleNodeImpl::StopAuthList(const std::vector<AuthType> &authTypeList)
127 {
128     std::lock_guard<std::mutex> lock(mutex_);
129     stopAuthTypeList_ = authTypeList;
130     return TryKickMachine(E_UPDATE_AUTH);
131 }
132 
SuccessAuth(AuthType authType)133 bool WidgetScheduleNodeImpl::SuccessAuth(AuthType authType)
134 {
135     std::lock_guard<std::mutex> lock(mutex_);
136     successAuthType_ = authType;
137     IAM_LOGI("success %{public}d.", E_COMPLETE_AUTH);
138     return TryKickMachine(E_COMPLETE_AUTH);
139 }
140 
NaviPinAuth()141 bool WidgetScheduleNodeImpl::NaviPinAuth()
142 {
143     std::lock_guard<std::mutex> lock(mutex_);
144     return TryKickMachine(E_NAVI_PIN_AUTH);
145 }
146 
WidgetParaInvalid()147 bool WidgetScheduleNodeImpl::WidgetParaInvalid()
148 {
149     std::lock_guard<std::mutex> lock(mutex_);
150     return TryKickMachine(E_WIDGET_PARA_INVALID);
151 }
152 
WidgetReload(uint32_t orientation,uint32_t needRotate,uint32_t alreadyLoad,AuthType & rotateAuthType)153 bool WidgetScheduleNodeImpl::WidgetReload(uint32_t orientation, uint32_t needRotate, uint32_t alreadyLoad,
154     AuthType &rotateAuthType)
155 {
156     std::lock_guard<std::mutex> lock(mutex_);
157     orientation_ = orientation;
158     needRotate_ = needRotate;
159     alreadyLoad_ = alreadyLoad;
160     rotateAuthType_ = rotateAuthType;
161     return TryKickMachine(E_WIDGET_RELOAD);
162 }
163 
SetCallback(std::shared_ptr<WidgetScheduleNodeCallback> callback)164 void WidgetScheduleNodeImpl::SetCallback(std::shared_ptr<WidgetScheduleNodeCallback> callback)
165 {
166     callback_ = callback;
167 }
168 
OnStartSchedule(FiniteStateMachine & machine,uint32_t event)169 void WidgetScheduleNodeImpl::OnStartSchedule(FiniteStateMachine &machine, uint32_t event)
170 {
171     auto callback = callback_.lock();
172     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
173     if (!callback->LaunchWidget()) {
174         IAM_LOGE("Failed to launch widget, cancel Auth");
175         StopSchedule();
176     }
177 }
178 
OnStopSchedule(FiniteStateMachine & machine,uint32_t event)179 void WidgetScheduleNodeImpl::OnStopSchedule(FiniteStateMachine &machine, uint32_t event)
180 {
181     auto callback = callback_.lock();
182     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
183     callback->EndAuthAsCancel();
184     iamHitraceHelper_ = nullptr;
185 }
186 
OnStartAuth(FiniteStateMachine & machine,uint32_t event)187 void WidgetScheduleNodeImpl::OnStartAuth(FiniteStateMachine &machine, uint32_t event)
188 {
189     auto callback = callback_.lock();
190     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
191     std::set<AuthType> startAuthTypeSet;
192     for (auto authType : startAuthTypeList_) {
193         if (runningAuthTypeSet_.find(authType) == runningAuthTypeSet_.end()) {
194             startAuthTypeSet.emplace(authType);
195         }
196     }
197     callback->ExecuteAuthList(startAuthTypeSet, endAfterFirstFail_, authIntent_);
198 }
199 
OnStopAuthList(FiniteStateMachine & machine,uint32_t event)200 void WidgetScheduleNodeImpl::OnStopAuthList(FiniteStateMachine &machine, uint32_t event)
201 {
202     auto callback = callback_.lock();
203     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
204     for (auto authType : stopAuthTypeList_) {
205         runningAuthTypeSet_.erase(authType);
206     }
207     callback->StopAuthList(stopAuthTypeList_);
208 }
209 
OnSuccessAuth(FiniteStateMachine & machine,uint32_t event)210 void WidgetScheduleNodeImpl::OnSuccessAuth(FiniteStateMachine &machine, uint32_t event)
211 {
212     auto callback = callback_.lock();
213     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
214     runningAuthTypeSet_.erase(successAuthType_);
215     callback->SuccessAuth(successAuthType_);
216 }
217 
OnNaviPinAuth(FiniteStateMachine & machine,uint32_t event)218 void WidgetScheduleNodeImpl::OnNaviPinAuth(FiniteStateMachine &machine, uint32_t event)
219 {
220     auto callback = callback_.lock();
221     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
222     callback->EndAuthAsNaviPin();
223 }
224 
OnWidgetParaInvalid(FiniteStateMachine & machine,uint32_t event)225 void WidgetScheduleNodeImpl::OnWidgetParaInvalid(FiniteStateMachine &machine, uint32_t event)
226 {
227     auto callback = callback_.lock();
228     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
229     callback->EndAuthAsWidgetParaInvalid();
230 }
231 
OnWidgetReloadInit(FiniteStateMachine & machine,uint32_t event)232 void WidgetScheduleNodeImpl::OnWidgetReloadInit(FiniteStateMachine &machine, uint32_t event)
233 {
234     auto callback = callback_.lock();
235     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
236     IAM_LOGI("Widget need reload, init");
237     callback->AuthWidgetReloadInit();
238 }
239 
OnWidgetReload(FiniteStateMachine & machine,uint32_t event)240 void WidgetScheduleNodeImpl::OnWidgetReload(FiniteStateMachine &machine, uint32_t event)
241 {
242     auto callback = callback_.lock();
243     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
244     IAM_LOGI("Widget need reload");
245     const uint32_t reloadInitMs = 100;
246     auto sleepTime = std::chrono::milliseconds(reloadInitMs);
247     std::this_thread::sleep_for(sleepTime);
248     if (!callback->AuthWidgetReload(orientation_, needRotate_, alreadyLoad_, rotateAuthType_)) {
249         IAM_LOGE("Failed to reload widget, cancel Auth");
250         StopSchedule();
251     }
252 }
253 } // namespace UserAuth
254 } // namespace UserIam
255 } // namespace OHOS