1 /*
2 * Copyright (c) 2020-2021 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 "hi_fsm.h"
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include "securec.h"
21 #include <unistd.h>
22 #include <cstring>
23 #include <pthread.h>
24 #include "fsm_common.h"
25 #include "fsm_state.h"
26 #include "hi_state_machine.h"
27 #include "fsm_oberver.h"
28 #include "media_log.h"
29
30 using OHOS::HiStateMachine;
31 using OHOS::FsmState;
32 using OHOS::HiState;
33 using OHOS::FsmOberver;
34
35 struct FsmInstanceCtx {
36 HiStateMachine *stateMachine;
37 pthread_mutex_t instanceLock;
38 std::list<FsmState *> fsmStateList;
39 FsmOberver *fsmOberver;
40 };
41
42 struct FsmContext {
43 pthread_mutex_t listLock;
44 std::list<FsmInstanceCtx *> fsmInstanceList;
45 };
46
47 static FsmContext g_fsmContext = {
48 PTHREAD_MUTEX_INITIALIZER,
49 };
50
FsmCheckInstanceExist(FsmInstanceCtx & fsmInstance)51 static bool FsmCheckInstanceExist(FsmInstanceCtx &fsmInstance)
52 {
53 FSM_LOCK(g_fsmContext.listLock);
54 std::list<FsmInstanceCtx *>::iterator msgIter = g_fsmContext.fsmInstanceList.begin();
55
56 for (; msgIter != g_fsmContext.fsmInstanceList.end(); msgIter++) {
57 if (&fsmInstance == *msgIter) {
58 FSM_UNLOCK(g_fsmContext.listLock);
59 return true;
60 }
61 }
62 FSM_UNLOCK(g_fsmContext.listLock);
63 return false;
64 }
65
FsmAddInstance(FsmInstanceCtx & fsmInstance)66 static void FsmAddInstance(FsmInstanceCtx &fsmInstance)
67 {
68 FSM_LOCK(g_fsmContext.listLock);
69
70 g_fsmContext.fsmInstanceList.push_back(&fsmInstance);
71
72 FSM_UNLOCK(g_fsmContext.listLock);
73 }
74
FsmDelInstance(FsmInstanceCtx & fsmInstance)75 static void FsmDelInstance(FsmInstanceCtx &fsmInstance)
76 {
77 FSM_LOCK(g_fsmContext.listLock);
78
79 std::list<FsmInstanceCtx *>::iterator msgIter = g_fsmContext.fsmInstanceList.begin();
80
81 for (; msgIter != g_fsmContext.fsmInstanceList.end(); msgIter++) {
82 if (&fsmInstance == *msgIter) {
83 g_fsmContext.fsmInstanceList.erase(msgIter);
84 break;
85 }
86 }
87 FSM_UNLOCK(g_fsmContext.listLock);
88 }
89
FsmFindState(FsmInstanceCtx & fsmInstance,const HiFsmState & state)90 static FsmState *FsmFindState(FsmInstanceCtx &fsmInstance, const HiFsmState &state)
91 {
92 std::list<FsmState *>::iterator msgIter = fsmInstance.fsmStateList.begin();
93
94 for (; msgIter != fsmInstance.fsmStateList.end(); msgIter++) {
95 FsmState *fsmState = *msgIter;
96 std::string stateName(state.stateName);
97 if (stateName == fsmState->Name()) {
98 return fsmState;
99 }
100 }
101
102 return nullptr;
103 }
104
HI_FSM_Create(void ** stateMachine,uint32_t maxQueueSize,uint32_t msgPayloadLen,const char * fsmName)105 int32_t HI_FSM_Create(void **stateMachine, uint32_t maxQueueSize, uint32_t msgPayloadLen, const char *fsmName)
106 {
107 FSM_RETURN_IF_NULL(fsmName);
108 FSM_RETURN_IF_NULL(stateMachine);
109 auto fsmInstance = new (std::nothrow) FsmInstanceCtx();
110 if (fsmInstance == nullptr) {
111 MEDIA_ERR_LOG("malloc FsmInstanceCtx failed");
112 return HI_FAILURE;
113 }
114 fsmInstance->stateMachine = nullptr;
115
116 fsmInstance->stateMachine = new (std::nothrow) HiStateMachine();
117 if (fsmInstance->stateMachine == nullptr) {
118 MEDIA_ERR_LOG("create HiStateMachine error !");
119 delete fsmInstance;
120 fsmInstance = nullptr;
121 return HI_FAILURE;
122 }
123 if (fsmInstance->stateMachine->Init(maxQueueSize, msgPayloadLen, fsmName) != HI_SUCCESS) {
124 MEDIA_ERR_LOG("HiStateMachine init error !");
125 delete fsmInstance->stateMachine;
126 fsmInstance->stateMachine = nullptr;
127 delete fsmInstance;
128 fsmInstance = nullptr;
129 return HI_FAILURE;
130 }
131
132 fsmInstance->fsmStateList.clear();
133
134 fsmInstance->fsmOberver = nullptr;
135
136 (void)pthread_mutex_init(&fsmInstance->instanceLock, nullptr);
137
138 FsmAddInstance(*fsmInstance);
139
140 *stateMachine = static_cast<void *>(fsmInstance);
141 return HI_SUCCESS;
142 }
143
HI_FSM_Destroy(void * stateMachine)144 int32_t HI_FSM_Destroy(void *stateMachine)
145 {
146 FSM_RETURN_IF_NULL(stateMachine);
147 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
148 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
149 int32_t ret = HI_SUCCESS;
150
151 if (fsmInstance->stateMachine != nullptr) {
152 ret = fsmInstance->stateMachine->Stop();
153 if (ret != HI_SUCCESS) {
154 MEDIA_ERR_LOG("stateMachine stop failed");
155 }
156 delete fsmInstance->stateMachine;
157 fsmInstance->stateMachine = nullptr;
158 }
159
160 if (fsmInstance->fsmOberver != nullptr) {
161 delete fsmInstance->fsmOberver;
162 fsmInstance->fsmOberver = nullptr;
163 }
164
165 std::list<FsmState *>::iterator msgIter = fsmInstance->fsmStateList.begin();
166 while (msgIter != fsmInstance->fsmStateList.end()) {
167 FsmState *fsmState = *msgIter;
168 delete fsmState;
169 fsmState = nullptr;
170 msgIter = fsmInstance->fsmStateList.erase(msgIter);
171 }
172
173 (void)pthread_mutex_destroy(&fsmInstance->instanceLock);
174
175 FsmDelInstance(*fsmInstance);
176
177 delete fsmInstance;
178
179 return HI_SUCCESS;
180 }
181
HI_FSM_AddState(void * stateMachine,const HiFsmState * state)182 int32_t HI_FSM_AddState(void *stateMachine, const HiFsmState *state)
183 {
184 FSM_RETURN_IF_NULL(stateMachine);
185 FSM_RETURN_IF_NULL(state);
186 FSM_RETURN_IF_NULL(state->handlerCallback);
187 FSM_RETURN_IF_NULL(state->enterCallback);
188 FSM_RETURN_IF_NULL(state->exitCallback);
189 FSM_RETURN_IF_NULL(state->priv);
190 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
191 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
192 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
193 std::string stateName(state->stateName);
194
195 FSM_LOCK(fsmInstance->instanceLock);
196 FsmState *fsmState = FsmFindState(*fsmInstance, *state);
197 if (fsmState != nullptr) {
198 MEDIA_ERR_LOG("state: %s already exist", state->stateName);
199 FSM_UNLOCK(fsmInstance->instanceLock);
200 return HI_FAILURE;
201 }
202
203 fsmState = new (std::nothrow) FsmState(state->handlerCallback, state->enterCallback, state->exitCallback,
204 state->priv, stateName);
205 if (fsmState == nullptr) {
206 MEDIA_ERR_LOG("state new failed");
207 FSM_UNLOCK(fsmInstance->instanceLock);
208 return HI_FAILURE;
209 }
210
211 fsmInstance->fsmStateList.push_back(fsmState);
212 int32_t ret = fsmInstance->stateMachine->AddState(*fsmState);
213 FSM_UNLOCK(fsmInstance->instanceLock);
214 return ret;
215 }
216
HI_FSM_RegMsgCallback(void * stateMachine,HI_FSM_EventCallback eventCallback,void * priv)217 int32_t HI_FSM_RegMsgCallback(void *stateMachine,
218 HI_FSM_EventCallback eventCallback, void *priv)
219 {
220 FSM_RETURN_IF_NULL(stateMachine);
221 FSM_RETURN_IF_NULL(eventCallback);
222 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
223 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
224 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
225 FSM_LOCK(fsmInstance->instanceLock);
226
227 FsmOberver *observer = new (std::nothrow) FsmOberver(eventCallback, priv);
228 if (observer == nullptr) {
229 MEDIA_ERR_LOG("FsmOberver new failed");
230 FSM_UNLOCK(fsmInstance->instanceLock);
231 return HI_FAILURE;
232 }
233 int32_t ret = fsmInstance->stateMachine->RegisterObserver(*observer);
234 if (ret != HI_SUCCESS) {
235 MEDIA_ERR_LOG("stateMachine registerObserver failed");
236 delete observer;
237 FSM_UNLOCK(fsmInstance->instanceLock);
238 return HI_FAILURE;
239 }
240
241 if (fsmInstance->fsmOberver != nullptr) {
242 delete fsmInstance->fsmOberver;
243 }
244
245 fsmInstance->fsmOberver = observer;
246
247 FSM_UNLOCK(fsmInstance->instanceLock);
248
249 return HI_SUCCESS;
250 }
251
HI_FSM_AddTransition(void * stateMachine,const HiFsmStateTrans * stateTrans)252 int32_t HI_FSM_AddTransition(void *stateMachine, const HiFsmStateTrans *stateTrans)
253 {
254 FSM_RETURN_IF_NULL(stateMachine);
255 FSM_RETURN_IF_NULL(stateTrans);
256 FSM_RETURN_IF_NULL(stateTrans->srcState);
257 FSM_RETURN_IF_NULL(stateTrans->destState);
258 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
259 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
260 FSM_LOCK(fsmInstance->instanceLock);
261
262 FsmState *fsmSrcState = FsmFindState(*fsmInstance, *(stateTrans->srcState));
263 if (fsmSrcState == nullptr) {
264 MEDIA_ERR_LOG("could not find state: %s",
265 stateTrans->srcState->stateName);
266 FSM_UNLOCK(fsmInstance->instanceLock);
267 return HI_FAILURE;
268 }
269
270 FsmState *fsmDstState = FsmFindState(*fsmInstance, *(stateTrans->destState));
271 if (fsmDstState == nullptr) {
272 MEDIA_ERR_LOG("could not find state: %s ",
273 stateTrans->destState->stateName);
274 FSM_UNLOCK(fsmInstance->instanceLock);
275 return HI_FAILURE;
276 }
277
278 fsmSrcState->AddTransition(stateTrans->msgType, *fsmDstState);
279 FSM_UNLOCK(fsmInstance->instanceLock);
280
281 return HI_SUCCESS;
282 }
283
HI_FSM_SetInitState(void * stateMachine,const HiFsmState * state)284 int32_t HI_FSM_SetInitState(void *stateMachine, const HiFsmState *state)
285 {
286 FSM_RETURN_IF_NULL(stateMachine);
287 FSM_RETURN_IF_NULL(state);
288
289 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
290 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
291 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
292 FSM_LOCK(fsmInstance->instanceLock);
293 FsmState *fsmState = FsmFindState(*fsmInstance, *state);
294 if (fsmState == nullptr) {
295 MEDIA_ERR_LOG("could not find state: %s ", state->stateName);
296 FSM_UNLOCK(fsmInstance->instanceLock);
297 return HI_FAILURE;
298 }
299 int32_t ret = fsmInstance->stateMachine->SetInitialState(*fsmState);
300 FSM_UNLOCK(fsmInstance->instanceLock);
301
302 return ret;
303 }
304
HI_FSM_Start(void * stateMachine)305 int32_t HI_FSM_Start(void *stateMachine)
306 {
307 FSM_RETURN_IF_NULL(stateMachine);
308 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
309 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
310 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
311
312 FSM_LOCK(fsmInstance->instanceLock);
313 int32_t ret = fsmInstance->stateMachine->Start();
314 FSM_UNLOCK(fsmInstance->instanceLock);
315
316 return ret;
317 }
318
HI_FSM_Stop(void * stateMachine)319 int32_t HI_FSM_Stop(void *stateMachine)
320 {
321 FSM_RETURN_IF_NULL(stateMachine);
322 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
323 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
324 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
325 FSM_LOCK(fsmInstance->instanceLock);
326 int32_t ret = fsmInstance->stateMachine->Stop();
327 FSM_UNLOCK(fsmInstance->instanceLock);
328
329 return ret;
330 }
331
HI_FSM_GetCurrentState(void * stateMachine,char stateName[MAX_STATE_NAME_LEN])332 int32_t HI_FSM_GetCurrentState(void *stateMachine, char stateName[MAX_STATE_NAME_LEN])
333 {
334 FSM_RETURN_IF_NULL(stateMachine);
335 FSM_RETURN_IF_NULL(stateName);
336 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
337 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
338 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
339 FSM_LOCK(fsmInstance->instanceLock);
340 const HiState *state = fsmInstance->stateMachine->CurrentState();
341 if (state == nullptr) {
342 MEDIA_ERR_LOG("current state is NULL");
343 FSM_UNLOCK(fsmInstance->instanceLock);
344 return HI_FAILURE;
345 }
346
347 if (strncpy_s(stateName, MAX_STATE_NAME_LEN, state->Name().c_str(), MAX_STATE_NAME_LEN - 1) != EOK) {
348 MEDIA_ERR_LOG("strncpy failed");
349 FSM_UNLOCK(fsmInstance->instanceLock);
350 return HI_FAILURE;
351 }
352
353 FSM_UNLOCK(fsmInstance->instanceLock);
354
355 return HI_SUCCESS;
356 }
357
HI_FSM_SendAsync(void * stateMachine,const MsgInfo * msg,uint64_t delayUs)358 int32_t HI_FSM_SendAsync(void *stateMachine, const MsgInfo *msg, uint64_t delayUs)
359 {
360 FSM_RETURN_IF_NULL(stateMachine);
361 FSM_RETURN_IF_NULL(msg);
362 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
363 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
364 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
365 return fsmInstance->stateMachine->Post(*msg, delayUs);
366 }
367
HI_FSM_SendSync(void * stateMachine,const MsgInfo * msg,const MsgInfo * replyMsg)368 int32_t HI_FSM_SendSync(void *stateMachine, const MsgInfo *msg, const MsgInfo *replyMsg)
369 {
370 FSM_RETURN_IF_NULL(stateMachine);
371 FSM_RETURN_IF_NULL(msg);
372 FSM_RETURN_IF_NULL(replyMsg);
373 FsmInstanceCtx *fsmInstance = static_cast<FsmInstanceCtx *>(stateMachine);
374 FSM_RETURN_IF_HANDLE_NOT_EXIST(FsmCheckInstanceExist, *fsmInstance);
375 (void)(replyMsg);
376 FSM_RETURN_IF_NULL(fsmInstance->stateMachine);
377 return fsmInstance->stateMachine->Send(*msg);
378 }
379