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 <shared_mutex>
17 
18 #include "sam_log.h"
19 #include "string_ex.h"
20 #include "samgr_err_code.h"
21 #include "schedule/system_ability_state_machine.h"
22 
23 namespace OHOS {
SystemAbilityStateMachine(const std::shared_ptr<SystemAbilityStateListener> & listener)24 SystemAbilityStateMachine::SystemAbilityStateMachine(const std::shared_ptr<SystemAbilityStateListener>& listener)
25 {
26     InitStateHandlerMap(listener);
27 }
28 
InitStateHandlerMap(const std::shared_ptr<SystemAbilityStateListener> & listener)29 void SystemAbilityStateMachine::InitStateHandlerMap(const std::shared_ptr<SystemAbilityStateListener>& listener)
30 {
31     abilityStateHandlerMap_[SystemAbilityState::NOT_LOADED] = std::make_shared<NotLoadedStateHandler>(listener);
32     abilityStateHandlerMap_[SystemAbilityState::LOADING] = std::make_shared<LoadingStateHandler>(listener);
33     abilityStateHandlerMap_[SystemAbilityState::LOADED] = std::make_shared<LoadedStateHandler>(listener);
34     abilityStateHandlerMap_[SystemAbilityState::UNLOADABLE] = std::make_shared<UnloadableStateHandler>(listener);
35     abilityStateHandlerMap_[SystemAbilityState::UNLOADING] = std::make_shared<UnloadingStateHandler>(listener);
36 
37     processStateHandlerMap_[SystemProcessState::NOT_STARTED] = std::make_shared<NotStartedStateHandler>(listener);
38     processStateHandlerMap_[SystemProcessState::STARTED] = std::make_shared<StartedStateHandler>(listener);
39     processStateHandlerMap_[SystemProcessState::STOPPING] = std::make_shared<StoppingStateHandler>(listener);
40 }
41 
AbilityStateTransitionLocked(const std::shared_ptr<SystemAbilityContext> & context,const SystemAbilityState nextState)42 int32_t SystemAbilityStateMachine::AbilityStateTransitionLocked(const std::shared_ptr<SystemAbilityContext>& context,
43     const SystemAbilityState nextState)
44 {
45     if (context == nullptr) {
46         HILOGE("Scheduler:context is null");
47         return SA_CONTEXT_NULL;
48     }
49     if (abilityStateHandlerMap_.count(nextState) == 0) {
50         HILOGE("Scheduler:invalid next state:%{public}d", nextState);
51         return INVALID_SA_NEXT_STATE;
52     }
53     std::shared_ptr<SystemAbilityStateHandler> handler = abilityStateHandlerMap_[nextState];
54     if (handler == nullptr) {
55         HILOGE("Scheduler:next state:%{public}d handler is null", nextState);
56         return SA_STATE_HANDLER_NULL;
57     }
58     SystemAbilityState currentState = context->state;
59     if (currentState == nextState) {
60         HILOGI("Scheduler SA:%{public}d state current %{public}d is same as next %{public}d",
61             context->systemAbilityId, currentState, nextState);
62         return ERR_OK;
63     }
64     if (!handler->CanEnter(currentState)) {
65         HILOGE("Scheduler SA:%{public}d can't state %{public}d to %{public}d",
66             context->systemAbilityId, currentState, nextState);
67         return TRANSIT_SA_STATE_FAIL;
68     }
69     if (!UpdateStateCount(context->ownProcessContext, currentState, nextState)) {
70         HILOGE("Scheduler SA:%{public}d update state count fail", context->systemAbilityId);
71         return UPDATE_STATE_COUNT_FAIL;
72     }
73     context->state = nextState;
74     HILOGD("Scheduler SA:%{public}d state %{public}d to %{public}d",
75         context->systemAbilityId, currentState, nextState);
76     handler->OnEnter(context);
77     return ERR_OK;
78 }
79 
UpdateStateCount(const std::shared_ptr<SystemProcessContext> & context,SystemAbilityState fromState,SystemAbilityState toState)80 bool SystemAbilityStateMachine::UpdateStateCount(const std::shared_ptr<SystemProcessContext>& context,
81     SystemAbilityState fromState, SystemAbilityState toState)
82 {
83     if (context == nullptr) {
84         HILOGE("Scheduler:proc context is null");
85         return false;
86     }
87     std::lock_guard<std::mutex> autoLock(context->stateCountLock);
88     if (!context->abilityStateCountMap.count(fromState) || !context->abilityStateCountMap.count(toState)) {
89         HILOGE("Scheduler proc:%{public}s invalid state",
90             Str16ToStr8(context->processName).c_str());
91         return false;
92     }
93     if (context->abilityStateCountMap[fromState] <= 0) {
94         HILOGE("Scheduler proc:%{public}s invalid current state count",
95             Str16ToStr8(context->processName).c_str());
96         return false;
97     }
98     context->abilityStateCountMap[fromState]--;
99     context->abilityStateCountMap[toState]++;
100     return true;
101 }
102 
ProcessStateTransitionLocked(const std::shared_ptr<SystemProcessContext> & context,SystemProcessState nextState)103 int32_t SystemAbilityStateMachine::ProcessStateTransitionLocked(const std::shared_ptr<SystemProcessContext>& context,
104     SystemProcessState nextState)
105 {
106     if (context == nullptr) {
107         HILOGE("Scheduler:proc context is null");
108         return PROC_CONTEXT_NULL;
109     }
110     if (processStateHandlerMap_.count(nextState) == 0) {
111         HILOGE("Scheduler:invalid next state:%{public}d", nextState);
112         return INVALID_PROC_NEXT_STATE;
113     }
114     std::shared_ptr<SystemProcessStateHandler> handler = processStateHandlerMap_[nextState];
115     if (handler == nullptr) {
116         HILOGE("Scheduler:next state:%{public}d handler is null", nextState);
117         return PROC_STATE_HANDLER_NULL;
118     }
119     SystemProcessState currentState = context->state;
120     if (currentState == nextState) {
121         HILOGI("Scheduler proc:%{public}s state current %{public}d is same as next %{public}d",
122             Str16ToStr8(context->processName).c_str(), currentState, nextState);
123         return ERR_OK;
124     }
125     if (!handler->CanEnter(currentState)) {
126         HILOGI("Scheduler proc:%{public}s can't state %{public}d to %{public}d",
127             Str16ToStr8(context->processName).c_str(), currentState, nextState);
128         return TRANSIT_PROC_STATE_FAIL;
129     }
130     context->state = nextState;
131     HILOGI("Scheduler proc:%{public}s state %{public}d to %{public}d",
132         Str16ToStr8(context->processName).c_str(), currentState, nextState);
133     handler->OnEnter(context);
134     return ERR_OK;
135 }
136 
CanEnter(SystemAbilityState fromState)137 bool NotLoadedStateHandler::CanEnter(SystemAbilityState fromState)
138 {
139     return fromState != SystemAbilityState::NOT_LOADED;
140 }
141 
OnEnter(const std::shared_ptr<SystemAbilityContext> & context)142 void NotLoadedStateHandler::OnEnter(const std::shared_ptr<SystemAbilityContext>& context)
143 {
144     auto listener = listener_.lock();
145     if (listener == nullptr) {
146         HILOGE("Scheduler:listener is null");
147         return;
148     }
149     listener->OnAbilityNotLoadedLocked(context->systemAbilityId);
150 }
151 
CanEnter(SystemAbilityState fromState)152 bool LoadingStateHandler::CanEnter(SystemAbilityState fromState)
153 {
154     return fromState == SystemAbilityState::NOT_LOADED;
155 }
156 
OnEnter(const std::shared_ptr<SystemAbilityContext> & context)157 void LoadingStateHandler::OnEnter(const std::shared_ptr<SystemAbilityContext>& context)
158 {
159     auto listener = listener_.lock();
160     if (listener == nullptr) {
161         HILOGE("Scheduler:listener is null");
162         return;
163     }
164     listener->OnAbilityLoadingLocked(context->systemAbilityId);
165 }
166 
CanEnter(SystemAbilityState fromState)167 bool LoadedStateHandler::CanEnter(SystemAbilityState fromState)
168 {
169     if (fromState == SystemAbilityState::NOT_LOADED
170         || fromState == SystemAbilityState::LOADING
171         || fromState == SystemAbilityState::UNLOADABLE) {
172         return true;
173     }
174     return false;
175 }
176 
OnEnter(const std::shared_ptr<SystemAbilityContext> & context)177 void LoadedStateHandler::OnEnter(const std::shared_ptr<SystemAbilityContext>& context)
178 {
179     auto listener = listener_.lock();
180     if (listener == nullptr) {
181         HILOGE("Scheduler:listener is null");
182         return;
183     }
184     listener->OnAbilityLoadedLocked(context->systemAbilityId);
185 }
186 
CanEnter(SystemAbilityState fromState)187 bool UnloadableStateHandler::CanEnter(SystemAbilityState fromState)
188 {
189     return fromState == SystemAbilityState::LOADED;
190 }
191 
OnEnter(const std::shared_ptr<SystemAbilityContext> & context)192 void UnloadableStateHandler::OnEnter(const std::shared_ptr<SystemAbilityContext>& context)
193 {
194     auto listener = listener_.lock();
195     if (listener == nullptr) {
196         HILOGE("Scheduler:listener is null");
197         return;
198     }
199     listener->OnAbilityUnloadableLocked(context->systemAbilityId);
200 }
201 
CanEnter(SystemAbilityState fromState)202 bool UnloadingStateHandler::CanEnter(SystemAbilityState fromState)
203 {
204     return fromState == SystemAbilityState::UNLOADABLE;
205 }
206 
OnEnter(const std::shared_ptr<SystemAbilityContext> & context)207 void UnloadingStateHandler::OnEnter(const std::shared_ptr<SystemAbilityContext>& context)
208 {
209     auto listener = listener_.lock();
210     if (listener == nullptr) {
211         HILOGE("Scheduler:listener is null");
212         return;
213     }
214     listener->OnAbilityUnloadingLocked(context->systemAbilityId);
215 }
216 
CanEnter(SystemProcessState fromState)217 bool NotStartedStateHandler::CanEnter(SystemProcessState fromState)
218 {
219     return fromState != SystemProcessState::NOT_STARTED;
220 }
221 
OnEnter(const std::shared_ptr<SystemProcessContext> & context)222 void NotStartedStateHandler::OnEnter(const std::shared_ptr<SystemProcessContext>& context)
223 {
224     auto listener = listener_.lock();
225     if (listener == nullptr) {
226         HILOGE("Scheduler:listener is null");
227         return;
228     }
229     listener->OnProcessNotStartedLocked(context->processName);
230 }
231 
CanEnter(SystemProcessState fromState)232 bool StartedStateHandler::CanEnter(SystemProcessState fromState)
233 {
234     return fromState == SystemProcessState::NOT_STARTED;
235 }
236 
OnEnter(const std::shared_ptr<SystemProcessContext> & context)237 void StartedStateHandler::OnEnter(const std::shared_ptr<SystemProcessContext>& context)
238 {
239     auto listener = listener_.lock();
240     if (listener == nullptr) {
241         HILOGE("Scheduler:listener is null");
242         return;
243     }
244     listener->OnProcessStartedLocked(context->processName);
245 }
246 
CanEnter(SystemProcessState fromState)247 bool StoppingStateHandler::CanEnter(SystemProcessState fromState)
248 {
249     return fromState == SystemProcessState::STARTED;
250 }
251 
OnEnter(const std::shared_ptr<SystemProcessContext> & context)252 void StoppingStateHandler::OnEnter(const std::shared_ptr<SystemProcessContext>& context)
253 {
254     auto listener = listener_.lock();
255     if (listener == nullptr) {
256         HILOGE("Scheduler:listener is null");
257         return;
258     }
259     listener->OnProcessStoppingLocked(context->processName);
260 }
261 }  // namespace OHOS