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