1  /*
2   * Copyright (c) 2023-2024 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 "base_state.h"
17  
18  #include "time_service_client.h"
19  
20  #include "standby_messsage.h"
21  #include "standby_service_log.h"
22  #include "standby_config_manager.h"
23  
24  #include "istate_manager_adapter.h"
25  #include "timed_task.h"
26  #include "time_provider.h"
27  #include "standby_service_impl.h"
28  #include "standby_config_manager.h"
29  
30  using namespace OHOS::MiscServices;
31  namespace OHOS {
32  namespace DevStandbyMgr {
33  #ifdef STANDBY_POWER_MANAGER_ENABLE
34  std::shared_ptr<PowerMgr::RunningLock> BaseState::standbyRunningLock_ = nullptr;
35  const int32_t RUNNINGLOCK_TIMEOUT = 5000;
36  #endif
37  bool BaseState::runningLockStatus_ = false;
38  
Init(const std::shared_ptr<BaseState> & statePtr)39  ErrCode BaseState::Init(const std::shared_ptr<BaseState>& statePtr)
40  {
41      auto callbackTask = [statePtr]() { statePtr->StartTransitNextState(statePtr); };
42      enterStandbyTimerId_ = TimedTask::CreateTimer(false, 0, true, false, callbackTask);
43      if (enterStandbyTimerId_ == 0) {
44          STANDBYSERVICE_LOGE("%{public}s state init failed", STATE_NAME_LIST[GetCurState()].c_str());
45          return ERR_STANDBY_STATE_INIT_FAILED;
46      }
47      return ERR_OK;
48  }
49  
UnInit()50  ErrCode BaseState::UnInit()
51  {
52      DestroyAllTimedTask();
53      enterStandbyTimerId_ = 0;
54      return ERR_OK;
55  }
56  
GetCurState()57  uint32_t BaseState::GetCurState()
58  {
59      return curState_;
60  }
61  
GetCurInnerPhase()62  uint32_t BaseState::GetCurInnerPhase()
63  {
64      return curPhase_;
65  }
66  
StartTransitNextState(const std::shared_ptr<BaseState> & statePtr)67  void BaseState::StartTransitNextState(const std::shared_ptr<BaseState>& statePtr)
68  {
69      handler_->PostTask([statePtr]() {
70          STANDBYSERVICE_LOGD("due to timeout, try to enter %{public}s state from %{public}s",
71              STATE_NAME_LIST[statePtr->nextState_].c_str(), STATE_NAME_LIST[statePtr->curState_].c_str());
72          BaseState::AcquireStandbyRunningLock();
73          auto stateManagerPtr = statePtr->stateManager_.lock();
74          if (!stateManagerPtr) {
75              STANDBYSERVICE_LOGW("state manager is nullptr, can not transit to next state");
76              BaseState::ReleaseStandbyRunningLock();
77              return;
78          }
79          if (stateManagerPtr->IsEvalution()) {
80              STANDBYSERVICE_LOGW("state is in evalution, stop evalution and enter next state");
81              stateManagerPtr->StopEvalution();
82          }
83          if (stateManagerPtr->TransitToState(statePtr->nextState_) != ERR_OK) {
84              STANDBYSERVICE_LOGW("can not transit to state %{public}d, block current state", statePtr->nextState_);
85              stateManagerPtr->BlockCurrentState();
86              BaseState::ReleaseStandbyRunningLock();
87          }
88          }, TRANSIT_NEXT_STATE_TIMED_TASK);
89  }
90  
TransitToPhase(uint32_t curPhase,uint32_t nextPhase)91  void BaseState::TransitToPhase(uint32_t curPhase, uint32_t nextPhase)
92  {
93      ConstraintEvalParam params{curState_, curPhase, curState_, nextPhase};
94      stateManager_.lock()->StartEvalCurrentState(params);
95  }
96  
TransitToPhaseInner(uint32_t prePhase,uint32_t curPhase)97  void BaseState::TransitToPhaseInner(uint32_t prePhase, uint32_t curPhase)
98  {
99      auto stateManagerPtr = stateManager_.lock();
100      if (!stateManagerPtr) {
101          STANDBYSERVICE_LOGW("state manager is nullptr, can not implement function to enter next phase");
102          return;
103      }
104      StandbyMessage message(StandbyMessageType::PHASE_TRANSIT);
105      message.want_ = AAFwk::Want{};
106      message.want_->SetParam(CURRENT_STATE, static_cast<int32_t>(curState_));
107      message.want_->SetParam(PREVIOUS_PHASE, static_cast<int32_t>(prePhase));
108      message.want_->SetParam(CURRENT_PHASE, static_cast<int32_t>(curPhase));
109      StandbyServiceImpl::GetInstance()->DispatchEvent(message);
110      STANDBYSERVICE_LOGI("phase transit succeed, phase form %{public}d to %{public}d",
111          static_cast<int32_t>(prePhase), static_cast<int32_t>(curPhase));
112  }
113  
IsInFinalPhase()114  bool BaseState::IsInFinalPhase()
115  {
116      return true;
117  }
118  
OnStateBlocked()119  void BaseState::OnStateBlocked()
120  {}
121  
SetTimedTask(const std::string & timedTaskName,uint64_t timedTaskId)122  void BaseState::SetTimedTask(const std::string& timedTaskName, uint64_t timedTaskId)
123  {
124      if (auto iter = timedTaskMap_.find(timedTaskName); iter == timedTaskMap_.end()) {
125          timedTaskMap_.emplace(timedTaskName, timedTaskId);
126      } else {
127          iter->second = timedTaskId;
128      }
129  }
130  
StartStateTransitionTimer(int64_t triggerTime)131  ErrCode BaseState::StartStateTransitionTimer(int64_t triggerTime)
132  {
133      if (enterStandbyTimerId_ == 0 || !MiscServices::TimeServiceClient::GetInstance()->
134          StartTimer(enterStandbyTimerId_, MiscServices::TimeServiceClient::GetInstance()->
135          GetWallTimeMs() + triggerTime)) {
136          STANDBYSERVICE_LOGE("%{public}s state set timed task failed", STATE_NAME_LIST[nextState_].c_str());
137          return ERR_STANDBY_TIMER_SERVICE_ERROR;
138      }
139  
140      STANDBYSERVICE_LOGD("StartStateTransitionTimer by id=" SPUBI64 ", triggerTime=" SPUBI64,
141          enterStandbyTimerId_, triggerTime);
142      SetTimedTask(TRANSIT_NEXT_STATE_TIMED_TASK, enterStandbyTimerId_);
143      return ERR_OK;
144  }
145  
StopTimedTask(const std::string & timedTaskName)146  ErrCode BaseState::StopTimedTask(const std::string& timedTaskName)
147  {
148      if (auto iter = timedTaskMap_.find(timedTaskName); iter == timedTaskMap_.end()) {
149          STANDBYSERVICE_LOGW("timedTask %{public}s not exist", timedTaskName.c_str());
150          return ERR_STANDBY_TIMERID_NOT_EXIST;
151      } else if (iter->second > 0) {
152          MiscServices::TimeServiceClient::GetInstance()->StopTimer(iter->second);
153      }
154  
155      return ERR_OK;
156  }
157  
DestroyAllTimedTask()158  void BaseState::DestroyAllTimedTask()
159  {
160      for (auto& [timeTaskName, timerId] : timedTaskMap_) {
161          handler_->RemoveTask(timeTaskName);
162          if (timerId > 0) {
163              TimeServiceClient::GetInstance()->StopTimer(timerId);
164              TimeServiceClient::GetInstance()->DestroyTimer(timerId);
165          }
166      }
167      timedTaskMap_.clear();
168  }
169  
InitRunningLock()170  void BaseState::InitRunningLock()
171  {
172      runningLockStatus_ = false;
173  #ifdef STANDBY_POWER_MANAGER_ENABLE
174      standbyRunningLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock(
175          "StandbyRunningLock", PowerMgr::RunningLockType::RUNNINGLOCK_BACKGROUND);
176  #endif
177  }
178  
AcquireStandbyRunningLock()179  void BaseState::AcquireStandbyRunningLock()
180  {
181      if (runningLockStatus_) {
182          return;
183      }
184  #ifdef STANDBY_POWER_MANAGER_ENABLE
185      if (standbyRunningLock_ == nullptr) {
186          standbyRunningLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock(
187              "StandbyRunningLock", PowerMgr::RunningLockType::RUNNINGLOCK_BACKGROUND);
188      }
189      if (standbyRunningLock_ != nullptr) {
190          standbyRunningLock_->Lock(RUNNINGLOCK_TIMEOUT);
191      }
192  #endif
193      runningLockStatus_ = true;
194      STANDBYSERVICE_LOGD("acquire standby running lock, status is %{public}d", runningLockStatus_);
195  }
196  
ReleaseStandbyRunningLock()197  void BaseState::ReleaseStandbyRunningLock()
198  {
199      if (!runningLockStatus_) {
200          return;
201      }
202  #ifdef STANDBY_POWER_MANAGER_ENABLE
203      if (standbyRunningLock_ == nullptr) {
204          STANDBYSERVICE_LOGE("standbyRunningLock_ is nullptr");
205      } else {
206          standbyRunningLock_->UnLock();
207      }
208  #endif
209      runningLockStatus_ = false;
210      STANDBYSERVICE_LOGD("release standby running lock, status is %{public}d", runningLockStatus_);
211  }
212  
ShellDump(const std::vector<std::string> & argsInStr,std::string & result)213  void BaseState::ShellDump(const std::vector<std::string>& argsInStr, std::string& result)
214  {
215      return;
216  }
217  
CalculateMaintTimeOut(const std::shared_ptr<IStateManagerAdapter> & stateManagerPtr,bool isFirstInterval)218  int64_t StateWithMaint::CalculateMaintTimeOut(const std::shared_ptr<IStateManagerAdapter>& stateManagerPtr,
219      bool isFirstInterval)
220  {
221      int64_t maintIntervalTimeOut {0};
222      auto mainIntervalSize = static_cast<int32_t>(maintInterval_.size());
223      if (mainIntervalSize <= 0) {
224          STANDBYSERVICE_LOGE("maintenance interval config error, can not enter maintence state");
225          return 0;
226      }
227      if (isFirstInterval) {
228          maintIntervalTimeOut = maintInterval_[maintIntervalIndex_];
229      } else {
230          maintIntervalIndex_ = std::min(maintIntervalIndex_ + 1, mainIntervalSize - 1);
231          maintIntervalTimeOut =  maintInterval_[maintIntervalIndex_];
232      }
233      int64_t timeDiff {0};
234      if (TimeProvider::GetCondition(maintIntervalTimeOut) == ConditionType::NIGHT_STANDBY &&
235          TimeProvider::TimeDiffToDayNightSwitch(timeDiff)) {
236          maintIntervalTimeOut *= TimeConstant::MSEC_PER_SEC;
237          maintIntervalTimeOut += timeDiff;
238          return maintIntervalTimeOut;
239      }
240      maintIntervalTimeOut *= TimeConstant::MSEC_PER_SEC;
241      return maintIntervalTimeOut;
242  }
243  }  // namespace DevStandbyMgr
244  }  // namespace OHOS