• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "suspend/suspend_controller.h"
17 
18 #include <file_ex.h>
19 #include <sys/eventfd.h>
20 
21 #include "power_log.h"
22 
23 namespace OHOS {
24 namespace PowerMgr {
25 namespace Suspend {
26 bool SuspendController::AutoSuspend::started_ = false;
27 
SuspendController()28 SuspendController::SuspendController()
29 {
30     auto f = std::bind(&SuspendController::WaitingSuspendCondition, this);
31     suspend_ = std::make_unique<AutoSuspend>(f);
32 }
33 
AutoSuspendLoop()34 void SuspendController::AutoSuspend::AutoSuspendLoop()
35 {
36     POWER_HILOGD(FEATURE_SUSPEND, "AutoSuspendLoop start");
37     while (true) {
38         std::this_thread::sleep_for(waitTime_);
39         if (!started_) {
40             POWER_HILOGW(FEATURE_SUSPEND, "AutoSuspend is stopped");
41             break;
42         }
43         const std::string wakeupCount = WaitWakeupCount();
44         if (wakeupCount.empty()) {
45             POWER_HILOGD(FEATURE_SUSPEND, "Can't read wake count, continue");
46             continue;
47         }
48         waitingFunc_();
49         if (!WriteWakeupCount(wakeupCount)) {
50             POWER_HILOGD(FEATURE_SUSPEND, "Can't write wake count, continue");
51             continue;
52         }
53         if (onSuspend_ != nullptr) {
54             onSuspend_();
55         }
56         bool success = SuspendEnter();
57         if (!success) {
58             POWER_HILOGE(FEATURE_SUSPEND, "Start suspend failed");
59         }
60         if (onWakeup_ != nullptr) {
61             onWakeup_();
62         }
63         break;
64     }
65     started_ = false;
66 
67     POWER_HILOGD(FEATURE_SUSPEND, "AutoSuspendLoop end");
68 }
69 
Start(SuspendCallback onSuspend,SuspendCallback onWakeup)70 void SuspendController::AutoSuspend::Start(SuspendCallback onSuspend, SuspendCallback onWakeup)
71 {
72     POWER_HILOGD(FEATURE_SUSPEND, "AutoSuspend Start");
73     onSuspend_ = onSuspend;
74     onWakeup_ = onWakeup;
75     if (started_) {
76         POWER_HILOGW(FEATURE_SUSPEND, "AutoSuspend is already started");
77         return;
78     }
79     daemon_ = std::make_unique<std::thread>(&AutoSuspend::AutoSuspendLoop, this);
80     daemon_->detach();
81     POWER_HILOGD(FEATURE_SUSPEND, "AutoSuspend Start detach");
82     started_ = true;
83 }
84 
Stop()85 void SuspendController::AutoSuspend::Stop()
86 {
87     POWER_HILOGD(FEATURE_SUSPEND, "AutoSuspend Stop");
88     if (started_ && daemon_.get() != nullptr) {
89         POWER_HILOGD(FEATURE_SUSPEND, "daemon join start");
90         started_ = false;
91         daemon_->join();
92         POWER_HILOGD(FEATURE_SUSPEND, "daemon join end");
93     }
94 }
95 
SuspendEnter()96 bool SuspendController::AutoSuspend::SuspendEnter()
97 {
98     static bool inited = false;
99     static UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
100     if (!inited) {
101         if (suspendStateFd < 0) {
102             POWER_HILOGE(FEATURE_SUSPEND, "Failed to open the suspending state fd");
103             return false;
104         }
105         inited = true;
106     }
107     POWER_HILOGD(FEATURE_SUSPEND, "Before suspend");
108     bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
109     POWER_HILOGD(FEATURE_SUSPEND, "After suspend");
110     if (!ret) {
111         POWER_HILOGE(FEATURE_SUSPEND, "Failed to write the suspending state");
112     }
113     return ret;
114 }
115 
WaitWakeupCount()116 std::string SuspendController::AutoSuspend::WaitWakeupCount()
117 {
118     if (wakeupCountFd < 0) {
119         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
120     }
121     std::string wakeupCount;
122     bool ret = LoadStringFromFd(wakeupCountFd, wakeupCount);
123     if (!ret) {
124         POWER_HILOGW(FEATURE_SUSPEND, "Read wakeup count failed");
125         return std::string();
126     }
127     return wakeupCount;
128 }
129 
WriteWakeupCount(std::string wakeupCount)130 bool SuspendController::AutoSuspend::WriteWakeupCount(std::string wakeupCount)
131 {
132     if (wakeupCountFd < 0) {
133         return false;
134     }
135     bool ret = SaveStringToFd(wakeupCountFd, wakeupCount.c_str());
136     if (!ret) {
137         POWER_HILOGE(FEATURE_SUSPEND, "Failed to write the wakeup count");
138     }
139     return ret;
140 }
141 
Suspend(SuspendCallback onSuspend,SuspendCallback onWakeup,bool force)142 void SuspendController::Suspend(SuspendCallback onSuspend, SuspendCallback onWakeup, bool force)
143 {
144     if (force) {
145         POWER_HILOGI(FEATURE_SUSPEND, "SuspendController Suspend: force");
146         if (onSuspend != nullptr) {
147             onSuspend();
148         }
149         suspend_->SuspendEnter();
150         if (onWakeup != nullptr) {
151             onWakeup();
152         }
153     } else {
154         POWER_HILOGI(FEATURE_SUSPEND, "SuspendController Suspend: not force");
155         suspend_->Start(onSuspend, onWakeup);
156     }
157 }
158 
Wakeup()159 void SuspendController::Wakeup()
160 {
161     suspend_->Stop();
162 }
163 
IncSuspendBlockCounter()164 void SuspendController::IncSuspendBlockCounter()
165 {
166     std::lock_guard lock(suspendMutex_);
167     suspendBlockCounter_++;
168     POWER_HILOGD(FEATURE_SUSPEND, "Running Lock Counter = %{public}d", suspendBlockCounter_);
169 }
170 
DecSuspendBlockCounter()171 void SuspendController::DecSuspendBlockCounter()
172 {
173     std::lock_guard lock(suspendMutex_);
174     suspendBlockCounter_--;
175     POWER_HILOGD(FEATURE_SUSPEND, "Running Lock Counter = %{public}d", suspendBlockCounter_);
176     if (SuspendConditionSatisfied()) {
177         suspendCv_.notify_one();
178     }
179 }
180 
SuspendConditionSatisfied()181 bool SuspendController::SuspendConditionSatisfied()
182 {
183     return suspendBlockCounter_ == 0;
184 }
185 
WaitingSuspendCondition()186 void SuspendController::WaitingSuspendCondition()
187 {
188     auto suspendLock = std::unique_lock(suspendMutex_);
189     suspendCv_.wait(suspendLock, [this] { return this->SuspendConditionSatisfied(); });
190 }
191 } // namespace Suspend
192 } // namespace PowerMgr
193 } // namespace OHOS
194