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 static const char kSleepState[] = "mem";
43 // TODO(b/128923994): we only need /sys/power/wake_[un]lock to export debugging info via
44 // /sys/kernel/debug/wakeup_sources.
45 static constexpr char kSysPowerWakeLock[] = "/sys/power/wake_lock";
46 static constexpr char kSysPowerWakeUnlock[] = "/sys/power/wake_unlock";
47 
48 // This function assumes that data in fd is small enough that it can be read in one go.
49 // We use this function instead of the ones available in libbase because it doesn't block
50 // indefinitely when reading from socket streams which are used for testing.
readFd(int fd)51 string readFd(int fd) {
52     char buf[BUFSIZ];
53     ssize_t n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)));
54     if (n < 0) return "";
55     return string{buf, static_cast<size_t>(n)};
56 }
57 
getCallingPid()58 static inline int getCallingPid() {
59     return ::android::hardware::IPCThreadState::self()->getCallingPid();
60 }
61 
WakeLock(SystemSuspend * systemSuspend,const string & name,int pid)62 WakeLock::WakeLock(SystemSuspend* systemSuspend, const string& name, int pid)
63     : mReleased(), mSystemSuspend(systemSuspend), mName(name), mPid(pid) {
64     mSystemSuspend->incSuspendCounter(mName);
65 }
66 
~WakeLock()67 WakeLock::~WakeLock() {
68     releaseOnce();
69 }
70 
release()71 Return<void> WakeLock::release() {
72     releaseOnce();
73     return Void();
74 }
75 
releaseOnce()76 void WakeLock::releaseOnce() {
77     std::call_once(mReleased, [this]() {
78         mSystemSuspend->decSuspendCounter(mName);
79         mSystemSuspend->updateWakeLockStatOnRelease(mName, mPid, getTimeNow());
80     });
81 }
82 
SystemSuspend(unique_fd wakeupCountFd,unique_fd stateFd,unique_fd suspendStatsFd,size_t maxNativeStatsEntries,unique_fd kernelWakelockStatsFd,std::chrono::milliseconds baseSleepTime,const sp<SuspendControlService> & controlService,bool useSuspendCounter)83 SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, unique_fd suspendStatsFd,
84                              size_t maxNativeStatsEntries, unique_fd kernelWakelockStatsFd,
85                              std::chrono::milliseconds baseSleepTime,
86                              const sp<SuspendControlService>& controlService,
87                              bool useSuspendCounter)
88     : mSuspendCounter(0),
89       mWakeupCountFd(std::move(wakeupCountFd)),
90       mStateFd(std::move(stateFd)),
91       mSuspendStatsFd(std::move(suspendStatsFd)),
92       mBaseSleepTime(baseSleepTime),
93       mSleepTime(baseSleepTime),
94       mControlService(controlService),
95       mStatsList(maxNativeStatsEntries, std::move(kernelWakelockStatsFd)),
96       mUseSuspendCounter(useSuspendCounter),
97       mWakeLockFd(-1),
98       mWakeUnlockFd(-1) {
99     mControlService->setSuspendService(this);
100 
101     if (!mUseSuspendCounter) {
102         mWakeLockFd.reset(TEMP_FAILURE_RETRY(open(kSysPowerWakeLock, O_CLOEXEC | O_RDWR)));
103         if (mWakeLockFd < 0) {
104             PLOG(ERROR) << "error opening " << kSysPowerWakeLock;
105         }
106         mWakeUnlockFd.reset(TEMP_FAILURE_RETRY(open(kSysPowerWakeUnlock, O_CLOEXEC | O_RDWR)));
107         if (mWakeUnlockFd < 0) {
108             PLOG(ERROR) << "error opening " << kSysPowerWakeUnlock;
109         }
110     }
111 }
112 
enableAutosuspend()113 bool SystemSuspend::enableAutosuspend() {
114     static bool initialized = false;
115     if (initialized) {
116         LOG(ERROR) << "Autosuspend already started.";
117         return false;
118     }
119 
120     initAutosuspend();
121     initialized = true;
122     return true;
123 }
124 
forceSuspend()125 bool SystemSuspend::forceSuspend() {
126     //  We are forcing the system to suspend. This particular call ignores all
127     //  existing wakelocks (full or partial). It does not cancel the wakelocks
128     //  or reset mSuspendCounter, it just ignores them.  When the system
129     //  returns from suspend, the wakelocks and SuspendCounter will not have
130     //  changed.
131     auto counterLock = std::unique_lock(mCounterLock);
132     bool success = WriteStringToFd(kSleepState, mStateFd);
133     counterLock.unlock();
134 
135     if (!success) {
136         PLOG(VERBOSE) << "error writing to /sys/power/state for forceSuspend";
137     }
138     return success;
139 }
140 
acquireWakeLock(WakeLockType,const hidl_string & name)141 Return<sp<IWakeLock>> SystemSuspend::acquireWakeLock(WakeLockType /* type */,
142                                                      const hidl_string& name) {
143     auto pid = getCallingPid();
144     auto timeNow = getTimeNow();
145     IWakeLock* wl = new WakeLock{this, name, pid};
146     mStatsList.updateOnAcquire(name, pid, timeNow);
147     return wl;
148 }
149 
incSuspendCounter(const string & name)150 void SystemSuspend::incSuspendCounter(const string& name) {
151     auto l = std::lock_guard(mCounterLock);
152     if (mUseSuspendCounter) {
153         mSuspendCounter++;
154     } else {
155         if (!WriteStringToFd(name, mWakeLockFd)) {
156             PLOG(ERROR) << "error writing " << name << " to " << kSysPowerWakeLock;
157         }
158     }
159 }
160 
decSuspendCounter(const string & name)161 void SystemSuspend::decSuspendCounter(const string& name) {
162     auto l = std::lock_guard(mCounterLock);
163     if (mUseSuspendCounter) {
164         if (--mSuspendCounter == 0) {
165             mCounterCondVar.notify_one();
166         }
167     } else {
168         if (!WriteStringToFd(name, mWakeUnlockFd)) {
169             PLOG(ERROR) << "error writing " << name << " to " << kSysPowerWakeUnlock;
170         }
171     }
172 }
173 
initAutosuspend()174 void SystemSuspend::initAutosuspend() {
175     std::thread autosuspendThread([this] {
176         while (true) {
177             std::this_thread::sleep_for(mSleepTime);
178             lseek(mWakeupCountFd, 0, SEEK_SET);
179             const string wakeupCount = readFd(mWakeupCountFd);
180             if (wakeupCount.empty()) {
181                 PLOG(ERROR) << "error reading from /sys/power/wakeup_count";
182                 continue;
183             }
184 
185             auto counterLock = std::unique_lock(mCounterLock);
186             mCounterCondVar.wait(counterLock, [this] { return mSuspendCounter == 0; });
187             // The mutex is locked and *MUST* remain locked until we write to /sys/power/state.
188             // Otherwise, a WakeLock might be acquired after we check mSuspendCounter and before we
189             // write to /sys/power/state.
190 
191             if (!WriteStringToFd(wakeupCount, mWakeupCountFd)) {
192                 PLOG(VERBOSE) << "error writing from /sys/power/wakeup_count";
193                 continue;
194             }
195             bool success = WriteStringToFd(kSleepState, mStateFd);
196             counterLock.unlock();
197 
198             if (!success) {
199                 PLOG(VERBOSE) << "error writing to /sys/power/state";
200             }
201 
202             mControlService->notifyWakeup(success);
203 
204             updateSleepTime(success);
205         }
206     });
207     autosuspendThread.detach();
208     LOG(INFO) << "automatic system suspend enabled";
209 }
210 
updateSleepTime(bool success)211 void SystemSuspend::updateSleepTime(bool success) {
212     static constexpr std::chrono::milliseconds kMaxSleepTime = 1min;
213     if (success) {
214         mSleepTime = mBaseSleepTime;
215         return;
216     }
217     // Double sleep time after each failure up to one minute.
218     mSleepTime = std::min(mSleepTime * 2, kMaxSleepTime);
219 }
220 
updateWakeLockStatOnRelease(const std::string & name,int pid,TimestampType timeNow)221 void SystemSuspend::updateWakeLockStatOnRelease(const std::string& name, int pid,
222                                                 TimestampType timeNow) {
223     mStatsList.updateOnRelease(name, pid, timeNow);
224 }
225 
getStatsList() const226 const WakeLockEntryList& SystemSuspend::getStatsList() const {
227     return mStatsList;
228 }
229 
updateStatsNow()230 void SystemSuspend::updateStatsNow() {
231     mStatsList.updateNow();
232 }
233 
234 /**
235  * Returns suspend stats.
236  */
getSuspendStats()237 Result<SuspendStats> SystemSuspend::getSuspendStats() {
238     SuspendStats stats;
239     std::unique_ptr<DIR, decltype(&closedir)> dp(fdopendir(dup(mSuspendStatsFd.get())), &closedir);
240     if (!dp) {
241         return stats;
242     }
243 
244     // rewinddir, else subsequent calls will not get any suspend_stats
245     rewinddir(dp.get());
246 
247     struct dirent* de;
248 
249     // Grab a wakelock before reading suspend stats,
250     // to ensure a consistent snapshot.
251     sp<IWakeLock> suspendStatsLock = acquireWakeLock(WakeLockType::PARTIAL, "suspend_stats_lock");
252 
253     while ((de = readdir(dp.get()))) {
254         std::string statName(de->d_name);
255         if ((statName == ".") || (statName == "..")) {
256             continue;
257         }
258 
259         unique_fd statFd{TEMP_FAILURE_RETRY(
260             openat(mSuspendStatsFd.get(), statName.c_str(), O_CLOEXEC | O_RDONLY))};
261         if (statFd < 0) {
262             return Error() << "Failed to open " << statName;
263         }
264 
265         std::string valStr;
266         if (!ReadFdToString(statFd.get(), &valStr)) {
267             return Error() << "Failed to read " << statName;
268         }
269 
270         // Trim newline
271         valStr.erase(std::remove(valStr.begin(), valStr.end(), '\n'), valStr.end());
272 
273         if (statName == "last_failed_dev") {
274             stats.lastFailedDev = valStr;
275         } else if (statName == "last_failed_step") {
276             stats.lastFailedStep = valStr;
277         } else {
278             int statVal = std::stoi(valStr);
279             if (statName == "success") {
280                 stats.success = statVal;
281             } else if (statName == "fail") {
282                 stats.fail = statVal;
283             } else if (statName == "failed_freeze") {
284                 stats.failedFreeze = statVal;
285             } else if (statName == "failed_prepare") {
286                 stats.failedPrepare = statVal;
287             } else if (statName == "failed_suspend") {
288                 stats.failedSuspend = statVal;
289             } else if (statName == "failed_suspend_late") {
290                 stats.failedSuspendLate = statVal;
291             } else if (statName == "failed_suspend_noirq") {
292                 stats.failedSuspendNoirq = statVal;
293             } else if (statName == "failed_resume") {
294                 stats.failedResume = statVal;
295             } else if (statName == "failed_resume_early") {
296                 stats.failedResumeEarly = statVal;
297             } else if (statName == "failed_resume_noirq") {
298                 stats.failedResumeNoirq = statVal;
299             } else if (statName == "last_failed_errno") {
300                 stats.lastFailedErrno = statVal;
301             }
302         }
303     }
304 
305     return stats;
306 }
307 
308 }  // namespace V1_0
309 }  // namespace suspend
310 }  // namespace system
311 }  // namespace android
312