12d43be4eSopenharmony_ci/*
22d43be4eSopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
32d43be4eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42d43be4eSopenharmony_ci * you may not use this file except in compliance with the License.
52d43be4eSopenharmony_ci * You may obtain a copy of the License at
62d43be4eSopenharmony_ci *
72d43be4eSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82d43be4eSopenharmony_ci *
92d43be4eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102d43be4eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112d43be4eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122d43be4eSopenharmony_ci * See the License for the specific language governing permissions and
132d43be4eSopenharmony_ci * limitations under the License.
142d43be4eSopenharmony_ci */
152d43be4eSopenharmony_ci
162d43be4eSopenharmony_ci#ifndef STATE_MACHINE_H
172d43be4eSopenharmony_ci#define STATE_MACHINE_H
182d43be4eSopenharmony_ci
192d43be4eSopenharmony_ci#include <memory>
202d43be4eSopenharmony_ci#include <mutex>
212d43be4eSopenharmony_ci#include <utility>
222d43be4eSopenharmony_ci#include <vector>
232d43be4eSopenharmony_ci
242d43be4eSopenharmony_ci#include "cellular_data_event_code.h"
252d43be4eSopenharmony_ci#include "inner_event.h"
262d43be4eSopenharmony_ci#include "tel_event_handler.h"
272d43be4eSopenharmony_ci#include "telephony_log_wrapper.h"
282d43be4eSopenharmony_ci
292d43be4eSopenharmony_cinamespace OHOS {
302d43be4eSopenharmony_cinamespace Telephony {
312d43be4eSopenharmony_ciclass State : public RefBase {
322d43be4eSopenharmony_ci#define PROCESSED true
332d43be4eSopenharmony_ci#define NOT_PROCESSED false
342d43be4eSopenharmony_cipublic:
352d43be4eSopenharmony_ci    explicit State(std::string &&name) : name_(std::move(name)) {}
362d43be4eSopenharmony_ci    virtual ~State() = default;
372d43be4eSopenharmony_ci    virtual void StateBegin() = 0;
382d43be4eSopenharmony_ci    virtual void StateEnd() = 0;
392d43be4eSopenharmony_ci    virtual bool StateProcess(const AppExecFwk::InnerEvent::Pointer &event) = 0;
402d43be4eSopenharmony_ci
412d43be4eSopenharmony_ci    void SetParentState(sptr<State> &parent)
422d43be4eSopenharmony_ci    {
432d43be4eSopenharmony_ci        parent_ = parent;
442d43be4eSopenharmony_ci    }
452d43be4eSopenharmony_ci
462d43be4eSopenharmony_ci    std::string GetStateMachineName() const
472d43be4eSopenharmony_ci    {
482d43be4eSopenharmony_ci        return name_;
492d43be4eSopenharmony_ci    }
502d43be4eSopenharmony_ci
512d43be4eSopenharmony_ciprotected:
522d43be4eSopenharmony_ci    friend class StateMachineEventHandler;
532d43be4eSopenharmony_ci    std::string name_;
542d43be4eSopenharmony_ci    sptr<State> parent_;
552d43be4eSopenharmony_ci    bool isActive_ = false;
562d43be4eSopenharmony_ci};
572d43be4eSopenharmony_ci
582d43be4eSopenharmony_ciclass StateMachineEventHandler : public TelEventHandler {
592d43be4eSopenharmony_cipublic:
602d43be4eSopenharmony_ci    explicit StateMachineEventHandler(const std::string &name) : TelEventHandler(name) {}
612d43be4eSopenharmony_ci    ~StateMachineEventHandler() = default;
622d43be4eSopenharmony_ci
632d43be4eSopenharmony_ci    virtual void SetOriginalState(sptr<State> &originalState)
642d43be4eSopenharmony_ci    {
652d43be4eSopenharmony_ci        originalState_ = originalState;
662d43be4eSopenharmony_ci    }
672d43be4eSopenharmony_ci
682d43be4eSopenharmony_ci    virtual void TransitionTo(sptr<State> &destState)
692d43be4eSopenharmony_ci    {
702d43be4eSopenharmony_ci        TELEPHONY_LOGI("State machine transition to %{public}s", destState->name_.c_str());
712d43be4eSopenharmony_ci        destState_ = destState;
722d43be4eSopenharmony_ci    }
732d43be4eSopenharmony_ci
742d43be4eSopenharmony_ci    virtual void Quit()
752d43be4eSopenharmony_ci    {
762d43be4eSopenharmony_ci        sptr<State> tmpState = curState_;
772d43be4eSopenharmony_ci        while (tmpState != nullptr && tmpState->isActive_) {
782d43be4eSopenharmony_ci            tmpState->StateEnd();
792d43be4eSopenharmony_ci            tmpState = tmpState->parent_;
802d43be4eSopenharmony_ci            isQuit_ = true;
812d43be4eSopenharmony_ci        }
822d43be4eSopenharmony_ci    }
832d43be4eSopenharmony_ci
842d43be4eSopenharmony_ci    // Only two-layer StateMachines are supported
852d43be4eSopenharmony_ci    virtual void ProcessTransitions(const AppExecFwk::InnerEvent::Pointer &event)
862d43be4eSopenharmony_ci    {
872d43be4eSopenharmony_ci        if (curState_ != destState_) {
882d43be4eSopenharmony_ci            TELEPHONY_LOGD("Begin process transitions");
892d43be4eSopenharmony_ci            if (curState_ != nullptr) {
902d43be4eSopenharmony_ci                sptr<State> tmpState = curState_->parent_;
912d43be4eSopenharmony_ci                while (tmpState != nullptr) {
922d43be4eSopenharmony_ci                    tmpState->StateEnd();
932d43be4eSopenharmony_ci                    tmpState = tmpState->parent_;
942d43be4eSopenharmony_ci                }
952d43be4eSopenharmony_ci                curState_->StateEnd();
962d43be4eSopenharmony_ci            }
972d43be4eSopenharmony_ci            if (destState_ != nullptr) {
982d43be4eSopenharmony_ci                sptr<State> tmpState = destState_->parent_;
992d43be4eSopenharmony_ci                while (tmpState != nullptr) {
1002d43be4eSopenharmony_ci                    tmpState->StateBegin();
1012d43be4eSopenharmony_ci                    tmpState = tmpState->parent_;
1022d43be4eSopenharmony_ci                }
1032d43be4eSopenharmony_ci                destState_->StateBegin();
1042d43be4eSopenharmony_ci            }
1052d43be4eSopenharmony_ci            curState_ = destState_;
1062d43be4eSopenharmony_ci            SendDeferredEvent();
1072d43be4eSopenharmony_ci        }
1082d43be4eSopenharmony_ci    }
1092d43be4eSopenharmony_ci
1102d43be4eSopenharmony_ci    void DeferEvent(AppExecFwk::InnerEvent::Pointer &&event)
1112d43be4eSopenharmony_ci    {
1122d43be4eSopenharmony_ci        std::lock_guard<std::mutex> guard(mtx_);
1132d43be4eSopenharmony_ci        deferEvents_.push_back(std::move(event));
1142d43be4eSopenharmony_ci    }
1152d43be4eSopenharmony_ci
1162d43be4eSopenharmony_ci    virtual void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
1172d43be4eSopenharmony_ci    {
1182d43be4eSopenharmony_ci        if (event == nullptr || isQuit_) {
1192d43be4eSopenharmony_ci            TELEPHONY_LOGE("The event parameter is incorrect");
1202d43be4eSopenharmony_ci            return;
1212d43be4eSopenharmony_ci        }
1222d43be4eSopenharmony_ci        if (event->GetInnerEventId() == CellularDataEventCode::MSG_STATE_MACHINE_QUIT) {
1232d43be4eSopenharmony_ci            TELEPHONY_LOGI("State machine exit");
1242d43be4eSopenharmony_ci            Quit();
1252d43be4eSopenharmony_ci            return;
1262d43be4eSopenharmony_ci        }
1272d43be4eSopenharmony_ci        if (event->GetInnerEventId() == CellularDataEventCode::MSG_STATE_MACHINE_INIT) {
1282d43be4eSopenharmony_ci            destState_ = originalState_;
1292d43be4eSopenharmony_ci            InitCmdEnter(originalState_);
1302d43be4eSopenharmony_ci        }
1312d43be4eSopenharmony_ci        ProcessMsg(event);
1322d43be4eSopenharmony_ci        ProcessTransitions(event);
1332d43be4eSopenharmony_ci    }
1342d43be4eSopenharmony_ci
1352d43be4eSopenharmony_ci    virtual void ProcessMsg(const AppExecFwk::InnerEvent::Pointer &event)
1362d43be4eSopenharmony_ci    {
1372d43be4eSopenharmony_ci        sptr<State> tmpState = curState_;
1382d43be4eSopenharmony_ci        TELEPHONY_LOGD("The event id: %{public}u", event->GetInnerEventId());
1392d43be4eSopenharmony_ci        while (tmpState != nullptr && !tmpState->StateProcess(event)) {
1402d43be4eSopenharmony_ci            tmpState = tmpState->parent_;
1412d43be4eSopenharmony_ci        }
1422d43be4eSopenharmony_ci    }
1432d43be4eSopenharmony_ci
1442d43be4eSopenharmony_ciprivate:
1452d43be4eSopenharmony_ci    void InitCmdEnter(const sptr<State> &state)
1462d43be4eSopenharmony_ci    {
1472d43be4eSopenharmony_ci        if (state == nullptr) {
1482d43be4eSopenharmony_ci            TELEPHONY_LOGE("registerState_ is null");
1492d43be4eSopenharmony_ci            return;
1502d43be4eSopenharmony_ci        }
1512d43be4eSopenharmony_ci        if (state->parent_ != nullptr) {
1522d43be4eSopenharmony_ci            InitCmdEnter(state->parent_);
1532d43be4eSopenharmony_ci        }
1542d43be4eSopenharmony_ci        TELEPHONY_LOGI("Initialize entry %{public}s", state->name_.c_str());
1552d43be4eSopenharmony_ci        state->StateBegin();
1562d43be4eSopenharmony_ci        curState_ = state;
1572d43be4eSopenharmony_ci    }
1582d43be4eSopenharmony_ci
1592d43be4eSopenharmony_ci    void SendDeferredEvent()
1602d43be4eSopenharmony_ci    {
1612d43be4eSopenharmony_ci        std::lock_guard<std::mutex> guard(mtx_);
1622d43be4eSopenharmony_ci        if (deferEvents_.empty()) {
1632d43be4eSopenharmony_ci            return;
1642d43be4eSopenharmony_ci        }
1652d43be4eSopenharmony_ci        for (size_t i = 0; i < deferEvents_.size(); ++i) {
1662d43be4eSopenharmony_ci            AppExecFwk::InnerEvent::Pointer event = std::move(deferEvents_[i]);
1672d43be4eSopenharmony_ci            SendImmediateEvent(event);
1682d43be4eSopenharmony_ci        }
1692d43be4eSopenharmony_ci        deferEvents_.clear();
1702d43be4eSopenharmony_ci    }
1712d43be4eSopenharmony_ci
1722d43be4eSopenharmony_ciprivate:
1732d43be4eSopenharmony_ci    sptr<State> originalState_;
1742d43be4eSopenharmony_ci    sptr<State> destState_;
1752d43be4eSopenharmony_ci    sptr<State> curState_;
1762d43be4eSopenharmony_ci    std::vector<AppExecFwk::InnerEvent::Pointer> deferEvents_;
1772d43be4eSopenharmony_ci    std::mutex mtx_;
1782d43be4eSopenharmony_ci    bool isQuit_ = false;
1792d43be4eSopenharmony_ci};
1802d43be4eSopenharmony_ci
1812d43be4eSopenharmony_ciclass StateMachine {
1822d43be4eSopenharmony_cipublic:
1832d43be4eSopenharmony_ci    explicit StateMachine(const std::string &name)
1842d43be4eSopenharmony_ci    {
1852d43be4eSopenharmony_ci        stateMachineEventHandler_ = std::make_shared<StateMachineEventHandler>(name);
1862d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
1872d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
1882d43be4eSopenharmony_ci            return;
1892d43be4eSopenharmony_ci        }
1902d43be4eSopenharmony_ci    }
1912d43be4eSopenharmony_ci
1922d43be4eSopenharmony_ci    virtual ~StateMachine() {}
1932d43be4eSopenharmony_ci
1942d43be4eSopenharmony_ci    void Quit()
1952d43be4eSopenharmony_ci    {
1962d43be4eSopenharmony_ci        AppExecFwk::InnerEvent::Pointer event =
1972d43be4eSopenharmony_ci            AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STATE_MACHINE_QUIT);
1982d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
1992d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
2002d43be4eSopenharmony_ci            return;
2012d43be4eSopenharmony_ci        }
2022d43be4eSopenharmony_ci        stateMachineEventHandler_->SendImmediateEvent(event);
2032d43be4eSopenharmony_ci    }
2042d43be4eSopenharmony_ci
2052d43be4eSopenharmony_ci    void Start()
2062d43be4eSopenharmony_ci    {
2072d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
2082d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
2092d43be4eSopenharmony_ci            return;
2102d43be4eSopenharmony_ci        }
2112d43be4eSopenharmony_ci        AppExecFwk::InnerEvent::Pointer event =
2122d43be4eSopenharmony_ci            AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STATE_MACHINE_INIT);
2132d43be4eSopenharmony_ci        stateMachineEventHandler_->SendImmediateEvent(event);
2142d43be4eSopenharmony_ci    }
2152d43be4eSopenharmony_ci
2162d43be4eSopenharmony_ci    void SetOriginalState(sptr<State> &originalState)
2172d43be4eSopenharmony_ci    {
2182d43be4eSopenharmony_ci        if (originalState == nullptr) {
2192d43be4eSopenharmony_ci            TELEPHONY_LOGE("originalState is null");
2202d43be4eSopenharmony_ci            return;
2212d43be4eSopenharmony_ci        }
2222d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
2232d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
2242d43be4eSopenharmony_ci            return;
2252d43be4eSopenharmony_ci        }
2262d43be4eSopenharmony_ci        stateMachineEventHandler_->SetOriginalState(originalState);
2272d43be4eSopenharmony_ci    }
2282d43be4eSopenharmony_ci
2292d43be4eSopenharmony_ci    void TransitionTo(sptr<State> &destState)
2302d43be4eSopenharmony_ci    {
2312d43be4eSopenharmony_ci        if (destState == nullptr) {
2322d43be4eSopenharmony_ci            TELEPHONY_LOGE("destState is null");
2332d43be4eSopenharmony_ci            return;
2342d43be4eSopenharmony_ci        }
2352d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
2362d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
2372d43be4eSopenharmony_ci            return;
2382d43be4eSopenharmony_ci        }
2392d43be4eSopenharmony_ci        stateMachineEventHandler_->TransitionTo(destState);
2402d43be4eSopenharmony_ci    }
2412d43be4eSopenharmony_ci
2422d43be4eSopenharmony_ci    void DeferEvent(const AppExecFwk::InnerEvent::Pointer &&event)
2432d43be4eSopenharmony_ci    {
2442d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
2452d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
2462d43be4eSopenharmony_ci            return;
2472d43be4eSopenharmony_ci        }
2482d43be4eSopenharmony_ci        stateMachineEventHandler_->DeferEvent(std::move(const_cast<AppExecFwk::InnerEvent::Pointer &>(event)));
2492d43be4eSopenharmony_ci    }
2502d43be4eSopenharmony_ci
2512d43be4eSopenharmony_ci    void SendEvent(AppExecFwk::InnerEvent::Pointer &event)
2522d43be4eSopenharmony_ci    {
2532d43be4eSopenharmony_ci        if (stateMachineEventHandler_ == nullptr) {
2542d43be4eSopenharmony_ci            TELEPHONY_LOGE("stateMachineEventHandler_ is null");
2552d43be4eSopenharmony_ci            return;
2562d43be4eSopenharmony_ci        }
2572d43be4eSopenharmony_ci        if (event == nullptr) {
2582d43be4eSopenharmony_ci            TELEPHONY_LOGE("event is null");
2592d43be4eSopenharmony_ci            return;
2602d43be4eSopenharmony_ci        }
2612d43be4eSopenharmony_ci        TELEPHONY_LOGD("State machine send event id %{public}u ", event->GetInnerEventId());
2622d43be4eSopenharmony_ci        stateMachineEventHandler_->SendEvent(event);
2632d43be4eSopenharmony_ci    }
2642d43be4eSopenharmony_ci
2652d43be4eSopenharmony_ciprotected:
2662d43be4eSopenharmony_ci    std::shared_ptr<StateMachineEventHandler> stateMachineEventHandler_;
2672d43be4eSopenharmony_ci};
2682d43be4eSopenharmony_ci} // namespace Telephony
2692d43be4eSopenharmony_ci} // namespace OHOS
2702d43be4eSopenharmony_ci#endif // STATE_MACHINE_H
271