1 /*
2 * Copyright (c) 2024 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 #include "state_manager.h"
16 #include "intell_voice_log.h"
17
18 #undef LOG_TAG
19 #define LOG_TAG "StateManger"
20
21 namespace OHOS {
22 namespace IntellVoiceUtils {
23 StateActions g_nullAction;
24 const State NULLSTATE(-1);
25
Handle(const StateMsg & msg,State & nextState)26 int StateActions::Handle(const StateMsg &msg, State &nextState)
27 {
28 if (actions.find(msg.msgId) == actions.end()) {
29 return NO_PROCESS_RET;
30 }
31 return (actions[msg.msgId])(msg, nextState);
32 }
33
ModuleStates(const State & defaultState,const std::string & name,const std::string & threadName)34 ModuleStates::ModuleStates(const State &defaultState, const std::string &name, const std::string &threadName)
35 : isInitSucc_(true), name_(name)
36 {
37 states_[defaultState] = nullptr;
38 currState_ = states_.begin();
39 Start(threadName);
40 }
41
~ModuleStates()42 ModuleStates::~ModuleStates()
43 {
44 for (auto each : states_) {
45 if (each.second != nullptr) {
46 delete each.second;
47 }
48 }
49
50 states_.clear();
51 }
52
ForState(const State & s)53 StateActions& ModuleStates::ForState(const State &s)
54 {
55 auto it = states_.find(s);
56 if (it == states_.end() || it->second == nullptr) {
57 StateActions* action = new (std::nothrow) StateActions();
58 if (action == nullptr) {
59 currState_ = states_.end();
60 isInitSucc_ = false;
61 return g_nullAction;
62 }
63 states_[s] = action;
64 }
65
66 return *(states_[s]);
67 }
68
ForState(int simpleState)69 StateActions& ModuleStates::ForState(int simpleState)
70 {
71 return ForState(State(simpleState));
72 }
73
FromState(int simpleStateStart,int simpleStateEnd)74 StateGroup& ModuleStates::FromState(int simpleStateStart, int simpleStateEnd)
75 {
76 for (int i = simpleStateStart; i <= simpleStateEnd; i++) {
77 StateActions& action = ForState(i);
78 AddAction(&action);
79 }
80
81 return *this;
82 }
83
ToState(std::map<State,StateActions * >::iterator & nextIt)84 void ModuleStates::ToState(std::map<State, StateActions*>::iterator &nextIt)
85 {
86 // exit current state
87 StateActions* action = currState_->second;
88 if (action->timerId != INVALID_ID) {
89 KillTimer(action->timerId);
90 }
91
92 INTELL_VOICE_LOG_INFO("%{public}s state from %{public}s to %{public}s", name_.c_str(),
93 (currState_->first).ToStr().c_str(), (nextIt->first).ToStr().c_str());
94
95 currState_ = nextIt;
96
97 // enter next state
98 action = nextIt->second;
99 if (action->cfg.delayUs != 0) {
100 action->timerId = SetTimer(action->cfg.type, action->cfg.delayUs, action->cfg.cookie, this);
101 }
102 }
103
OnTimerEvent(TimerEvent & info)104 void ModuleStates::OnTimerEvent(TimerEvent &info)
105 {
106 StateMsg msg(info.type, &info, sizeof(info));
107 HandleMsg(msg);
108 }
109
HandleMsg(const StateMsg & msg)110 int ModuleStates::HandleMsg(const StateMsg &msg)
111 {
112 std::unique_lock<std::mutex> lock(msgHandleMutex_);
113
114 if ((currState_ == states_.end()) || (currState_->second == nullptr)) {
115 INTELL_VOICE_LOG_ERROR("%{public}s invalid current state", name_.c_str());
116 return -1;
117 }
118
119 State nextState = currState_->first;
120 int ret = currState_->second->Handle(msg, nextState);
121 if (ret != 0) {
122 if (ret != NO_PROCESS_RET) {
123 INTELL_VOICE_LOG_ERROR("%{public}s handle msg %{public}d fail", name_.c_str(), msg.msgId);
124 } else {
125 INTELL_VOICE_LOG_INFO("%{public}s state %{public}d no need to handle msg %{public}d", name_.c_str(),
126 currState_->first.state, msg.msgId);
127 }
128 return ret;
129 }
130
131 if (currState_->first == nextState) {
132 return 0;
133 }
134
135 auto nextIt = states_.find(nextState);
136 if (nextIt == states_.end()) {
137 INTELL_VOICE_LOG_ERROR("%{public}s invalid next state %{public}s", name_.c_str(), nextState.ToStr().c_str());
138 return 0;
139 }
140
141 ToState(nextIt);
142
143 return 0;
144 }
145
ResetTimerDelay()146 void ModuleStates::ResetTimerDelay()
147 {
148 if (currState_ == states_.end()) {
149 INTELL_VOICE_LOG_ERROR("invalid current state");
150 return;
151 }
152 StateActions *action = currState_->second;
153 if (action == nullptr) {
154 INTELL_VOICE_LOG_ERROR("action of state:%{public}d is nullptr", currState_->first.state);
155 return;
156 }
157 if ((action->timerId == INVALID_ID) || (action->cfg.delayUs == 0)) {
158 INTELL_VOICE_LOG_INFO("no valid timer to reset");
159 return;
160 }
161 action->timerId = ResetTimer(action->timerId, action->cfg.type, action->cfg.delayUs, action->cfg.cookie, this);
162 }
163
CurrState() const164 State ModuleStates::CurrState() const
165 {
166 if (currState_ == states_.end()) {
167 return NULLSTATE;
168 }
169
170 return currState_->first;
171 }
172
IsStatesInitSucc() const173 bool ModuleStates::IsStatesInitSucc() const
174 {
175 return isInitSucc_;
176 }
177 }
178 }