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