1 /* 2 * Copyright (C) 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 #ifndef STATE_MACHINE_H 17 #define STATE_MACHINE_H 18 19 #include <memory> 20 #include <mutex> 21 #include <utility> 22 #include <vector> 23 24 #include "event_handler.h" 25 #include "inner_event.h" 26 27 #include "telephony_log_wrapper.h" 28 29 #include "cellular_data_event_code.h" 30 31 namespace OHOS { 32 namespace Telephony { 33 class State : public RefBase { 34 #define PROCESSED true 35 #define NOT_PROCESSED false 36 public: State(std::string && name)37 explicit State(std::string &&name) : name_(std::move(name)) {} 38 virtual ~State() = default; 39 virtual void StateBegin() = 0; 40 virtual void StateEnd() = 0; 41 virtual bool StateProcess(const AppExecFwk::InnerEvent::Pointer &event) = 0; 42 SetParentState(sptr<State> & parent)43 void SetParentState(sptr<State> &parent) 44 { 45 parent_ = parent; 46 } 47 GetStateMachineName()48 std::string GetStateMachineName() const 49 { 50 return name_; 51 } 52 53 protected: 54 friend class StateMachineEventHandler; 55 std::string name_; 56 sptr<State> parent_; 57 bool isActive_ = false; 58 }; 59 60 class StateMachineEventHandler : public AppExecFwk::EventHandler { 61 public: StateMachineEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner)62 explicit StateMachineEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner) 63 : EventHandler(runner) 64 {} 65 ~StateMachineEventHandler() = default; 66 SetOriginalState(sptr<State> & originalState)67 virtual void SetOriginalState(sptr<State> &originalState) 68 { 69 originalState_ = originalState; 70 } 71 TransitionTo(sptr<State> & destState)72 virtual void TransitionTo(sptr<State> &destState) 73 { 74 TELEPHONY_LOGI("State machine transition to %{public}s", destState->name_.c_str()); 75 destState_ = destState; 76 } 77 Quit()78 virtual void Quit() 79 { 80 sptr<State> tmpState = curState_; 81 while (tmpState != nullptr && tmpState->isActive_) { 82 tmpState->StateEnd(); 83 tmpState = tmpState->parent_; 84 isQuit_ = true; 85 } 86 } 87 88 // Only two-layer StateMachines are supported ProcessTransitions(const AppExecFwk::InnerEvent::Pointer & event)89 virtual void ProcessTransitions(const AppExecFwk::InnerEvent::Pointer &event) 90 { 91 if (curState_ != destState_) { 92 TELEPHONY_LOGI("Begin process transitions"); 93 if (curState_ != nullptr) { 94 sptr<State> tmpState = curState_->parent_; 95 while (tmpState != nullptr) { 96 tmpState->StateEnd(); 97 tmpState = tmpState->parent_; 98 } 99 curState_->StateEnd(); 100 } 101 if (destState_ != nullptr) { 102 sptr<State> tmpState = destState_->parent_; 103 while (tmpState != nullptr) { 104 tmpState->StateBegin(); 105 tmpState = tmpState->parent_; 106 } 107 destState_->StateBegin(); 108 } 109 curState_ = destState_; 110 SendDeferredEvent(); 111 } 112 } 113 DeferEvent(AppExecFwk::InnerEvent::Pointer && event)114 void DeferEvent(AppExecFwk::InnerEvent::Pointer &&event) 115 { 116 std::lock_guard<std::mutex> guard(mtx_); 117 deferEvents_.push_back(std::move(event)); 118 } 119 ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)120 virtual void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) 121 { 122 if (event == nullptr || isQuit_) { 123 TELEPHONY_LOGE("The event parameter is incorrect"); 124 return; 125 } 126 if (event->GetInnerEventId() == CellularDataEventCode::MSG_STATE_MACHINE_QUIT) { 127 TELEPHONY_LOGI("State machine exit"); 128 Quit(); 129 return; 130 } 131 if (event->GetInnerEventId() == CellularDataEventCode::MSG_STATE_MACHINE_INIT) { 132 destState_ = originalState_; 133 InitCmdEnter(originalState_); 134 } 135 ProcessMsg(event); 136 ProcessTransitions(event); 137 } 138 ProcessMsg(const AppExecFwk::InnerEvent::Pointer & event)139 virtual void ProcessMsg(const AppExecFwk::InnerEvent::Pointer &event) 140 { 141 sptr<State> tmpState = curState_; 142 TELEPHONY_LOGI("The event id: %{public}u", event->GetInnerEventId()); 143 while (tmpState != nullptr && !tmpState->StateProcess(event)) { 144 tmpState = tmpState->parent_; 145 } 146 } 147 148 private: InitCmdEnter(const sptr<State> & state)149 void InitCmdEnter(const sptr<State> &state) 150 { 151 if (state == nullptr) { 152 TELEPHONY_LOGE("registerState_ is null"); 153 return; 154 } 155 if (state->parent_ != nullptr) { 156 InitCmdEnter(state->parent_); 157 } 158 TELEPHONY_LOGI("Initialize entry %{public}s", state->name_.c_str()); 159 state->StateBegin(); 160 curState_ = state; 161 } 162 SendDeferredEvent()163 void SendDeferredEvent() 164 { 165 std::lock_guard<std::mutex> guard(mtx_); 166 if (deferEvents_.empty()) { 167 return; 168 } 169 for (size_t i = 0; i < deferEvents_.size(); ++i) { 170 AppExecFwk::InnerEvent::Pointer event = std::move(deferEvents_[i]); 171 SendImmediateEvent(event); 172 } 173 deferEvents_.clear(); 174 } 175 176 private: 177 sptr<State> originalState_; 178 sptr<State> destState_; 179 sptr<State> curState_; 180 std::vector<AppExecFwk::InnerEvent::Pointer> deferEvents_; 181 std::mutex mtx_; 182 bool isQuit_ = false; 183 }; 184 185 class StateMachine { 186 public: StateMachine(const std::shared_ptr<AppExecFwk::EventRunner> & runner)187 explicit StateMachine(const std::shared_ptr<AppExecFwk::EventRunner> &runner) 188 { 189 stateMachineEventHandler_ = std::make_shared<StateMachineEventHandler>(runner); 190 if (stateMachineEventHandler_ == nullptr) { 191 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 192 return; 193 } 194 } 195 ~StateMachine()196 virtual ~StateMachine() {} 197 Quit()198 void Quit() 199 { 200 AppExecFwk::InnerEvent::Pointer event = 201 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STATE_MACHINE_QUIT); 202 if (stateMachineEventHandler_ == nullptr) { 203 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 204 return; 205 } 206 stateMachineEventHandler_->SendImmediateEvent(event); 207 } 208 Start()209 void Start() 210 { 211 if (stateMachineEventHandler_ == nullptr) { 212 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 213 return; 214 } 215 AppExecFwk::InnerEvent::Pointer event = 216 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STATE_MACHINE_INIT); 217 stateMachineEventHandler_->SendImmediateEvent(event); 218 } 219 SetOriginalState(sptr<State> & originalState)220 void SetOriginalState(sptr<State> &originalState) 221 { 222 if (originalState == nullptr) { 223 TELEPHONY_LOGE("originalState is null"); 224 return; 225 } 226 if (stateMachineEventHandler_ == nullptr) { 227 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 228 return; 229 } 230 stateMachineEventHandler_->SetOriginalState(originalState); 231 } 232 TransitionTo(sptr<State> & destState)233 void TransitionTo(sptr<State> &destState) 234 { 235 if (destState == nullptr) { 236 TELEPHONY_LOGE("destState is null"); 237 return; 238 } 239 if (stateMachineEventHandler_ == nullptr) { 240 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 241 return; 242 } 243 stateMachineEventHandler_->TransitionTo(destState); 244 } 245 DeferEvent(const AppExecFwk::InnerEvent::Pointer && event)246 void DeferEvent(const AppExecFwk::InnerEvent::Pointer &&event) 247 { 248 if (stateMachineEventHandler_ == nullptr) { 249 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 250 return; 251 } 252 stateMachineEventHandler_->DeferEvent(std::move(const_cast<AppExecFwk::InnerEvent::Pointer &>(event))); 253 } 254 SendEvent(AppExecFwk::InnerEvent::Pointer & event)255 void SendEvent(AppExecFwk::InnerEvent::Pointer &event) 256 { 257 if (stateMachineEventHandler_ == nullptr) { 258 TELEPHONY_LOGE("stateMachineEventHandler_ is null"); 259 return; 260 } 261 TELEPHONY_LOGI("State machine send event id %{public}u ", event->GetInnerEventId()); 262 stateMachineEventHandler_->SendEvent(event); 263 } 264 265 protected: 266 std::shared_ptr<StateMachineEventHandler> stateMachineEventHandler_; 267 }; 268 } // namespace Telephony 269 } // namespace OHOS 270 #endif // STATE_MACHINE_H 271