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