1 /*
2  * Copyright (c) 2021-2022 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 #include "account_state_machine.h"
17 #include "account_info.h"
18 #include "account_log_wrapper.h"
19 #include "datetime_ex.h"
20 #include "perf_stat.h"
21 
22 namespace OHOS {
23 namespace AccountSA {
24 /**
25  * Account state machine initialize.
26  */
OnInitialize()27 void AccountStateMachine::OnInitialize()
28 {
29     stateMachineMap_ = {
30         // ACCOUNT_STATE_UNBOUND state
31         std::make_pair(ACCOUNT_STATE_UNBOUND, std::map<int, AccountStateAction *> {
32             // normal event, transform to login state
33             std::make_pair(ACCOUNT_BIND_SUCCESS_EVT, new (std::nothrow) LoginAction(ACCOUNT_STATE_LOGIN)),
34             // normal event, keep in unbound state
35             std::make_pair(ACCOUNT_BIND_FAILED_EVT, new (std::nothrow) ExceptionAction(ACCOUNT_STATE_UNBOUND)),
36             // unexpected event, re-initial state machine, check the state from account server
37             std::make_pair(ACCOUNT_AUTHENTICATE_SUCCESS_EVT, new (std::nothrow) LoginAction(ACCOUNT_STATE_LOGIN)),
38             // unexpected event, re-initial state machine, check the state from account server
39             std::make_pair(ACCOUNT_AUTHENTICATE_FAILED_EVT, nullptr),
40             // unexpected event, re-initial state machine, check the state from account server
41             std::make_pair(ACCOUNT_TOKEN_EXPIRED_EVT, nullptr),
42             // unexpected event, re-initial state machine, check the state from account server
43             std::make_pair(ACCOUNT_PASSWORD_CHANGED_EVT, nullptr),
44             // unexpected event, re-initial state machine, check the state from account server
45             std::make_pair(ACCOUNT_MANUAL_LOGOUT_EVT, nullptr),
46             // unexpected event, keep in unbound state
47             std::make_pair(ACCOUNT_MANUAL_UNBOUND_EVT, nullptr),
48             // unexpected event, keep in unbound state
49             std::make_pair(ACCOUNT_MANUAL_LOGOFF_EVT, nullptr)}
50         ),
51         // ACCOUNT_STATE_LOGIN state
52         std::make_pair(ACCOUNT_STATE_LOGIN, std::map<int, AccountStateAction *> {
53             // expected event, keep in login state
54             std::make_pair(ACCOUNT_BIND_SUCCESS_EVT, nullptr),
55             // unexpected event, re-initial state machine, check the state from account server
56             std::make_pair(ACCOUNT_BIND_FAILED_EVT, new (std::nothrow) ExceptionAction(ACCOUNT_STATE_LOGIN)),
57             // normal event, keep in login state
58             std::make_pair(ACCOUNT_AUTHENTICATE_SUCCESS_EVT, nullptr),
59             // normal event, transform to logout state
60             std::make_pair(ACCOUNT_AUTHENTICATE_FAILED_EVT, nullptr),
61             // expected event, transform to logout state
62             std::make_pair(ACCOUNT_TOKEN_EXPIRED_EVT, new (std::nothrow) LogoutAction(ACCOUNT_STATE_UNBOUND)),
63             // expected event, transform to logout state
64             std::make_pair(ACCOUNT_PASSWORD_CHANGED_EVT, new (std::nothrow) LogoutAction(ACCOUNT_STATE_UNBOUND)),
65             // expected event, transform to logout state
66             std::make_pair(ACCOUNT_MANUAL_LOGOUT_EVT, new (std::nothrow) LogoutAction(ACCOUNT_STATE_UNBOUND)),
67             // expected event, transform to unbound state
68             std::make_pair(ACCOUNT_MANUAL_UNBOUND_EVT, new (std::nothrow) UnboundAction(ACCOUNT_STATE_UNBOUND)),
69             // expected event, transform to logoff state
70             std::make_pair(ACCOUNT_MANUAL_LOGOFF_EVT, new (std::nothrow) LogoffAction(ACCOUNT_STATE_UNBOUND))}
71         ),
72     };
73 }
74 
75 /**
76  * Account state machine clean.
77  */
Clean()78 void AccountStateMachine::Clean()
79 {
80     for (auto &currentStateIter : stateMachineMap_) {
81         for (auto &eventIter : currentStateIter.second) {
82             if (eventIter.second != nullptr) {
83                 delete eventIter.second;
84                 eventIter.second = nullptr;
85             }
86         }
87     }
88 }
89 
90 /**
91  * Process a state change event
92  *
93  * @param evt the event info
94  * @return true if the processing was completed, otherwise false
95  */
StateChangeProcess(int evt)96 bool AccountStateMachine::StateChangeProcess(int evt)
97 {
98     // for performance record
99     std::string stateRecordStr;
100     int64_t processTicks = GetTickCount();
101     stateRecordStr.append("state from[").append(std::to_string(currentState_)).append("] to [");
102 
103     // get all the current state event action
104     auto stateIter = stateMachineMap_.find(currentState_);
105     if (stateIter == stateMachineMap_.end()) {
106         ACCOUNT_LOGE("current state %{public}d is not in state machine map.", currentState_);
107         return false;
108     }
109 
110     // get the current event action
111     auto eventIter = stateIter->second.find(evt);
112     if (eventIter == stateIter->second.end()) {
113         ACCOUNT_LOGE("event %{public}d is not in state machine map.", evt);
114         return false;
115     }
116 
117     // maybe action is null
118     if (eventIter->second == nullptr) {
119         ACCOUNT_LOGI("event %{public}d has no action.", evt);
120         return true;
121     }
122 
123     int nextState = eventIter->second->GetNextState();
124     if (currentState_ != nextState) {
125         ACCOUNT_LOGI("account state change, (oldstate, newstate) = (%{public}d, %{public}d)", currentState_, nextState);
126         currentState_ = nextState;
127     }
128 
129     // Record state change performance
130     processTicks = GetTickCount() - processTicks;
131     stateRecordStr.append(std::to_string(nextState)).append("], event[").append(std::to_string(evt)).append("] Cost");
132     PerfStat::GetInstance().SetAccountStateChangeTime(stateRecordStr, processTicks);
133 
134     return true;
135 }
136 } // namespace AccountSA
137 } // namespace OHOS
138