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 "sleep_state.h"
17 
18 #include <cmath>
19 #include "time_service_client.h"
20 
21 #include "standby_service_log.h"
22 #include "standby_config_manager.h"
23 #include "iconstraint_manager_adapter.h"
24 #include "istate_manager_adapter.h"
25 #include "time_provider.h"
26 #include "timed_task.h"
27 
28 using namespace OHOS::MiscServices;
29 namespace OHOS {
30 namespace DevStandbyMgr {
31 namespace {
32     constexpr int32_t DUMP_REPEAT_DETECTION_TIMEOUT = 100;
33 }
34 
SleepState(uint32_t curState,uint32_t curPhase,const std::shared_ptr<IStateManagerAdapter> & stateManager,std::shared_ptr<AppExecFwk::EventHandler> & handler)35 SleepState::SleepState(uint32_t curState, uint32_t curPhase, const std::shared_ptr<IStateManagerAdapter>&
36     stateManager, std::shared_ptr<AppExecFwk::EventHandler>& handler): BaseState(curState,
37     curPhase, stateManager, handler)
38 {
39     maintInterval_ = StandbyConfigManager::GetInstance()->GetStandbyDurationList(SLEEP_MAINT_DURATOIN);
40     nextState_ = StandbyState::MAINTENANCE;
41 }
42 
Init(const std::shared_ptr<BaseState> & statePtr)43 ErrCode SleepState::Init(const std::shared_ptr<BaseState>& statePtr)
44 {
45     auto callbackTask = [statePtr]() { statePtr->StartTransitNextState(statePtr); };
46     enterStandbyTimerId_ = TimedTask::CreateTimer(false, 0, true, true, callbackTask);
47     if (enterStandbyTimerId_ == 0) {
48         STANDBYSERVICE_LOGE("%{public}s state init failed", STATE_NAME_LIST[GetCurState()].c_str());
49         return ERR_STANDBY_STATE_INIT_FAILED;
50     }
51 
52     if (!StandbyConfigManager::GetInstance()->GetStandbySwitch(DETECT_MOTION_CONFIG)) {
53         return ERR_OK;
54     }
55     auto callback = [sleepState = shared_from_this()]() { sleepState->StartPeriodlyMotionDetection(); };
56     repeatedDetectionTimerId_ = TimedTask::CreateTimer(true, REPEATED_MOTION_DETECTION_INTERVAL, true, false, callback);
57     if (repeatedDetectionTimerId_ == 0) {
58         STANDBYSERVICE_LOGE("%{public}s init failed", STATE_NAME_LIST[GetCurState()].c_str());
59         return ERR_STANDBY_STATE_INIT_FAILED;
60     }
61     SetTimedTask(REPEATED_MOTION_DETECTION_TASK, repeatedDetectionTimerId_);
62     return ERR_OK;
63 }
64 
StartPeriodlyMotionDetection()65 void SleepState::StartPeriodlyMotionDetection()
66 {
67     handler_->PostTask([sleepState = shared_from_this()]() {
68         sleepState->isRepeatedDetection_ = true;
69         ConstraintEvalParam params{sleepState->curState_, sleepState->curPhase_,
70             sleepState->curState_, sleepState->curPhase_};
71         params.isRepeatedDetection_ = true;
72         auto stateManagerPtr = sleepState->stateManager_.lock();
73         if (!stateManagerPtr) {
74             return;
75         }
76         stateManagerPtr->StartEvalCurrentState(params);
77         }, REPEATED_MOTION_DETECTION_TASK);
78 }
79 
UnInit()80 ErrCode SleepState::UnInit()
81 {
82     BaseState::UnInit();
83     isRepeatedDetection_ = false;
84     repeatedDetectionTimerId_ = 0;
85     return ERR_OK;
86 }
87 
BeginState()88 ErrCode SleepState::BeginState()
89 {
90     auto stateManagerPtr = stateManager_.lock();
91     if (!stateManagerPtr) {
92         STANDBYSERVICE_LOGE("state manager adapter is nullptr");
93         return ERR_STATE_MANAGER_IS_NULLPTR;
94     }
95     isRepeatedDetection_ = false;
96     int64_t maintIntervalTimeOut = 0;
97     if (stateManagerPtr->GetPreState() == StandbyState::MAINTENANCE) {
98         maintIntervalTimeOut = CalculateMaintTimeOut(stateManagerPtr, false);
99         if (maintIntervalTimeOut != 0) {
100             STANDBYSERVICE_LOGI("from maintenance to sleep, maintIntervalTimeOut is " SPUBI64,
101                 maintIntervalTimeOut);
102             StartStateTransitionTimer(maintIntervalTimeOut);
103         }
104         return ERR_OK;
105     }
106 
107     maintIntervalIndex_ = 0;
108     curPhase_ = SleepStatePhase::SYS_RES_DEEP;
109     maintIntervalTimeOut = CalculateMaintTimeOut(stateManagerPtr, true);
110     STANDBYSERVICE_LOGI("maintIntervalTimeOut is " SPUBI64 " ms", maintIntervalTimeOut);
111 
112     handler_->PostTask([sleepState = shared_from_this()]() {
113         BaseState::AcquireStandbyRunningLock();
114         sleepState->TransitToPhase(sleepState->curPhase_, sleepState->curPhase_ + 1);
115         }, TRANSIT_NEXT_PHASE_INSTANT_TASK);
116     StartStateTransitionTimer(maintIntervalTimeOut);
117     CheckScrenOffHalfHour();
118     return ERR_OK;
119 }
120 
TryToEnterNextPhase(const std::shared_ptr<IStateManagerAdapter> & stateManagerPtr,int32_t retryTimeOut)121 void SleepState::TryToEnterNextPhase(const std::shared_ptr<IStateManagerAdapter>& stateManagerPtr,
122     int32_t retryTimeOut)
123 {
124     if (stateManagerPtr->IsEvalution()) {
125         STANDBYSERVICE_LOGW("state is in evalution, postpone to enter next phase");
126         handler_->PostTask([sleepState = shared_from_this(), stateManagerPtr, retryTimeOut]() {
127             sleepState->TryToEnterNextPhase(stateManagerPtr, retryTimeOut);
128             }, TRANSIT_NEXT_PHASE_INSTANT_TASK, retryTimeOut);
129     } else if (curPhase_ < SleepStatePhase::END) {
130         TransitToPhase(curPhase_, curPhase_ + 1);
131     }
132 }
133 
EndState()134 ErrCode SleepState::EndState()
135 {
136     StopTimedTask(TRANSIT_NEXT_STATE_TIMED_TASK);
137     StopTimedTask(REPEATED_MOTION_DETECTION_TASK);
138     handler_->RemoveTask(TRANSIT_NEXT_STATE_TIMED_TASK);
139     handler_->RemoveTask(TRANSIT_NEXT_PHASE_INSTANT_TASK);
140     handler_->RemoveTask(REPEATED_MOTION_DETECTION_TASK);
141     return ERR_OK;
142 }
143 
CheckTransitionValid(uint32_t nextState)144 bool SleepState::CheckTransitionValid(uint32_t nextState)
145 {
146     if (nextState == StandbyState::NAP) {
147         STANDBYSERVICE_LOGE("can not transit from sleep to nap");
148         return false;
149     }
150     return true;
151 }
152 
EndEvalCurrentState(bool evalResult)153 void SleepState::EndEvalCurrentState(bool evalResult)
154 {
155     auto stateManagerPtr = stateManager_.lock();
156     if (!stateManagerPtr) {
157         STANDBYSERVICE_LOGW("state manager is nullptr, cannot end eval sleep state");
158         return;
159     }
160     if (curPhase_ < SleepStatePhase::END) {
161         if (evalResult) {
162             TransitToPhaseInner(curPhase_, curPhase_ + 1);
163         }
164         SetPhaseTransitOrRepeatedTask();
165         return;
166     }
167     if (!evalResult && isRepeatedDetection_) {
168         stateManagerPtr->TransitToState(StandbyState::WORKING);
169     }
170     isRepeatedDetection_ = false;
171 }
172 
SetPhaseTransitOrRepeatedTask()173 void SleepState::SetPhaseTransitOrRepeatedTask()
174 {
175     curPhase_ += 1;
176     if (curPhase_ < SleepStatePhase::END) {
177         handler_->PostTask([sleepState = shared_from_this()]() {
178             sleepState->TransitToPhase(sleepState->curPhase_, sleepState->curPhase_ + 1);
179             }, TRANSIT_NEXT_PHASE_INSTANT_TASK);
180     } else {
181         BaseState::ReleaseStandbyRunningLock();
182         if (repeatedDetectionTimerId_ == 0 || !MiscServices::TimeServiceClient::GetInstance()->
183             StartTimer(repeatedDetectionTimerId_, MiscServices::TimeServiceClient::GetInstance()->
184             GetWallTimeMs() + REPEATED_MOTION_DETECTION_INTERVAL)) {
185             STANDBYSERVICE_LOGE("sleep state set periodly task failed");
186         }
187     }
188 }
189 
ShellDump(const std::vector<std::string> & argsInStr,std::string & result)190 void SleepState::ShellDump(const std::vector<std::string>& argsInStr, std::string& result)
191 {
192     if (argsInStr[DUMP_FIRST_PARAM] == DUMP_SIMULATE_SENSOR) {
193         if (argsInStr[DUMP_SECOND_PARAM] == "--repeat") {
194             StartPeriodlyMotionDetection();
195             handler_->PostTask([sleepState = shared_from_this()]() {
196                 STANDBYSERVICE_LOGD("after 100ms, stop sensor");
197                 sleepState->stateManager_.lock()->EndEvalCurrentState(false);
198                 }, DUMP_REPEAT_DETECTION_TIMEOUT);
199             result += "finished start repeated sensor\n";
200         }
201     }
202 }
203 
CheckScrenOffHalfHour()204 void SleepState::CheckScrenOffHalfHour()
205 {
206     auto stateManagerPtr = stateManager_.lock();
207     if (!stateManagerPtr) {
208         STANDBYSERVICE_LOGW("state manager is nullptr, cannot begin screen off half hour");
209         return;
210     }
211     if (MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs() -
212         stateManagerPtr->GetScreenOffTimeStamp() >= HALF_HOUR) {
213         stateManagerPtr->OnScreenOffHalfHour(true, false);
214     }
215 }
216 
IsInFinalPhase()217 bool SleepState::IsInFinalPhase()
218 {
219     return curPhase_ == SleepStatePhase::END;
220 }
221 }  // namespace DevStandbyMgr
222 }  // namespace OHOS