1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "SystemSuspend.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/strings.h>
22 #include <fcntl.h>
23 #include <hidl/Status.h>
24 #include <hwbinder/IPCThreadState.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 
28 #include <string>
29 #include <thread>
30 
31 using ::android::base::Error;
32 using ::android::base::ReadFdToString;
33 using ::android::base::WriteStringToFd;
34 using ::android::hardware::Void;
35 using ::std::string;
36 
37 namespace android {
38 namespace system {
39 namespace suspend {
40 namespace V1_0 {
41 
42 struct SuspendTime {
43     std::chrono::nanoseconds suspendOverhead;
44     std::chrono::nanoseconds suspendTime;
45 };
46 
47 static const char kSleepState[] = "mem";
48 // TODO(b/128923994): we only need /sys/power/wake_[un]lock to export debugging info via
49 // /sys/kernel/debug/wakeup_sources.
50 static constexpr char kSysPowerWakeLock[] = "/sys/power/wake_lock";
51 static constexpr char kSysPowerWakeUnlock[] = "/sys/power/wake_unlock";
52 static constexpr char kUnknownWakeup[] = "unknown";
53 
54 // This function assumes that data in fd is small enough that it can be read in one go.
55 // We use this function instead of the ones available in libbase because it doesn't block
56 // indefinitely when reading from socket streams which are used for testing.
readFd(int fd)57 string readFd(int fd) {
58     char buf[BUFSIZ];
59     ssize_t n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)));
60     if (n < 0) return "";
61     return string{buf, static_cast<size_t>(n)};
62 }
63 
getCallingPid()64 static inline int getCallingPid() {
65     return ::android::hardware::IPCThreadState::self()->getCallingPid();
66 }
67 
readWakeupReasons(int fd)68 static std::vector<std::string> readWakeupReasons(int fd) {
69     std::vector<std::string> wakeupReasons;
70     std::string reasonlines;
71 
72     lseek(fd, 0, SEEK_SET);
73     if (!ReadFdToString(fd, &reasonlines)) {
74         LOG(ERROR) << "failed to read wakeup reasons";
75         // Return unknown wakeup reason if we fail to read
76         return {kUnknownWakeup};
77     }
78 
79     std::stringstream ss(reasonlines);
80     for (std::string reasonline; std::getline(ss, reasonline);) {
81         reasonline = ::android::base::Trim(reasonline);
82 
83         // Only include non-empty reason lines
84         if (!reasonline.empty()) {
85             wakeupReasons.push_back(reasonline);
86         }
87     }
88 
89     // Empty wakeup reason found. Record as unknown wakeup
90     if (wakeupReasons.empty()) {
91         wakeupReasons.push_back(kUnknownWakeup);
92     }
93 
94     return wakeupReasons;
95 }
96 
97 // reads the suspend overhead and suspend time
98 // Returns 0s if reading the sysfs node fails (unlikely)
readSuspendTime(int fd)99 static struct SuspendTime readSuspendTime(int fd) {
100     std::string content;
101 
102     lseek(fd, 0, SEEK_SET);
103     if (!ReadFdToString(fd, &content)) {
104         LOG(ERROR) << "failed to read suspend time";
105         return {0ns, 0ns};
106     }
107 
108     double suspendOverhead, suspendTime;
109     std::stringstream ss(content);
110     if (!(ss >> suspendOverhead) || !(ss >> suspendTime)) {
111         LOG(ERROR) << "failed to parse suspend time " << content;
112         return {0ns, 0ns};
113     }
114 
115     return {std::chrono::duration_cast<std::chrono::nanoseconds>(
116                 std::chrono::duration<double>(suspendOverhead)),
117             std::chrono::duration_cast<std::chrono::nanoseconds>(
118                 std::chrono::duration<double>(suspendTime))};
119 }
120 
WakeLock(SystemSuspend * systemSuspend,const string & name,int pid)121 WakeLock::WakeLock(SystemSuspend* systemSuspend, const string& name, int pid)
122     : mReleased(), mSystemSuspend(systemSuspend), mName(name), mPid(pid) {
123     mSystemSuspend->incSuspendCounter(mName);
124 }
125 
~WakeLock()126 WakeLock::~WakeLock() {
127     releaseOnce();
128 }
129 
release()130 Return<void> WakeLock::release() {
131     releaseOnce();
132     return Void();
133 }
134 
releaseOnce()135 void WakeLock::releaseOnce() {
136     std::call_once(mReleased, [this]() {
137         mSystemSuspend->decSuspendCounter(mName);
138         mSystemSuspend->updateWakeLockStatOnRelease(mName, mPid, getTimeNow());
139     });
140 }
141 
SystemSuspend(unique_fd wakeupCountFd,unique_fd stateFd,unique_fd suspendStatsFd,size_t maxStatsEntries,unique_fd kernelWakelockStatsFd,unique_fd wakeupReasonsFd,unique_fd suspendTimeFd,const SleepTimeConfig & sleepTimeConfig,const sp<SuspendControlService> & controlService,const sp<SuspendControlServiceInternal> & controlServiceInternal,bool useSuspendCounter)142 SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, unique_fd suspendStatsFd,
143                              size_t maxStatsEntries, unique_fd kernelWakelockStatsFd,
144                              unique_fd wakeupReasonsFd, unique_fd suspendTimeFd,
145                              const SleepTimeConfig& sleepTimeConfig,
146                              const sp<SuspendControlService>& controlService,
147                              const sp<SuspendControlServiceInternal>& controlServiceInternal,
148                              bool useSuspendCounter)
149     : mSuspendCounter(0),
150       mWakeupCountFd(std::move(wakeupCountFd)),
151       mStateFd(std::move(stateFd)),
152       mSuspendStatsFd(std::move(suspendStatsFd)),
153       mSuspendTimeFd(std::move(suspendTimeFd)),
154       kSleepTimeConfig(sleepTimeConfig),
155       mSleepTime(sleepTimeConfig.baseSleepTime),
156       mNumConsecutiveBadSuspends(0),
157       mControlService(controlService),
158       mControlServiceInternal(controlServiceInternal),
159       mStatsList(maxStatsEntries, std::move(kernelWakelockStatsFd)),
160       mWakeupList(maxStatsEntries),
161       mUseSuspendCounter(useSuspendCounter),
162       mWakeLockFd(-1),
163       mWakeUnlockFd(-1),
164       mWakeupReasonsFd(std::move(wakeupReasonsFd)) {
165     mControlServiceInternal->setSuspendService(this);
166 
167     if (!mUseSuspendCounter) {
168         mWakeLockFd.reset(TEMP_FAILURE_RETRY(open(kSysPowerWakeLock, O_CLOEXEC | O_RDWR)));
169         if (mWakeLockFd < 0) {
170             PLOG(ERROR) << "error opening " << kSysPowerWakeLock;
171         }
172         mWakeUnlockFd.reset(TEMP_FAILURE_RETRY(open(kSysPowerWakeUnlock, O_CLOEXEC | O_RDWR)));
173         if (mWakeUnlockFd < 0) {
174             PLOG(ERROR) << "error opening " << kSysPowerWakeUnlock;
175         }
176     }
177 }
178 
enableAutosuspend()179 bool SystemSuspend::enableAutosuspend() {
180     if (mAutosuspendEnabled.test_and_set()) {
181         LOG(ERROR) << "Autosuspend already started.";
182         return false;
183     }
184 
185     initAutosuspend();
186     return true;
187 }
188 
forceSuspend()189 bool SystemSuspend::forceSuspend() {
190     //  We are forcing the system to suspend. This particular call ignores all
191     //  existing wakelocks (full or partial). It does not cancel the wakelocks
192     //  or reset mSuspendCounter, it just ignores them.  When the system
193     //  returns from suspend, the wakelocks and SuspendCounter will not have
194     //  changed.
195     auto counterLock = std::unique_lock(mCounterLock);
196     bool success = WriteStringToFd(kSleepState, mStateFd);
197     counterLock.unlock();
198 
199     if (!success) {
200         PLOG(VERBOSE) << "error writing to /sys/power/state for forceSuspend";
201     }
202     return success;
203 }
204 
acquireWakeLock(WakeLockType,const hidl_string & name)205 Return<sp<IWakeLock>> SystemSuspend::acquireWakeLock(WakeLockType /* type */,
206                                                      const hidl_string& name) {
207     auto pid = getCallingPid();
208     auto timeNow = getTimeNow();
209     IWakeLock* wl = new WakeLock{this, name, pid};
210     mControlService->notifyWakelock(name, true);
211     mStatsList.updateOnAcquire(name, pid, timeNow);
212     return wl;
213 }
214 
incSuspendCounter(const string & name)215 void SystemSuspend::incSuspendCounter(const string& name) {
216     auto l = std::lock_guard(mCounterLock);
217     if (mUseSuspendCounter) {
218         mSuspendCounter++;
219     } else {
220         if (!WriteStringToFd(name, mWakeLockFd)) {
221             PLOG(ERROR) << "error writing " << name << " to " << kSysPowerWakeLock;
222         }
223     }
224 }
225 
decSuspendCounter(const string & name)226 void SystemSuspend::decSuspendCounter(const string& name) {
227     auto l = std::lock_guard(mCounterLock);
228     if (mUseSuspendCounter) {
229         if (--mSuspendCounter == 0) {
230             mCounterCondVar.notify_one();
231         }
232     } else {
233         if (!WriteStringToFd(name, mWakeUnlockFd)) {
234             PLOG(ERROR) << "error writing " << name << " to " << kSysPowerWakeUnlock;
235         }
236     }
237 }
238 
initAutosuspend()239 void SystemSuspend::initAutosuspend() {
240     std::thread autosuspendThread([this] {
241         while (true) {
242             std::this_thread::sleep_for(mSleepTime);
243             lseek(mWakeupCountFd, 0, SEEK_SET);
244             const string wakeupCount = readFd(mWakeupCountFd);
245             if (wakeupCount.empty()) {
246                 PLOG(ERROR) << "error reading from /sys/power/wakeup_count";
247                 continue;
248             }
249 
250             auto counterLock = std::unique_lock(mCounterLock);
251             mCounterCondVar.wait(counterLock, [this] { return mSuspendCounter == 0; });
252             // The mutex is locked and *MUST* remain locked until we write to /sys/power/state.
253             // Otherwise, a WakeLock might be acquired after we check mSuspendCounter and before we
254             // write to /sys/power/state.
255 
256             if (!WriteStringToFd(wakeupCount, mWakeupCountFd)) {
257                 PLOG(VERBOSE) << "error writing from /sys/power/wakeup_count";
258                 continue;
259             }
260             bool success = WriteStringToFd(kSleepState, mStateFd);
261             counterLock.unlock();
262 
263             if (!success) {
264                 PLOG(VERBOSE) << "error writing to /sys/power/state";
265             }
266 
267             struct SuspendTime suspendTime = readSuspendTime(mSuspendTimeFd);
268             updateSleepTime(success, suspendTime);
269 
270             std::vector<std::string> wakeupReasons = readWakeupReasons(mWakeupReasonsFd);
271             mWakeupList.update(wakeupReasons);
272 
273             mControlService->notifyWakeup(success, wakeupReasons);
274         }
275     });
276     autosuspendThread.detach();
277     LOG(INFO) << "automatic system suspend enabled";
278 }
279 
280 /**
281  * Updates sleep time depending on the result of suspend attempt.
282  * Time (in milliseconds) between suspend attempts is described the formula
283  * t[n] = { B, 0 < n <= N
284  *        { min(B * (S**(n - N)), M), n > N
285  * where:
286  *   n is the number of consecutive bad suspend attempts,
287  *   B = kBaseSleepTime,
288  *   N = kSuspendBackoffThreshold,
289  *   S = kSleepTimeScaleFactor,
290  *   M = kMaxSleepTime
291  *
292  * kFailedSuspendBackoffEnabled determines whether a failed suspend is counted as a bad suspend
293  *
294  * kShortSuspendBackoffEnabled determines whether a suspend whose duration
295  * t < kShortSuspendThreshold is counted as a bad suspend
296  */
updateSleepTime(bool success,const struct SuspendTime & suspendTime)297 void SystemSuspend::updateSleepTime(bool success, const struct SuspendTime& suspendTime) {
298     std::scoped_lock lock(mSuspendInfoLock);
299     mSuspendInfo.suspendAttemptCount++;
300     mSuspendInfo.sleepTimeMillis +=
301         std::chrono::round<std::chrono::milliseconds>(mSleepTime).count();
302 
303     bool shortSuspend = success && (suspendTime.suspendTime > 0ns) &&
304                         (suspendTime.suspendTime < kSleepTimeConfig.shortSuspendThreshold);
305 
306     bool badSuspend = (kSleepTimeConfig.failedSuspendBackoffEnabled && !success) ||
307                       (kSleepTimeConfig.shortSuspendBackoffEnabled && shortSuspend);
308 
309     auto suspendTimeMillis =
310         std::chrono::round<std::chrono::milliseconds>(suspendTime.suspendTime).count();
311     auto suspendOverheadMillis =
312         std::chrono::round<std::chrono::milliseconds>(suspendTime.suspendOverhead).count();
313 
314     if (success) {
315         mSuspendInfo.suspendOverheadTimeMillis += suspendOverheadMillis;
316         mSuspendInfo.suspendTimeMillis += suspendTimeMillis;
317     } else {
318         mSuspendInfo.failedSuspendCount++;
319         mSuspendInfo.failedSuspendOverheadTimeMillis += suspendOverheadMillis;
320     }
321 
322     if (shortSuspend) {
323         mSuspendInfo.shortSuspendCount++;
324         mSuspendInfo.shortSuspendTimeMillis += suspendTimeMillis;
325     }
326 
327     if (!badSuspend) {
328         mNumConsecutiveBadSuspends = 0;
329         mSleepTime = kSleepTimeConfig.baseSleepTime;
330         return;
331     }
332 
333     // Suspend attempt was bad (failed or short suspend)
334     if (mNumConsecutiveBadSuspends >= kSleepTimeConfig.backoffThreshold) {
335         if (mNumConsecutiveBadSuspends == kSleepTimeConfig.backoffThreshold) {
336             mSuspendInfo.newBackoffCount++;
337         } else {
338             mSuspendInfo.backoffContinueCount++;
339         }
340 
341         mSleepTime = std::min(std::chrono::round<std::chrono::milliseconds>(
342                                   mSleepTime * kSleepTimeConfig.sleepTimeScaleFactor),
343                               kSleepTimeConfig.maxSleepTime);
344     }
345 
346     mNumConsecutiveBadSuspends++;
347 }
348 
updateWakeLockStatOnRelease(const std::string & name,int pid,TimestampType timeNow)349 void SystemSuspend::updateWakeLockStatOnRelease(const std::string& name, int pid,
350                                                 TimestampType timeNow) {
351     mControlService->notifyWakelock(name, false);
352     mStatsList.updateOnRelease(name, pid, timeNow);
353 }
354 
getStatsList() const355 const WakeLockEntryList& SystemSuspend::getStatsList() const {
356     return mStatsList;
357 }
358 
updateStatsNow()359 void SystemSuspend::updateStatsNow() {
360     mStatsList.updateNow();
361 }
362 
getSuspendInfo(SuspendInfo * info)363 void SystemSuspend::getSuspendInfo(SuspendInfo* info) {
364     std::scoped_lock lock(mSuspendInfoLock);
365 
366     *info = mSuspendInfo;
367 }
368 
getWakeupList() const369 const WakeupList& SystemSuspend::getWakeupList() const {
370     return mWakeupList;
371 }
372 
373 /**
374  * Returns suspend stats.
375  */
getSuspendStats()376 Result<SuspendStats> SystemSuspend::getSuspendStats() {
377     SuspendStats stats;
378     std::unique_ptr<DIR, decltype(&closedir)> dp(fdopendir(dup(mSuspendStatsFd.get())), &closedir);
379     if (!dp) {
380         return stats;
381     }
382 
383     // rewinddir, else subsequent calls will not get any suspend_stats
384     rewinddir(dp.get());
385 
386     struct dirent* de;
387 
388     // Grab a wakelock before reading suspend stats,
389     // to ensure a consistent snapshot.
390     sp<IWakeLock> suspendStatsLock = acquireWakeLock(WakeLockType::PARTIAL, "suspend_stats_lock");
391 
392     while ((de = readdir(dp.get()))) {
393         std::string statName(de->d_name);
394         if ((statName == ".") || (statName == "..")) {
395             continue;
396         }
397 
398         unique_fd statFd{TEMP_FAILURE_RETRY(
399             openat(mSuspendStatsFd.get(), statName.c_str(), O_CLOEXEC | O_RDONLY))};
400         if (statFd < 0) {
401             return Error() << "Failed to open " << statName;
402         }
403 
404         std::string valStr;
405         if (!ReadFdToString(statFd.get(), &valStr)) {
406             return Error() << "Failed to read " << statName;
407         }
408 
409         // Trim newline
410         valStr.erase(std::remove(valStr.begin(), valStr.end(), '\n'), valStr.end());
411 
412         if (statName == "last_failed_dev") {
413             stats.lastFailedDev = valStr;
414         } else if (statName == "last_failed_step") {
415             stats.lastFailedStep = valStr;
416         } else {
417             int statVal = std::stoi(valStr);
418             if (statName == "success") {
419                 stats.success = statVal;
420             } else if (statName == "fail") {
421                 stats.fail = statVal;
422             } else if (statName == "failed_freeze") {
423                 stats.failedFreeze = statVal;
424             } else if (statName == "failed_prepare") {
425                 stats.failedPrepare = statVal;
426             } else if (statName == "failed_suspend") {
427                 stats.failedSuspend = statVal;
428             } else if (statName == "failed_suspend_late") {
429                 stats.failedSuspendLate = statVal;
430             } else if (statName == "failed_suspend_noirq") {
431                 stats.failedSuspendNoirq = statVal;
432             } else if (statName == "failed_resume") {
433                 stats.failedResume = statVal;
434             } else if (statName == "failed_resume_early") {
435                 stats.failedResumeEarly = statVal;
436             } else if (statName == "failed_resume_noirq") {
437                 stats.failedResumeNoirq = statVal;
438             } else if (statName == "last_failed_errno") {
439                 stats.lastFailedErrno = statVal;
440             }
441         }
442     }
443 
444     return stats;
445 }
446 
getSleepTime() const447 std::chrono::milliseconds SystemSuspend::getSleepTime() const {
448     return mSleepTime;
449 }
450 
451 }  // namespace V1_0
452 }  // namespace suspend
453 }  // namespace system
454 }  // namespace android
455