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_state_machine.h"
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <sys/prctl.h>
21 #include <unistd.h>
22 #include "fsm_common.h"
23 #include "media_log.h"
24
25 namespace OHOS {
HiStateMachine()26 HiStateMachine::HiStateMachine()
27 {
28 m_looper = nullptr;
29 m_currentState = nullptr;
30 m_observer = nullptr;
31 m_running = false;
32 m_allStates.clear();
33 }
34
Deinit()35 int32_t HiStateMachine::Deinit()
36 {
37 int32_t ret = Stop();
38 if (ret != HI_SUCCESS) {
39 MEDIA_ERR_LOG("Stop err ");
40 }
41 m_allStates.clear();
42 if (m_looper != nullptr) {
43 ret = m_looper->Deinit();
44 if (ret != HI_SUCCESS) {
45 MEDIA_ERR_LOG("m_looper->Deinit err !");
46 }
47 delete m_looper;
48 m_looper = nullptr;
49 }
50 return HI_SUCCESS;
51 }
52
Init(uint32_t maxQueueSize,uint32_t maxMsgPayloadSize,const std::string smName)53 int32_t HiStateMachine::Init(uint32_t maxQueueSize, uint32_t maxMsgPayloadSize, const std::string smName)
54 {
55 if (m_looper != nullptr) {
56 MEDIA_ERR_LOG("HiStateMachine::Init is init already !");
57 return HI_SUCCESS;
58 }
59 m_running = false;
60 m_looper = new (std::nothrow) MessageLooper(smName);
61 if (m_looper == nullptr) {
62 MEDIA_ERR_LOG("fail to create MessageLooper !");
63 return HI_FAILURE;
64 }
65 if (m_looper->Init(maxQueueSize, maxMsgPayloadSize, smName) != HI_SUCCESS) {
66 MEDIA_ERR_LOG("MessageLooper init error !");
67 goto LOOPER_DEL;
68 }
69 if (m_looper->RegisterHandler(*this) != HI_SUCCESS) {
70 MEDIA_ERR_LOG("fail to RegisterHandler !");
71 goto LOOPER_DEINIT;
72 }
73 return HI_SUCCESS;
74
75 LOOPER_DEINIT:
76 (void)m_looper->Deinit();
77 LOOPER_DEL:
78 delete m_looper;
79 m_looper = nullptr;
80 return HI_FAILURE;
81 }
82
~HiStateMachine()83 HiStateMachine::~HiStateMachine()
84 {
85 (void)Deinit();
86 }
87
AddState(HiState & state)88 int32_t HiStateMachine::AddState(HiState &state)
89 {
90 if (m_running) {
91 MEDIA_ERR_LOG("can't addState when running");
92 return HI_FAILURE;
93 }
94 if (!StateExist(state)) {
95 m_allStates.push_back(&state);
96 } else {
97 MEDIA_ERR_LOG("state already exist");
98 return HI_FAILURE;
99 }
100 return HI_SUCCESS;
101 }
102
RegisterObserver(HiStateMachineObserver & observer)103 int32_t HiStateMachine::RegisterObserver(HiStateMachineObserver &observer)
104 {
105 if (m_running) {
106 MEDIA_ERR_LOG("can't registerObserver when running");
107 return HI_FAILURE;
108 }
109 m_observer = &observer;
110 return HI_SUCCESS;
111 }
112
SetInitialState(HiState & state)113 int32_t HiStateMachine::SetInitialState(HiState &state)
114 {
115 if (m_running) {
116 MEDIA_ERR_LOG("can't set initstate when running");
117 return HI_FAILURE;
118 }
119
120 if (StateExist(state)) {
121 m_currentState = &state;
122 } else {
123 MEDIA_ERR_LOG("init state not exist:%s", state.Name().c_str());
124 return HI_FAILURE;
125 }
126 return HI_SUCCESS;
127 }
128
CurrentState()129 const HiState *HiStateMachine::CurrentState()
130 {
131 return m_currentState;
132 }
133
Transition(HiState & nextState)134 void HiStateMachine::Transition(HiState &nextState)
135 {
136 if (m_currentState == nullptr) {
137 MEDIA_ERR_LOG("m_currentState == nullptr");
138 return;
139 }
140 if (StateExist(nextState)) {
141 m_currentState->Exit();
142 nextState.Enter();
143 m_currentState = &nextState;
144 } else {
145 MEDIA_ERR_LOG("transition state not exist:%s", nextState.Name().c_str());
146 }
147 }
148
Start()149 int32_t HiStateMachine::Start()
150 {
151 if (m_running) {
152 MEDIA_ERR_LOG("already running");
153 return HI_FAILURE;
154 }
155 if (m_currentState == nullptr) {
156 MEDIA_ERR_LOG("initstate not set");
157 return HI_FAILURE;
158 }
159 if (m_looper == nullptr) {
160 MEDIA_ERR_LOG("mlooper is nullptr !");
161 return HI_FAILURE;
162 }
163 int32_t ret = m_looper->Start();
164 if (ret != HI_SUCCESS) {
165 return HI_FAILURE;
166 }
167 m_running = true;
168 return HI_SUCCESS;
169 }
170
Stop()171 int32_t HiStateMachine::Stop()
172 {
173 int32_t ret = HI_SUCCESS;
174 if (m_running) {
175 if (m_looper == nullptr) {
176 MEDIA_ERR_LOG("mlooper is nullptr !");
177 return HI_FAILURE;
178 }
179 ret = m_looper->Stop();
180 m_running = false;
181 }
182 return ret;
183 }
184
Send(const MsgInfo & msg)185 int32_t HiStateMachine::Send(const MsgInfo &msg)
186 {
187 if (m_looper == nullptr) {
188 MEDIA_ERR_LOG("mlooper is nullptr !");
189 return HI_FAILURE;
190 }
191 return m_looper->Send(msg);
192 }
193
Send(int32_t what)194 int32_t HiStateMachine::Send(int32_t what)
195 {
196 MsgInfo msg;
197 msg.what = what;
198 msg.arg1 = 0;
199 msg.arg2 = 0;
200 msg.msgData = nullptr;
201 msg.msgDataLen = 0;
202 msg.isNeedReply = false;
203 msg.privDate = nullptr;
204 msg.msgCallback = nullptr;
205 if (m_looper == nullptr) {
206 MEDIA_ERR_LOG("mlooper is nullptr !");
207 return HI_FAILURE;
208 }
209 return m_looper->Send(msg);
210 }
211
Post(const MsgInfo & msg,uint64_t delayUs)212 int32_t HiStateMachine::Post(const MsgInfo &msg, uint64_t delayUs)
213 {
214 if (!m_running) {
215 MEDIA_ERR_LOG("post fail: FSM stoped");
216 return HI_FAILURE;
217 }
218 if (m_looper == nullptr) {
219 MEDIA_ERR_LOG("mlooper is nullptr !");
220 return HI_FAILURE;
221 }
222 return m_looper->Post(msg, delayUs);
223 }
224
Post(int32_t what,uint64_t delayUs)225 int32_t HiStateMachine::Post(int32_t what, uint64_t delayUs)
226 {
227 MsgInfo msg;
228 msg.what = what;
229 msg.arg1 = 0;
230 msg.arg2 = 0;
231 msg.msgData = nullptr;
232 msg.msgDataLen = 0;
233 msg.isNeedReply = false; // no requirment to reply by now, should check it in the future
234 msg.privDate = nullptr;
235 msg.msgCallback = nullptr;
236 if (!m_running) {
237 MEDIA_ERR_LOG("post fail: FSM stoped");
238 return HI_FAILURE;
239 }
240 if (m_looper == nullptr) {
241 MEDIA_ERR_LOG("mlooper is nullptr !");
242 return HI_FAILURE;
243 }
244 return m_looper->Post(msg, delayUs);
245 }
246
RemoveEvent(const MsgInfo & msg)247 int32_t HiStateMachine::RemoveEvent(const MsgInfo &msg)
248 {
249 if (!m_running) {
250 MEDIA_ERR_LOG("removeEvent fail: FSM stoped");
251 return HI_FAILURE;
252 }
253 if (m_looper == nullptr) {
254 MEDIA_ERR_LOG("mlooper is nullptr !");
255 return HI_FAILURE;
256 }
257 m_looper->RemoveMessage(msg);
258 return HI_SUCCESS;
259 }
260
OnMessageReceived(const MsgInfo & msg)261 int32_t HiStateMachine::OnMessageReceived(const MsgInfo &msg)
262 {
263 if (m_currentState == nullptr) {
264 MEDIA_ERR_LOG("initstate not set");
265 return HI_FAILURE;
266 }
267 int32_t ret = m_currentState->HandleMessage(msg);
268 if (ret == HI_SUCCESS) {
269 HiState *nextState = m_currentState->FindTransition(msg.what);
270 if (nextState != nullptr) {
271 Transition(*nextState);
272 }
273 }
274
275 if (m_observer != nullptr) {
276 m_observer->OnEventHandled(*this, msg.what, ret);
277 }
278 return ret;
279 }
280
StateExist(const HiState & state)281 bool HiStateMachine::StateExist(const HiState &state)
282 {
283 std::vector<HiState *>::iterator it;
284
285 for (it = m_allStates.begin(); it != m_allStates.end(); it++) {
286 if (*it == &state || (*it)->Name() == state.Name()) {
287 return true;
288 }
289 }
290 return false;
291 }
292 };
293