1c2b37d2cSopenharmony_ci/*
2c2b37d2cSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3c2b37d2cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c2b37d2cSopenharmony_ci * you may not use this file except in compliance with the License.
5c2b37d2cSopenharmony_ci * You may obtain a copy of the License at
6c2b37d2cSopenharmony_ci *
7c2b37d2cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c2b37d2cSopenharmony_ci *
9c2b37d2cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c2b37d2cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c2b37d2cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c2b37d2cSopenharmony_ci * See the License for the specific language governing permissions and
13c2b37d2cSopenharmony_ci * limitations under the License.
14c2b37d2cSopenharmony_ci */
15c2b37d2cSopenharmony_ci
16c2b37d2cSopenharmony_ci#include "account_state_machine.h"
17c2b37d2cSopenharmony_ci#include "account_info.h"
18c2b37d2cSopenharmony_ci#include "account_log_wrapper.h"
19c2b37d2cSopenharmony_ci#include "datetime_ex.h"
20c2b37d2cSopenharmony_ci#include "perf_stat.h"
21c2b37d2cSopenharmony_ci
22c2b37d2cSopenharmony_cinamespace OHOS {
23c2b37d2cSopenharmony_cinamespace AccountSA {
24c2b37d2cSopenharmony_ci/**
25c2b37d2cSopenharmony_ci * Account state machine initialize.
26c2b37d2cSopenharmony_ci */
27c2b37d2cSopenharmony_civoid AccountStateMachine::OnInitialize()
28c2b37d2cSopenharmony_ci{
29c2b37d2cSopenharmony_ci    stateMachineMap_ = {
30c2b37d2cSopenharmony_ci        // ACCOUNT_STATE_UNBOUND state
31c2b37d2cSopenharmony_ci        std::make_pair(ACCOUNT_STATE_UNBOUND, std::map<int, AccountStateAction *> {
32c2b37d2cSopenharmony_ci            // normal event, transform to login state
33c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_BIND_SUCCESS_EVT, new (std::nothrow) LoginAction(ACCOUNT_STATE_LOGIN)),
34c2b37d2cSopenharmony_ci            // normal event, keep in unbound state
35c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_BIND_FAILED_EVT, new (std::nothrow) ExceptionAction(ACCOUNT_STATE_UNBOUND)),
36c2b37d2cSopenharmony_ci            // unexpected event, re-initial state machine, check the state from account server
37c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_AUTHENTICATE_SUCCESS_EVT, new (std::nothrow) LoginAction(ACCOUNT_STATE_LOGIN)),
38c2b37d2cSopenharmony_ci            // unexpected event, re-initial state machine, check the state from account server
39c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_AUTHENTICATE_FAILED_EVT, nullptr),
40c2b37d2cSopenharmony_ci            // unexpected event, re-initial state machine, check the state from account server
41c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_TOKEN_EXPIRED_EVT, nullptr),
42c2b37d2cSopenharmony_ci            // unexpected event, re-initial state machine, check the state from account server
43c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_PASSWORD_CHANGED_EVT, nullptr),
44c2b37d2cSopenharmony_ci            // unexpected event, re-initial state machine, check the state from account server
45c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_MANUAL_LOGOUT_EVT, nullptr),
46c2b37d2cSopenharmony_ci            // unexpected event, keep in unbound state
47c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_MANUAL_UNBOUND_EVT, nullptr),
48c2b37d2cSopenharmony_ci            // unexpected event, keep in unbound state
49c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_MANUAL_LOGOFF_EVT, nullptr)}
50c2b37d2cSopenharmony_ci        ),
51c2b37d2cSopenharmony_ci        // ACCOUNT_STATE_LOGIN state
52c2b37d2cSopenharmony_ci        std::make_pair(ACCOUNT_STATE_LOGIN, std::map<int, AccountStateAction *> {
53c2b37d2cSopenharmony_ci            // expected event, keep in login state
54c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_BIND_SUCCESS_EVT, nullptr),
55c2b37d2cSopenharmony_ci            // unexpected event, re-initial state machine, check the state from account server
56c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_BIND_FAILED_EVT, new (std::nothrow) ExceptionAction(ACCOUNT_STATE_LOGIN)),
57c2b37d2cSopenharmony_ci            // normal event, keep in login state
58c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_AUTHENTICATE_SUCCESS_EVT, nullptr),
59c2b37d2cSopenharmony_ci            // normal event, transform to logout state
60c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_AUTHENTICATE_FAILED_EVT, nullptr),
61c2b37d2cSopenharmony_ci            // expected event, transform to logout state
62c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_TOKEN_EXPIRED_EVT, new (std::nothrow) LogoutAction(ACCOUNT_STATE_UNBOUND)),
63c2b37d2cSopenharmony_ci            // expected event, transform to logout state
64c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_PASSWORD_CHANGED_EVT, new (std::nothrow) LogoutAction(ACCOUNT_STATE_UNBOUND)),
65c2b37d2cSopenharmony_ci            // expected event, transform to logout state
66c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_MANUAL_LOGOUT_EVT, new (std::nothrow) LogoutAction(ACCOUNT_STATE_UNBOUND)),
67c2b37d2cSopenharmony_ci            // expected event, transform to unbound state
68c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_MANUAL_UNBOUND_EVT, new (std::nothrow) UnboundAction(ACCOUNT_STATE_UNBOUND)),
69c2b37d2cSopenharmony_ci            // expected event, transform to logoff state
70c2b37d2cSopenharmony_ci            std::make_pair(ACCOUNT_MANUAL_LOGOFF_EVT, new (std::nothrow) LogoffAction(ACCOUNT_STATE_UNBOUND))}
71c2b37d2cSopenharmony_ci        ),
72c2b37d2cSopenharmony_ci    };
73c2b37d2cSopenharmony_ci}
74c2b37d2cSopenharmony_ci
75c2b37d2cSopenharmony_ci/**
76c2b37d2cSopenharmony_ci * Account state machine clean.
77c2b37d2cSopenharmony_ci */
78c2b37d2cSopenharmony_civoid AccountStateMachine::Clean()
79c2b37d2cSopenharmony_ci{
80c2b37d2cSopenharmony_ci    for (auto &currentStateIter : stateMachineMap_) {
81c2b37d2cSopenharmony_ci        for (auto &eventIter : currentStateIter.second) {
82c2b37d2cSopenharmony_ci            if (eventIter.second != nullptr) {
83c2b37d2cSopenharmony_ci                delete eventIter.second;
84c2b37d2cSopenharmony_ci                eventIter.second = nullptr;
85c2b37d2cSopenharmony_ci            }
86c2b37d2cSopenharmony_ci        }
87c2b37d2cSopenharmony_ci    }
88c2b37d2cSopenharmony_ci}
89c2b37d2cSopenharmony_ci
90c2b37d2cSopenharmony_ci/**
91c2b37d2cSopenharmony_ci * Process a state change event
92c2b37d2cSopenharmony_ci *
93c2b37d2cSopenharmony_ci * @param evt the event info
94c2b37d2cSopenharmony_ci * @return true if the processing was completed, otherwise false
95c2b37d2cSopenharmony_ci */
96c2b37d2cSopenharmony_cibool AccountStateMachine::StateChangeProcess(int evt)
97c2b37d2cSopenharmony_ci{
98c2b37d2cSopenharmony_ci    // for performance record
99c2b37d2cSopenharmony_ci    std::string stateRecordStr;
100c2b37d2cSopenharmony_ci    int64_t processTicks = GetTickCount();
101c2b37d2cSopenharmony_ci    stateRecordStr.append("state from[").append(std::to_string(currentState_)).append("] to [");
102c2b37d2cSopenharmony_ci
103c2b37d2cSopenharmony_ci    // get all the current state event action
104c2b37d2cSopenharmony_ci    auto stateIter = stateMachineMap_.find(currentState_);
105c2b37d2cSopenharmony_ci    if (stateIter == stateMachineMap_.end()) {
106c2b37d2cSopenharmony_ci        ACCOUNT_LOGE("current state %{public}d is not in state machine map.", currentState_);
107c2b37d2cSopenharmony_ci        return false;
108c2b37d2cSopenharmony_ci    }
109c2b37d2cSopenharmony_ci
110c2b37d2cSopenharmony_ci    // get the current event action
111c2b37d2cSopenharmony_ci    auto eventIter = stateIter->second.find(evt);
112c2b37d2cSopenharmony_ci    if (eventIter == stateIter->second.end()) {
113c2b37d2cSopenharmony_ci        ACCOUNT_LOGE("event %{public}d is not in state machine map.", evt);
114c2b37d2cSopenharmony_ci        return false;
115c2b37d2cSopenharmony_ci    }
116c2b37d2cSopenharmony_ci
117c2b37d2cSopenharmony_ci    // maybe action is null
118c2b37d2cSopenharmony_ci    if (eventIter->second == nullptr) {
119c2b37d2cSopenharmony_ci        ACCOUNT_LOGI("event %{public}d has no action.", evt);
120c2b37d2cSopenharmony_ci        return true;
121c2b37d2cSopenharmony_ci    }
122c2b37d2cSopenharmony_ci
123c2b37d2cSopenharmony_ci    int nextState = eventIter->second->GetNextState();
124c2b37d2cSopenharmony_ci    if (currentState_ != nextState) {
125c2b37d2cSopenharmony_ci        ACCOUNT_LOGI("account state change, (oldstate, newstate) = (%{public}d, %{public}d)", currentState_, nextState);
126c2b37d2cSopenharmony_ci        currentState_ = nextState;
127c2b37d2cSopenharmony_ci    }
128c2b37d2cSopenharmony_ci
129c2b37d2cSopenharmony_ci    // Record state change performance
130c2b37d2cSopenharmony_ci    processTicks = GetTickCount() - processTicks;
131c2b37d2cSopenharmony_ci    stateRecordStr.append(std::to_string(nextState)).append("], event[").append(std::to_string(evt)).append("] Cost");
132c2b37d2cSopenharmony_ci    PerfStat::GetInstance().SetAccountStateChangeTime(stateRecordStr, processTicks);
133c2b37d2cSopenharmony_ci
134c2b37d2cSopenharmony_ci    return true;
135c2b37d2cSopenharmony_ci}
136c2b37d2cSopenharmony_ci} // namespace AccountSA
137c2b37d2cSopenharmony_ci} // namespace OHOS
138