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 }