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 ¤tStateIter : 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