1 /*
2 * Copyright (c) 2023 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 "power_mgr_client.h"
17 #include "state_manager_adapter.h"
18
19 #include "common_event_support.h"
20 #include "standby_service_impl.h"
21 #include "standby_state_subscriber.h"
22 #include "standby_config_manager.h"
23
24 #include "base_state.h"
25 #include "dark_state.h"
26 #include "maintenance_state.h"
27 #include "nap_state.h"
28 #include "sleep_state.h"
29 #include "working_state.h"
30
31 namespace OHOS {
32 namespace DevStandbyMgr {
Init()33 bool StateManagerAdapter::Init()
34 {
35 auto StandbyServiceImpl = StandbyServiceImpl::GetInstance();
36 handler_ = StandbyServiceImpl->GetHandler();
37 constraintManager_ = StandbyServiceImpl->GetConstraintManager();
38 strategyManager_ = StandbyServiceImpl->GetStrategyManager();
39 auto stateManager = StandbyServiceImpl->GetStateManager();
40 BaseState::InitRunningLock();
41 workingStatePtr_ = std::make_shared<WorkingState>(StandbyState::WORKING, 0, stateManager, handler_);
42 darkStatePtr_ = std::make_shared<DarkState>(StandbyState::DARK, 0, stateManager, handler_);
43 napStatePtr_ = std::make_shared<NapState>(StandbyState::NAP, 0, stateManager, handler_);
44 maintStatePtr_ = std::make_shared<MaintenanceState>(StandbyState::MAINTENANCE, 0, stateManager, handler_);
45 sleepStatePtr_ = std::make_shared<SleepState>(StandbyState::SLEEP, 0, stateManager, handler_);
46 indexToState_ = {
47 workingStatePtr_, darkStatePtr_, napStatePtr_, maintStatePtr_, sleepStatePtr_
48 };
49 auto callbackTask = [this]() { this->OnScreenOffHalfHour(true, false); };
50 scrOffHalfHourTimerId_ = TimedTask::CreateTimer(false, 0, true, false, callbackTask);
51 if (scrOffHalfHourTimerId_ == 0) {
52 STANDBYSERVICE_LOGE("timer of screen off half hour is nullptr");
53 }
54 for (const auto& statePtr : indexToState_) {
55 if (statePtr->Init(statePtr) != ERR_OK) {
56 return false;
57 }
58 }
59 curStatePtr_ = workingStatePtr_;
60 preStatePtr_ = curStatePtr_;
61 isScreenOn_ = PowerMgr::PowerMgrClient::GetInstance().IsScreenOn();
62 if (curStatePtr_->BeginState() != ERR_OK) {
63 return false;
64 }
65 SendNotification(preStatePtr_->GetCurState(), true);
66 STANDBYSERVICE_LOGI("state manager plugin initialization succeed");
67 return true;
68 }
69
UnInit()70 bool StateManagerAdapter::UnInit()
71 {
72 TransitToState(StandbyState::WORKING);
73 curStatePtr_->EndState();
74 for (auto& statePtr : indexToState_) {
75 statePtr->UnInit();
76 statePtr.reset();
77 }
78 if (scrOffHalfHourTimerId_ > 0) {
79 MiscServices::TimeServiceClient::GetInstance()->StopTimer(scrOffHalfHourTimerId_);
80 MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(scrOffHalfHourTimerId_);
81 }
82 BaseState::ReleaseStandbyRunningLock();
83 return true;
84 }
85
HandleEvent(const StandbyMessage & message)86 void StateManagerAdapter::HandleEvent(const StandbyMessage& message)
87 {
88 if (message.eventId_ == StandbyMessageType::COMMON_EVENT) {
89 HandleCommonEvent(message);
90 } else if (message.eventId_ == StandbyMessageType::RES_CTRL_CONDITION_CHANGED) {
91 SendNotification(curStatePtr_->GetCurState(), false);
92 }
93 }
94
HandleCommonEvent(const StandbyMessage & message)95 void StateManagerAdapter::HandleCommonEvent(const StandbyMessage& message)
96 {
97 HandleScrOffHalfHour(message);
98 HandleOpenCloseLid(message);
99 HandleScreenStatus(message);
100 if (message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON ||
101 message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_CHARGING ||
102 message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED) {
103 TransitToState(StandbyState::WORKING);
104 }
105 if (curStatePtr_->GetCurState() != StandbyState::WORKING) {
106 return;
107 }
108 if (CheckEnterDarkState(message)) {
109 TransitToState(StandbyState::DARK);
110 }
111 }
112
HandleScreenStatus(const StandbyMessage & message)113 void StateManagerAdapter::HandleScreenStatus(const StandbyMessage& message)
114 {
115 if (message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON) {
116 isScreenOn_ = true;
117 } else if (message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF) {
118 isScreenOn_ = false;
119 }
120 }
121
CheckEnterDarkState(const StandbyMessage & message)122 bool StateManagerAdapter::CheckEnterDarkState(const StandbyMessage& message)
123 {
124 if (isScreenOn_) {
125 return false;
126 }
127 if (message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF ||
128 message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_DISCHARGING ||
129 message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED) {
130 return true;
131 }
132 return true;
133 }
134
HandleScrOffHalfHour(const StandbyMessage & message)135 void StateManagerAdapter::HandleScrOffHalfHour(const StandbyMessage& message)
136 {
137 if (scrOffHalfHourTimerId_ == 0) {
138 return;
139 }
140 if (message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF) {
141 isScreenOn_ = false;
142 screenOffTimeStamp_ = MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs();
143 MiscServices::TimeServiceClient::GetInstance()->StartTimer(scrOffHalfHourTimerId_,
144 screenOffTimeStamp_ + HALF_HOUR);
145 } else if (message.action_ == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON) {
146 isScreenOn_ = true;
147 MiscServices::TimeServiceClient::GetInstance()->StopTimer(scrOffHalfHourTimerId_);
148 }
149 }
150
HandleOpenCloseLid(const StandbyMessage & message)151 void StateManagerAdapter::HandleOpenCloseLid(const StandbyMessage& message)
152 {
153 if (message.action_ == LID_OPEN) {
154 TransitToState(StandbyState::WORKING);
155 } else if (message.action_ == LID_CLOSE && (curStatePtr_->GetCurState() != StandbyState::SLEEP &&
156 curStatePtr_->GetCurState() != StandbyState::MAINTENANCE)) {
157 UnblockCurrentState();
158 TransitToStateInner(StandbyState::SLEEP);
159 }
160 }
161
GetCurState()162 uint32_t StateManagerAdapter::GetCurState()
163 {
164 return curStatePtr_->GetCurState();
165 }
166
GetPreState()167 uint32_t StateManagerAdapter::GetPreState()
168 {
169 return preStatePtr_->GetCurState();
170 }
171
StartEvalCurrentState(const ConstraintEvalParam & params)172 ErrCode StateManagerAdapter::StartEvalCurrentState(const ConstraintEvalParam& params)
173 {
174 STANDBYSERVICE_LOGI("start evalution current state, current: %{public}u, %{public}u, next:"\
175 " %{public}u, %{public}u", params.curState_, params.curPhase_, params.nextState_,
176 params.nextPhase_);
177 isEvalution_ = true;
178 constraintManager_->StartEvalution(params);
179 return ERR_OK;
180 }
181
EndEvalCurrentState(bool evalResult)182 ErrCode StateManagerAdapter::EndEvalCurrentState(bool evalResult)
183 {
184 if (!isEvalution_) {
185 STANDBYSERVICE_LOGE("can not end evalution before start evalution");
186 return ERR_STANDBY_STATE_TIMING_SEQ_ERROR;
187 }
188 STANDBYSERVICE_LOGD("end evalution current state, result is %{public}d", evalResult);
189 isEvalution_ = false;
190 constraintManager_->StopEvalution();
191 curStatePtr_->EndEvalCurrentState(evalResult);
192 return ERR_OK;
193 }
194
BlockCurrentState()195 void StateManagerAdapter::BlockCurrentState()
196 {
197 isBlocked_ = true;
198 curStatePtr_->OnStateBlocked();
199 }
200
UnblockCurrentState()201 void StateManagerAdapter::UnblockCurrentState()
202 {
203 isBlocked_ = false;
204 }
205
TransitToState(uint32_t nextState)206 ErrCode StateManagerAdapter::TransitToState(uint32_t nextState)
207 {
208 uint32_t curState = curStatePtr_->GetCurState();
209 if (!CheckTransitionValid(curState, nextState)) {
210 return ERR_STANDBY_STATE_TRANSITION_FAILED;
211 }
212 if (curState == nextState) {
213 UnblockCurrentState();
214 } else if (nextState == StandbyState::MAINTENANCE ||
215 curState == StandbyState::MAINTENANCE) {
216 return TransitWithMaint(nextState);
217 } else if (curState < nextState) {
218 return EnterStandby(nextState);
219 } else {
220 return ExitStandby(nextState);
221 }
222 return ERR_OK;
223 }
224
ExitStandby(uint32_t nextState)225 ErrCode StateManagerAdapter::ExitStandby(uint32_t nextState)
226 {
227 if (isEvalution_) {
228 constraintManager_->StopEvalution();
229 isEvalution_ = false;
230 }
231 UnblockCurrentState();
232 if (scrOffHalfHourCtrl_) {
233 OnScreenOffHalfHour(false, false);
234 }
235 TransitToStateInner(nextState);
236 return ERR_OK;
237 }
238
CheckTransitionValid(uint32_t curState,uint32_t nextState)239 bool StateManagerAdapter::CheckTransitionValid(uint32_t curState, uint32_t nextState)
240 {
241 bool ret = curStatePtr_->CheckTransitionValid(nextState);
242 if (!ret) {
243 STANDBYSERVICE_LOGE("can not transitting from now %{public}s to next %{public}s",
244 STATE_NAME_LIST[curState].c_str(), STATE_NAME_LIST[nextState].c_str());
245 }
246 return ret;
247 }
248
EnterStandby(uint32_t nextState)249 ErrCode StateManagerAdapter::EnterStandby(uint32_t nextState)
250 {
251 if (isBlocked_) {
252 STANDBYSERVICE_LOGE("current standby state is blocked due to the previous failure of constraint");
253 return ERR_STANDBY_STATAE_BLOCKED;
254 }
255 ConstraintEvalParam params{curStatePtr_->GetCurState(), curStatePtr_->GetCurInnerPhase(), nextState, 0};
256 StartEvalCurrentState(params);
257 return ERR_OK;
258 }
259
TransitWithMaint(uint32_t nextState)260 ErrCode StateManagerAdapter::TransitWithMaint(uint32_t nextState)
261 {
262 return TransitToStateInner(nextState);
263 }
264
TransitToStateInner(uint32_t nextState)265 ErrCode StateManagerAdapter::TransitToStateInner(uint32_t nextState)
266 {
267 curStatePtr_->EndState();
268 preStatePtr_ = curStatePtr_;
269 curStatePtr_ = indexToState_[nextState];
270 curStatePtr_->BeginState();
271
272 RecordStateTransition();
273 SendNotification(preStatePtr_->GetCurState(), true);
274 BaseState::ReleaseStandbyRunningLock();
275 return ERR_OK;
276 }
277
RecordStateTransition()278 void StateManagerAdapter::RecordStateTransition()
279 {
280 auto curTimeStampMs = MiscServices::TimeServiceClient::GetInstance()->GetMonotonicTimeMs();
281 stateRecordList_.emplace_back(std::make_pair(preStatePtr_->GetCurState(),
282 curTimeStampMs));
283 if (stateRecordList_.size() > MAX_RECORD_SIZE) {
284 stateRecordList_.pop_front();
285 }
286 }
287
StopEvalution()288 void StateManagerAdapter::StopEvalution()
289 {
290 if (isEvalution_) {
291 constraintManager_->StopEvalution();
292 isEvalution_ = false;
293 }
294 }
295
OnScreenOffHalfHour(bool scrOffHalfHourCtrl,bool repeated)296 void StateManagerAdapter::OnScreenOffHalfHour(bool scrOffHalfHourCtrl, bool repeated)
297 {
298 handler_->PostSyncTask([this, scrOffHalfHourCtrl, repeated]() {
299 OnScreenOffHalfHourInner(scrOffHalfHourCtrl, repeated);
300 }, AppExecFwk::EventQueue::Priority::HIGH);
301 }
302
OnScreenOffHalfHourInner(bool scrOffHalfHourCtrl,bool repeated)303 void StateManagerAdapter::OnScreenOffHalfHourInner(bool scrOffHalfHourCtrl, bool repeated)
304 {
305 uint32_t curState = curStatePtr_->GetCurState();
306 uint32_t preState = preStatePtr_->GetCurState();
307 STANDBYSERVICE_LOGD("screen off half hour, cur state is %{public}s, pre state is %{public}s",
308 STATE_NAME_LIST[curState].c_str(), STATE_NAME_LIST[preState].c_str());
309 if (scrOffHalfHourCtrl && !(curState == StandbyState::SLEEP || (preState == StandbyState::SLEEP &&
310 curState == StandbyState::MAINTENANCE))) {
311 return;
312 }
313 if (!repeated && scrOffHalfHourCtrl_ == scrOffHalfHourCtrl) {
314 return;
315 }
316 STANDBYSERVICE_LOGD("half hour ctrl status from %{public}d to %{public}d", scrOffHalfHourCtrl_, scrOffHalfHourCtrl);
317 scrOffHalfHourCtrl_ = scrOffHalfHourCtrl;
318 StandbyMessage message(StandbyMessageType::SCREEN_OFF_HALF_HOUR);
319 message.want_ = AAFwk::Want{};
320 message.want_->SetParam(SCR_OFF_HALF_HOUR_STATUS, scrOffHalfHourCtrl_);
321 StandbyServiceImpl::GetInstance()->DispatchEvent(message);
322 }
323
SendNotification(uint32_t preState,bool needDispatchEvent)324 void StateManagerAdapter::SendNotification(uint32_t preState, bool needDispatchEvent)
325 {
326 uint32_t curState = curStatePtr_->GetCurState();
327 STANDBYSERVICE_LOGI("state transit succeed, previous is %{public}s, current is %{public}s",
328 STATE_NAME_LIST[preState].c_str(), STATE_NAME_LIST[curState].c_str());
329 if (needDispatchEvent) {
330 StandbyMessage message(StandbyMessageType::STATE_TRANSIT);
331 message.want_ = AAFwk::Want{};
332 message.want_->SetParam(PREVIOUS_STATE, static_cast<int32_t>(preState));
333 message.want_->SetParam(CURRENT_STATE, static_cast<int32_t>(curState));
334 StandbyServiceImpl::GetInstance()->DispatchEvent(message);
335 }
336 StandbyStateSubscriber::GetInstance()->ReportStandbyState(curState);
337 }
338
ShellDump(const std::vector<std::string> & argsInStr,std::string & result)339 void StateManagerAdapter::ShellDump(const std::vector<std::string>& argsInStr, std::string& result)
340 {
341 if (argsInStr[DUMP_FIRST_PARAM] == DUMP_DETAIL_INFO) {
342 DumpShowDetailInfo(argsInStr, result);
343 if (argsInStr[DUMP_SECOND_PARAM] == DUMP_RESET_STATE) {
344 DumpResetState(argsInStr, result);
345 }
346 } else if (argsInStr[DUMP_FIRST_PARAM] == DUMP_ENTER_STATE) {
347 DumpEnterSpecifiedState(argsInStr, result);
348 } else if (argsInStr[DUMP_FIRST_PARAM] == DUMP_SIMULATE_SENSOR) {
349 DumpActivateMotion(argsInStr, result);
350 }
351 curStatePtr_->ShellDump(argsInStr, result);
352 }
353
DumpShowDetailInfo(const std::vector<std::string> & argsInStr,std::string & result)354 void StateManagerAdapter::DumpShowDetailInfo(const std::vector<std::string>& argsInStr, std::string& result)
355 {
356 result += "isEvalution: " + std::to_string(isEvalution_) + ", isBlocking: " +
357 std::to_string(isBlocked_) + ", current state: " + STATE_NAME_LIST[
358 curStatePtr_->GetCurState()] + ", current phase: " + std::to_string(curStatePtr_->
359 GetCurInnerPhase()) + ", previous state: " + STATE_NAME_LIST[preStatePtr_->GetCurState()] +
360 ", scrOffHalfHourCtrl: " + std::to_string(scrOffHalfHourCtrl_) +
361 ", isScreenOn: " + std::to_string(isScreenOn_) + "\n";
362
363 if (stateRecordList_.empty()) {
364 result += "\nstate record is empty\n";
365 } else {
366 result += "\nstate transition record:\n";
367 }
368
369 for (const auto &[stateIndex, timeStamp] : stateRecordList_) {
370 result += STATE_NAME_LIST[stateIndex] + "\t" + std::to_string(timeStamp) + "\n";
371 }
372 }
373
DumpResetState(const std::vector<std::string> & argsInStr,std::string & result)374 void StateManagerAdapter::DumpResetState(const std::vector<std::string>& argsInStr, std::string& result)
375 {
376 UnInit();
377 Init();
378 result += "\nreset state and validate debug parameter\n";
379 }
380
DumpEnterSpecifiedState(const std::vector<std::string> & argsInStr,std::string & result)381 void StateManagerAdapter::DumpEnterSpecifiedState(const std::vector<std::string>& argsInStr, std::string& result)
382 {
383 isBlocked_ = false;
384 if (argsInStr[DUMP_THIRD_PARAM] == "false") {
385 curStatePtr_->StartTransitNextState(curStatePtr_);
386 } else {
387 auto iter = std::find(STATE_NAME_LIST.begin(), STATE_NAME_LIST.end(), argsInStr[DUMP_SECOND_PARAM]);
388 if (iter == STATE_NAME_LIST.end()) {
389 result += "state name is not correct";
390 return;
391 }
392 TransitToStateInner(iter - STATE_NAME_LIST.begin());
393 }
394 }
395
DumpActivateMotion(const std::vector<std::string> & argsInStr,std::string & result)396 void StateManagerAdapter::DumpActivateMotion(const std::vector<std::string>& argsInStr, std::string& result)
397 {
398 if (argsInStr[DUMP_SECOND_PARAM] == "--motion") {
399 curStatePtr_->StartTransitNextState(curStatePtr_);
400 handler_->PostTask([this]() {
401 STANDBYSERVICE_LOGD("after 3000ms, stop sensor");
402 this->EndEvalCurrentState(false);
403 }, MOTION_DETECTION_TIMEOUT);
404 result += "finished start periodly sensor\n";
405 } else if (argsInStr[DUMP_SECOND_PARAM] == "--blocked") {
406 BlockCurrentState();
407 } else if (argsInStr[DUMP_SECOND_PARAM] == "--halfhour") {
408 OnScreenOffHalfHourInner(true, true);
409 }
410 }
411 } // namespace DevStandbyMgr
412 } // namespace OHOS