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