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 <android-base/file.h>
18 #include <android-base/logging.h>
19 #include <android-base/result.h>
20 #include <android-base/unique_fd.h>
21 #include <android/system/suspend/BnSuspendCallback.h>
22 #include <binder/IPCThreadState.h>
23 #include <binder/IServiceManager.h>
24 #include <binder/ProcessState.h>
25 #include <cutils/native_handle.h>
26 #include <ftw.h>
27 #include <gmock/gmock.h>
28 #include <gtest/gtest.h>
29 #include <hidl/HidlTransportSupport.h>
30 #include <sys/poll.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 
34 #include <chrono>
35 #include <cmath>
36 #include <csignal>
37 #include <cstdlib>
38 #include <future>
39 #include <string>
40 #include <thread>
41 
42 #include "SuspendControlService.h"
43 #include "SystemSuspend.h"
44 
45 using android::sp;
46 using android::base::Result;
47 using android::base::Socketpair;
48 using android::base::unique_fd;
49 using android::base::WriteStringToFd;
50 using android::hardware::configureRpcThreadpool;
51 using android::hardware::joinRpcThreadpool;
52 using android::hardware::Return;
53 using android::hardware::Void;
54 using android::system::suspend::BnSuspendCallback;
55 using android::system::suspend::ISuspendControlService;
56 using android::system::suspend::WakeLockInfo;
57 using android::system::suspend::V1_0::getTimeNow;
58 using android::system::suspend::V1_0::ISystemSuspend;
59 using android::system::suspend::V1_0::IWakeLock;
60 using android::system::suspend::V1_0::readFd;
61 using android::system::suspend::V1_0::SuspendControlService;
62 using android::system::suspend::V1_0::SuspendStats;
63 using android::system::suspend::V1_0::SystemSuspend;
64 using android::system::suspend::V1_0::TimestampType;
65 using android::system::suspend::V1_0::WakeLockType;
66 using namespace std::chrono_literals;
67 
68 namespace android {
69 
70 static constexpr char kServiceName[] = "TestService";
71 static constexpr char kControlServiceName[] = "TestControlService";
72 
isReadBlocked(int fd,int timeout_ms=20)73 static bool isReadBlocked(int fd, int timeout_ms = 20) {
74     struct pollfd pfd {
75         .fd = fd, .events = POLLIN,
76     };
77     return poll(&pfd, 1, timeout_ms) == 0;
78 }
79 
80 class SystemSuspendTest : public ::testing::Test {
81    protected:
registerTestService()82     static void registerTestService() {
83         std::thread testService([] {
84             configureRpcThreadpool(1, true /* callerWillJoin */);
85 
86             sp<SuspendControlService> suspendControl = new SuspendControlService();
87             auto controlStatus = ::android::defaultServiceManager()->addService(
88                 android::String16(kControlServiceName), suspendControl);
89             if (android::OK != controlStatus) {
90                 LOG(FATAL) << "Unable to register service " << kControlServiceName << controlStatus;
91             }
92 
93             // Create non-HW binder threadpool for SuspendControlService.
94             sp<android::ProcessState> ps{android::ProcessState::self()};
95             ps->startThreadPool();
96 
97             sp<ISystemSuspend> suspend = new SystemSuspend(
98                 std::move(wakeupCountFds[1]), std::move(stateFds[1]),
99                 unique_fd(-1) /*suspendStatsFd*/, 1 /* maxNativeStatsEntries */,
100                 unique_fd(-1) /* kernelWakelockStatsFd */, 0ms /* baseSleepTime */, suspendControl);
101             status_t status = suspend->registerAsService(kServiceName);
102             if (android::OK != status) {
103                 LOG(FATAL) << "Unable to register service: " << status;
104             }
105 
106             joinRpcThreadpool();
107         });
108         testService.detach();
109     }
110 
SetUpTestSuite()111     static void SetUpTestSuite() {
112         Socketpair(SOCK_STREAM, &wakeupCountFds[0], &wakeupCountFds[1]);
113         Socketpair(SOCK_STREAM, &stateFds[0], &stateFds[1]);
114 
115         registerTestService();
116         ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, kServiceName);
117         sp<ISystemSuspend> suspendService = ISystemSuspend::getService(kServiceName);
118         ASSERT_NE(suspendService, nullptr) << "failed to get suspend service";
119 
120         sp<IBinder> control =
121             android::defaultServiceManager()->getService(android::String16(kControlServiceName));
122         ASSERT_NE(control, nullptr) << "failed to get the suspend control service";
123         sp<ISuspendControlService> controlService = interface_cast<ISuspendControlService>(control);
124 
125         // Start auto-suspend.
126         bool enabled = false;
127         controlService->enableAutosuspend(&enabled);
128         ASSERT_EQ(enabled, true) << "failed to start autosuspend";
129     }
130 
131    public:
SetUp()132     virtual void SetUp() override {
133         ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, kServiceName);
134         suspendService = ISystemSuspend::getService(kServiceName);
135         ASSERT_NE(suspendService, nullptr) << "failed to get suspend service";
136 
137         sp<IBinder> control =
138             android::defaultServiceManager()->getService(android::String16(kControlServiceName));
139         ASSERT_NE(control, nullptr) << "failed to get the suspend control service";
140         controlService = interface_cast<ISuspendControlService>(control);
141 
142         wakeupCountFd = wakeupCountFds[0];
143         stateFd = stateFds[0];
144 
145         // SystemSuspend HAL should not have written back to wakeupCountFd or stateFd yet.
146         ASSERT_TRUE(isReadBlocked(wakeupCountFd));
147         ASSERT_TRUE(isReadBlocked(stateFd));
148     }
149 
TearDown()150     virtual void TearDown() override {
151         if (!isReadBlocked(wakeupCountFd)) readFd(wakeupCountFd);
152         if (!isReadBlocked(stateFd)) readFd(stateFd).empty();
153         ASSERT_TRUE(isReadBlocked(wakeupCountFd));
154         ASSERT_TRUE(isReadBlocked(stateFd));
155     }
156 
unblockSystemSuspendFromWakeupCount()157     void unblockSystemSuspendFromWakeupCount() {
158         std::string wakeupCount = std::to_string(rand());
159         ASSERT_TRUE(WriteStringToFd(wakeupCount, wakeupCountFd));
160     }
161 
isSystemSuspendBlocked(int timeout_ms=20)162     bool isSystemSuspendBlocked(int timeout_ms = 20) { return isReadBlocked(stateFd, timeout_ms); }
163 
acquireWakeLock(const std::string & name="TestLock")164     sp<IWakeLock> acquireWakeLock(const std::string& name = "TestLock") {
165         return suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
166     }
167 
getActiveWakeLockCount()168     size_t getActiveWakeLockCount() {
169         std::vector<WakeLockInfo> wlStats;
170         controlService->getWakeLockStats(&wlStats);
171         return count_if(wlStats.begin(), wlStats.end(), [](auto entry) { return entry.isActive; });
172     }
173 
checkLoop(int numIter)174     void checkLoop(int numIter) {
175         for (int i = 0; i < numIter; i++) {
176             // Mock value for /sys/power/wakeup_count.
177             std::string wakeupCount = std::to_string(rand());
178             ASSERT_TRUE(WriteStringToFd(wakeupCount, wakeupCountFd));
179             ASSERT_EQ(readFd(wakeupCountFd), wakeupCount)
180                 << "wakeup count value written by SystemSuspend is not equal to value given to it";
181             ASSERT_EQ(readFd(stateFd), "mem")
182                 << "SystemSuspend failed to write correct sleep state.";
183         }
184     }
185     sp<ISystemSuspend> suspendService;
186     sp<ISuspendControlService> controlService;
187     static unique_fd wakeupCountFds[2];
188     static unique_fd stateFds[2];
189     static int wakeupCountFd;
190     static int stateFd;
191 };
192 
193 // SystemSuspendTest test suite resources
194 unique_fd SystemSuspendTest::wakeupCountFds[2];
195 unique_fd SystemSuspendTest::stateFds[2];
196 int SystemSuspendTest::wakeupCountFd;
197 int SystemSuspendTest::stateFd;
198 
199 // Tests that autosuspend thread can only be enabled once.
TEST_F(SystemSuspendTest,OnlyOneEnableAutosuspend)200 TEST_F(SystemSuspendTest, OnlyOneEnableAutosuspend) {
201     bool enabled = false;
202     controlService->enableAutosuspend(&enabled);
203     ASSERT_EQ(enabled, false);
204 }
205 
TEST_F(SystemSuspendTest,AutosuspendLoop)206 TEST_F(SystemSuspendTest, AutosuspendLoop) {
207     checkLoop(5);
208 }
209 
210 // Tests that upon WakeLock destruction SystemSuspend HAL is unblocked.
TEST_F(SystemSuspendTest,WakeLockDestructor)211 TEST_F(SystemSuspendTest, WakeLockDestructor) {
212     {
213         sp<IWakeLock> wl = acquireWakeLock();
214         ASSERT_NE(wl, nullptr);
215         unblockSystemSuspendFromWakeupCount();
216         ASSERT_TRUE(isSystemSuspendBlocked());
217     }
218     ASSERT_FALSE(isSystemSuspendBlocked());
219 }
220 
221 // Tests that upon WakeLock::release() SystemSuspend HAL is unblocked.
TEST_F(SystemSuspendTest,WakeLockRelease)222 TEST_F(SystemSuspendTest, WakeLockRelease) {
223     sp<IWakeLock> wl = acquireWakeLock();
224     ASSERT_NE(wl, nullptr);
225     unblockSystemSuspendFromWakeupCount();
226     ASSERT_TRUE(isSystemSuspendBlocked());
227     wl->release();
228     ASSERT_FALSE(isSystemSuspendBlocked());
229 }
230 
231 // Tests that multiple WakeLocks correctly block SystemSuspend HAL.
TEST_F(SystemSuspendTest,MultipleWakeLocks)232 TEST_F(SystemSuspendTest, MultipleWakeLocks) {
233     {
234         sp<IWakeLock> wl1 = acquireWakeLock();
235         ASSERT_NE(wl1, nullptr);
236         ASSERT_TRUE(isSystemSuspendBlocked());
237         unblockSystemSuspendFromWakeupCount();
238         {
239             sp<IWakeLock> wl2 = acquireWakeLock();
240             ASSERT_NE(wl2, nullptr);
241             ASSERT_TRUE(isSystemSuspendBlocked());
242         }
243         ASSERT_TRUE(isSystemSuspendBlocked());
244     }
245     ASSERT_FALSE(isSystemSuspendBlocked());
246 }
247 
248 // Tests that upon thread deallocation WakeLock is destructed and SystemSuspend HAL is unblocked.
TEST_F(SystemSuspendTest,ThreadCleanup)249 TEST_F(SystemSuspendTest, ThreadCleanup) {
250     std::thread clientThread([this] {
251         sp<IWakeLock> wl = acquireWakeLock();
252         ASSERT_NE(wl, nullptr);
253         unblockSystemSuspendFromWakeupCount();
254         ASSERT_TRUE(isSystemSuspendBlocked());
255     });
256     clientThread.join();
257     ASSERT_FALSE(isSystemSuspendBlocked());
258 }
259 
260 // Test that binder driver correctly deallocates acquired WakeLocks, even if the client processs
261 // is terminated without ability to do clean up.
TEST_F(SystemSuspendTest,CleanupOnAbort)262 TEST_F(SystemSuspendTest, CleanupOnAbort) {
263     ASSERT_EXIT(
264         {
265             sp<IWakeLock> wl = acquireWakeLock();
266             ASSERT_NE(wl, nullptr);
267             std::abort();
268         },
269         ::testing::KilledBySignal(SIGABRT), "");
270     ASSERT_TRUE(isSystemSuspendBlocked());
271     unblockSystemSuspendFromWakeupCount();
272     // Timing of the wake lock clean-up after process death is scheduler-dependent.
273     // Increase the timeout to avoid flakes.
274     ASSERT_FALSE(isSystemSuspendBlocked(200));
275 }
276 
277 // Stress test acquiring/releasing WakeLocks.
TEST_F(SystemSuspendTest,WakeLockStressTest)278 TEST_F(SystemSuspendTest, WakeLockStressTest) {
279     // numThreads threads will acquire/release numLocks locks each.
280     constexpr int numThreads = 10;
281     constexpr int numLocks = 10000;
282     std::thread tds[numThreads];
283 
284     for (int i = 0; i < numThreads; i++) {
285         tds[i] = std::thread([this] {
286             for (int j = 0; j < numLocks; j++) {
287                 sp<IWakeLock> wl1 = acquireWakeLock();
288                 sp<IWakeLock> wl2 = acquireWakeLock();
289                 wl2->release();
290             }
291         });
292     }
293     for (int i = 0; i < numThreads; i++) {
294         tds[i].join();
295     }
296     ASSERT_EQ(getActiveWakeLockCount(), 0);
297 }
298 
299 // Callbacks are passed around as sp<>. However, mock expectations are verified when mock objects
300 // are destroyed, i.e. the test needs to control lifetime of the mock object.
301 // MockCallbackImpl can be destroyed independently of its wrapper MockCallback which is passed to
302 // SystemSuspend.
303 struct MockCallbackImpl {
304     MOCK_METHOD1(notifyWakeup, binder::Status(bool));
305 };
306 
307 class MockCallback : public BnSuspendCallback {
308    public:
MockCallback(MockCallbackImpl * impl)309     MockCallback(MockCallbackImpl* impl) : mImpl(impl), mDisabled(false) {}
notifyWakeup(bool x)310     binder::Status notifyWakeup(bool x) {
311         return mDisabled ? binder::Status::ok() : mImpl->notifyWakeup(x);
312     }
313     // In case we pull the rug from under MockCallback, but SystemSuspend still has an sp<> to the
314     // object.
disable()315     void disable() { mDisabled = true; }
316 
317    private:
318     MockCallbackImpl* mImpl;
319     bool mDisabled;
320 };
321 
322 // Tests that nullptr can't be registered as callbacks.
TEST_F(SystemSuspendTest,RegisterInvalidCallback)323 TEST_F(SystemSuspendTest, RegisterInvalidCallback) {
324     bool retval = false;
325     controlService->registerCallback(nullptr, &retval);
326     ASSERT_FALSE(retval);
327 }
328 
329 // Tests that SystemSuspend HAL correctly notifies wakeup events.
TEST_F(SystemSuspendTest,CallbackNotifyWakeup)330 TEST_F(SystemSuspendTest, CallbackNotifyWakeup) {
331     constexpr int numWakeups = 5;
332     MockCallbackImpl impl;
333     // SystemSuspend should suspend numWakeup + 1 times. However, it might
334     // only be able to notify numWakeup times. The test case might have
335     // finished by the time last notification completes.
336     EXPECT_CALL(impl, notifyWakeup).Times(testing::AtLeast(numWakeups));
337     sp<MockCallback> cb = new MockCallback(&impl);
338     bool retval = false;
339     controlService->registerCallback(cb, &retval);
340     ASSERT_TRUE(retval);
341     checkLoop(numWakeups + 1);
342     cb->disable();
343 }
344 
345 // Tests that SystemSuspend HAL correctly deals with a dead callback.
TEST_F(SystemSuspendTest,DeadCallback)346 TEST_F(SystemSuspendTest, DeadCallback) {
347     ASSERT_EXIT(
348         {
349             sp<MockCallback> cb = new MockCallback(nullptr);
350             bool retval = false;
351             controlService->registerCallback(cb, &retval);
352             ASSERT_TRUE(retval);
353             std::exit(0);
354         },
355         ::testing::ExitedWithCode(0), "");
356 
357     // Dead process callback must still be dealt with either by unregistering it
358     // or checking isOk() on every call.
359     checkLoop(3);
360 }
361 
362 // Callback that registers another callback.
363 class CbRegisteringCb : public BnSuspendCallback {
364    public:
CbRegisteringCb(sp<ISuspendControlService> controlService)365     CbRegisteringCb(sp<ISuspendControlService> controlService) : mControlService(controlService) {}
notifyWakeup(bool x)366     binder::Status notifyWakeup(bool x) {
367         sp<MockCallback> cb = new MockCallback(nullptr);
368         cb->disable();
369         bool retval = false;
370         mControlService->registerCallback(cb, &retval);
371         return binder::Status::ok();
372     }
373 
374    private:
375     sp<ISuspendControlService> mControlService;
376 };
377 
378 // Tests that callback registering another callback doesn't result in a deadlock.
TEST_F(SystemSuspendTest,CallbackRegisterCallbackNoDeadlock)379 TEST_F(SystemSuspendTest, CallbackRegisterCallbackNoDeadlock) {
380     sp<CbRegisteringCb> cb = new CbRegisteringCb(controlService);
381     bool retval = false;
382     controlService->registerCallback(cb, &retval);
383     ASSERT_TRUE(retval);
384     checkLoop(3);
385 }
386 
387 class SystemSuspendSameThreadTest : public ::testing::Test {
388    public:
acquireWakeLock(const std::string & name="TestLock")389     sp<IWakeLock> acquireWakeLock(const std::string& name = "TestLock") {
390         return suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
391     }
392 
393     /**
394      * Returns true if wake lock is found else false.
395      */
findWakeLockInfoByName(const std::vector<WakeLockInfo> & wlStats,const std::string & name,WakeLockInfo * info)396     bool findWakeLockInfoByName(const std::vector<WakeLockInfo>& wlStats, const std::string& name,
397                                 WakeLockInfo* info) {
398         auto it = std::find_if(wlStats.begin(), wlStats.end(),
399                                [&name](const auto& x) { return x.name == name; });
400         if (it != wlStats.end()) {
401             *info = *it;
402             return true;
403         }
404         return false;
405     }
406 
writeStatToFile(int statDirFd,const std::string & fileName,const std::string & stat)407     bool writeStatToFile(int statDirFd, const std::string& fileName, const std::string& stat) {
408         unique_fd statFd{TEMP_FAILURE_RETRY(
409             openat(statDirFd, fileName.c_str(), O_CREAT | O_CLOEXEC | O_RDWR, S_IRWXU))};
410         if (statFd < 0) {
411             PLOG(ERROR) << "SystemSuspend: Error opening " << fileName;
412             return false;
413         }
414 
415         if (!WriteStringToFd(stat, statFd.get())) {
416             PLOG(ERROR) << "SystemSuspend: Error writing stat to " << fileName;
417             return false;
418         }
419 
420         return true;
421     }
422 
writeStatToFile(int statDirFd,const std::string & fileName,int64_t stat)423     bool writeStatToFile(int statDirFd, const std::string& fileName, int64_t stat) {
424         return writeStatToFile(statDirFd, fileName, std::to_string(stat));
425     }
426 
427     /**
428      * Creates a kernel wakelock directory and stats files.
429      * Returns true on success else false.
430      */
addKernelWakelock(const std::string & name,int64_t activeCount=42,int64_t activeTime=42,int64_t eventCount=42,int64_t expireCount=42,int64_t lastChange=42,int64_t maxTime=42,int64_t preventSuspendTime=42,int64_t totalTime=42,int64_t wakeupCount=42)431     bool addKernelWakelock(const std::string& name, int64_t activeCount = 42,
432                            int64_t activeTime = 42, int64_t eventCount = 42,
433                            int64_t expireCount = 42, int64_t lastChange = 42, int64_t maxTime = 42,
434                            int64_t preventSuspendTime = 42, int64_t totalTime = 42,
435                            int64_t wakeupCount = 42) {
436         static int id = 0;
437         std::string kwlId = "wakeup" + std::to_string(id++);
438 
439         if ((mkdirat(kernelWakelockStatsFd, kwlId.c_str(), S_IRWXU)) < 0) {
440             PLOG(ERROR) << "SystemSuspend: Error creating directory for " << kwlId;
441             return false;
442         }
443 
444         unique_fd kernelWakelockFd{TEMP_FAILURE_RETRY(
445             openat(kernelWakelockStatsFd, kwlId.c_str(), O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
446         if (kernelWakelockFd < 0) {
447             PLOG(ERROR) << "SystemSuspend: Error opening " << kwlId;
448             return false;
449         }
450 
451         int fd = kernelWakelockFd.get();
452 
453         return writeStatToFile(fd, "name", name) &&
454                writeStatToFile(fd, "active_count", activeCount) &&
455                writeStatToFile(fd, "active_time_ms", activeTime) &&
456                writeStatToFile(fd, "event_count", eventCount) &&
457                writeStatToFile(fd, "expire_count", expireCount) &&
458                writeStatToFile(fd, "last_change_ms", lastChange) &&
459                writeStatToFile(fd, "max_time_ms", maxTime) &&
460                writeStatToFile(fd, "prevent_suspend_time_ms", preventSuspendTime) &&
461                writeStatToFile(fd, "total_time_ms", totalTime) &&
462                writeStatToFile(fd, "wakeup_count", wakeupCount);
463     }
464 
465     /**
466      * Adds Suspend stats files to suspendStatDir.
467      * Returns true on success else false.
468      */
addSuspendStats(int64_t success=42,int64_t fail=42,int64_t failedFreeze=42,int64_t failedPrepare=42,int64_t failedSuspend=42,int64_t failedSuspendLate=42,int64_t failedSuspendNoirq=42,int64_t failedResume=42,int64_t failedResumeEarly=42,int64_t failedResumeNoirq=42,const std::string & lastFailedDev="fakeDev",int64_t lastFailedErrno=42,const std::string & lastFailedStep="fakeStep")469     bool addSuspendStats(int64_t success = 42, int64_t fail = 42, int64_t failedFreeze = 42,
470                          int64_t failedPrepare = 42, int64_t failedSuspend = 42,
471                          int64_t failedSuspendLate = 42, int64_t failedSuspendNoirq = 42,
472                          int64_t failedResume = 42, int64_t failedResumeEarly = 42,
473                          int64_t failedResumeNoirq = 42,
474                          const std::string& lastFailedDev = "fakeDev", int64_t lastFailedErrno = 42,
475                          const std::string& lastFailedStep = "fakeStep") {
476         int fd = suspendStatsFd.get();
477 
478         return writeStatToFile(fd, "success", success) && writeStatToFile(fd, "fail", fail) &&
479                writeStatToFile(fd, "failed_freeze", failedFreeze) &&
480                writeStatToFile(fd, "failed_prepare", failedPrepare) &&
481                writeStatToFile(fd, "failed_suspend", failedSuspend) &&
482                writeStatToFile(fd, "failed_suspend_late", failedSuspendLate) &&
483                writeStatToFile(fd, "failed_suspend_noirq", failedSuspendNoirq) &&
484                writeStatToFile(fd, "failed_resume", failedResume) &&
485                writeStatToFile(fd, "failed_resume_early", failedResumeEarly) &&
486                writeStatToFile(fd, "failed_resume_noirq", failedResumeNoirq) &&
487                writeStatToFile(fd, "last_failed_dev", lastFailedDev) &&
488                writeStatToFile(fd, "last_failed_errno", lastFailedErrno) &&
489                writeStatToFile(fd, "last_failed_step", lastFailedStep);
490     }
491 
removeDirectoryEntry(const std::string & path)492     bool removeDirectoryEntry(const std::string& path) {
493         auto callback = [](const char* child, const struct stat*, int file_type,
494                            struct FTW*) -> int {
495             switch (file_type) {
496                 case FTW_D:
497                 case FTW_DP:
498                 case FTW_DNR:
499                     if (rmdir(child) == -1) {
500                         PLOG(ERROR) << "rmdir " << child;
501                     }
502                     break;
503                 case FTW_NS:
504                 default:
505                     if (rmdir(child) != -1) break;
506                     // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
507                     FALLTHROUGH_INTENDED;
508                 case FTW_F:
509                 case FTW_SL:
510                 case FTW_SLN:
511                     if (unlink(child) == -1) {
512                         PLOG(ERROR) << "unlink " << child;
513                     }
514                     break;
515             }
516             return 0;
517         };
518         return nftw(path.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0;
519     }
520 
521     /**
522      * Removes all entries from directory.
523      * Returns true on success else false.
524      */
clearDirectory(const std::string & dirPath)525     bool clearDirectory(const std::string& dirPath) {
526         std::unique_ptr<DIR, decltype(&closedir)> dp(opendir(dirPath.c_str()), &closedir);
527         if (!dp) {
528             return false;
529         }
530 
531         rewinddir(dp.get());
532         struct dirent* de;
533         while ((de = readdir(dp.get()))) {
534             std::string name(de->d_name);
535             if ((name == ".") || (name == "..")) {
536                 continue;
537             }
538             if (!removeDirectoryEntry(dirPath + "/" + name)) {
539                 PLOG(ERROR) << "SystemSuspend: Failed to remove " << name;
540                 return false;
541             }
542         }
543 
544         return true;
545     }
546 
547     /**
548      * Returns wakelock stats.
549      */
getWakelockStats()550     std::vector<WakeLockInfo> getWakelockStats() {
551         std::vector<WakeLockInfo> wlStats;
552         controlService->getWakeLockStats(&wlStats);
553         return wlStats;
554     }
555 
556     /**
557      * Returns suspend stats.
558      */
getSuspendStats()559     Result<SuspendStats> getSuspendStats() {
560         return reinterpret_cast<SystemSuspend*>(suspendService.get())->getSuspendStats();
561     }
562 
SetUp()563     virtual void SetUp() override {
564         kernelWakelockStatsFd = unique_fd(TEMP_FAILURE_RETRY(
565             open(kernelWakelockStatsDir.path, O_DIRECTORY | O_CLOEXEC | O_RDONLY)));
566         if (kernelWakelockStatsFd < 0) {
567             PLOG(FATAL) << "SystemSuspend: Failed to open kernel wakelock stats directory";
568         }
569 
570         suspendStatsFd = unique_fd(
571             TEMP_FAILURE_RETRY(open(suspendStatsDir.path, O_DIRECTORY | O_CLOEXEC | O_RDONLY)));
572         if (suspendStatsFd < 0) {
573             PLOG(FATAL) << "SystemSuspend: Failed to open suspend_stats directory";
574         }
575 
576         // Set up same thread suspend services
577         sp<SuspendControlService> suspendControl = new SuspendControlService();
578         controlService = suspendControl;
579         suspendService = new SystemSuspend(
580             unique_fd(-1) /* wakeupCountFd */, unique_fd(-1) /* stateFd */,
581             unique_fd(dup(suspendStatsFd)), 1 /* maxNativeStatsEntries */,
582             unique_fd(dup(kernelWakelockStatsFd.get())), 0ms /* baseSleepTime */, suspendControl);
583     }
584 
TearDown()585     virtual void TearDown() override {
586         ASSERT_TRUE(clearDirectory(kernelWakelockStatsDir.path));
587         ASSERT_TRUE(clearDirectory(suspendStatsDir.path));
588     }
589 
590     sp<ISystemSuspend> suspendService;
591     sp<ISuspendControlService> controlService;
592     unique_fd kernelWakelockStatsFd;
593     unique_fd suspendStatsFd;
594     TemporaryDir kernelWakelockStatsDir;
595     TemporaryDir suspendStatsDir;
596 };
597 
598 // Test that getWakeLockStats has correct information about Native WakeLocks.
TEST_F(SystemSuspendSameThreadTest,GetNativeWakeLockStats)599 TEST_F(SystemSuspendSameThreadTest, GetNativeWakeLockStats) {
600     std::string fakeWlName = "FakeLock";
601     {
602         sp<IWakeLock> fakeLock = acquireWakeLock(fakeWlName);
603         std::vector<WakeLockInfo> wlStats = getWakelockStats();
604         ASSERT_EQ(wlStats.size(), 1);
605 
606         WakeLockInfo nwlInfo;
607         ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName, &nwlInfo));
608         ASSERT_EQ(nwlInfo.name, fakeWlName);
609         ASSERT_EQ(nwlInfo.activeCount, 1);
610         ASSERT_EQ(nwlInfo.isActive, true);
611         ASSERT_FALSE(nwlInfo.isKernelWakelock);
612 
613         ASSERT_EQ(nwlInfo.pid, getpid());
614 
615         ASSERT_EQ(nwlInfo.eventCount, 0);
616         ASSERT_EQ(nwlInfo.expireCount, 0);
617         ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
618         ASSERT_EQ(nwlInfo.wakeupCount, 0);
619 
620         // We sleep so that the wake lock stats entry get updated with a different timestamp.
621         std::this_thread::sleep_for(1s);
622     }
623     std::vector<WakeLockInfo> wlStats = getWakelockStats();
624     ASSERT_EQ(wlStats.size(), 1);
625 
626     WakeLockInfo nwlInfo;
627     ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName, &nwlInfo));
628     ASSERT_EQ(nwlInfo.name, fakeWlName);
629     ASSERT_EQ(nwlInfo.activeCount, 1);
630     ASSERT_GE(nwlInfo.maxTime, 1000);
631     ASSERT_GE(nwlInfo.totalTime, 1000);
632     ASSERT_EQ(nwlInfo.isActive, false);
633     ASSERT_EQ(nwlInfo.activeTime, 0);  // No longer active
634     ASSERT_FALSE(nwlInfo.isKernelWakelock);
635 
636     ASSERT_EQ(nwlInfo.pid, getpid());
637 
638     ASSERT_EQ(nwlInfo.eventCount, 0);
639     ASSERT_EQ(nwlInfo.expireCount, 0);
640     ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
641     ASSERT_EQ(nwlInfo.wakeupCount, 0);
642 }
643 
644 // Test that getWakeLockStats has correct information about Kernel WakeLocks.
TEST_F(SystemSuspendSameThreadTest,GetKernelWakeLockStats)645 TEST_F(SystemSuspendSameThreadTest, GetKernelWakeLockStats) {
646     std::string fakeKwlName1 = "fakeKwl1";
647     std::string fakeKwlName2 = "fakeKwl2";
648     addKernelWakelock(fakeKwlName1);
649     addKernelWakelock(fakeKwlName2, 10 /* activeCount */);
650 
651     std::vector<WakeLockInfo> wlStats = getWakelockStats();
652 
653     ASSERT_EQ(wlStats.size(), 2);
654 
655     WakeLockInfo kwlInfo1;
656     ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName1, &kwlInfo1));
657     ASSERT_EQ(kwlInfo1.name, fakeKwlName1);
658     ASSERT_EQ(kwlInfo1.activeCount, 42);
659     ASSERT_EQ(kwlInfo1.lastChange, 42);
660     ASSERT_EQ(kwlInfo1.maxTime, 42);
661     ASSERT_EQ(kwlInfo1.totalTime, 42);
662     ASSERT_EQ(kwlInfo1.isActive, true);
663     ASSERT_EQ(kwlInfo1.activeTime, 42);
664     ASSERT_TRUE(kwlInfo1.isKernelWakelock);
665 
666     ASSERT_EQ(kwlInfo1.pid, -1);
667 
668     ASSERT_EQ(kwlInfo1.eventCount, 42);
669     ASSERT_EQ(kwlInfo1.expireCount, 42);
670     ASSERT_EQ(kwlInfo1.preventSuspendTime, 42);
671     ASSERT_EQ(kwlInfo1.wakeupCount, 42);
672 
673     WakeLockInfo kwlInfo2;
674     ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName2, &kwlInfo2));
675     ASSERT_EQ(kwlInfo2.name, fakeKwlName2);
676     ASSERT_EQ(kwlInfo2.activeCount, 10);
677     ASSERT_EQ(kwlInfo2.lastChange, 42);
678     ASSERT_EQ(kwlInfo2.maxTime, 42);
679     ASSERT_EQ(kwlInfo2.totalTime, 42);
680     ASSERT_EQ(kwlInfo2.isActive, true);
681     ASSERT_EQ(kwlInfo2.activeTime, 42);
682     ASSERT_TRUE(kwlInfo2.isKernelWakelock);
683 
684     ASSERT_EQ(kwlInfo2.pid, -1);
685 
686     ASSERT_EQ(kwlInfo2.eventCount, 42);
687     ASSERT_EQ(kwlInfo2.expireCount, 42);
688     ASSERT_EQ(kwlInfo2.preventSuspendTime, 42);
689     ASSERT_EQ(kwlInfo2.wakeupCount, 42);
690 }
691 
692 // Test that getWakeLockStats has correct information about Native AND Kernel WakeLocks.
TEST_F(SystemSuspendSameThreadTest,GetNativeAndKernelWakeLockStats)693 TEST_F(SystemSuspendSameThreadTest, GetNativeAndKernelWakeLockStats) {
694     std::string fakeNwlName = "fakeNwl";
695     std::string fakeKwlName = "fakeKwl";
696 
697     addKernelWakelock(fakeKwlName);
698 
699     {
700         sp<IWakeLock> fakeLock = acquireWakeLock(fakeNwlName);
701         std::vector<WakeLockInfo> wlStats = getWakelockStats();
702         ASSERT_EQ(wlStats.size(), 2);
703 
704         // Native Wakelock Stats
705         WakeLockInfo nwlInfo;
706         ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeNwlName, &nwlInfo));
707         ASSERT_EQ(nwlInfo.name, fakeNwlName);
708         ASSERT_EQ(nwlInfo.activeCount, 1);
709         ASSERT_EQ(nwlInfo.isActive, true);
710         ASSERT_FALSE(nwlInfo.isKernelWakelock);
711 
712         ASSERT_EQ(nwlInfo.pid, getpid());
713 
714         ASSERT_EQ(nwlInfo.eventCount, 0);
715         ASSERT_EQ(nwlInfo.expireCount, 0);
716         ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
717         ASSERT_EQ(nwlInfo.wakeupCount, 0);
718 
719         // Kernel Wakelock Stats
720         WakeLockInfo kwlInfo;
721         ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName, &kwlInfo));
722         ASSERT_EQ(kwlInfo.name, fakeKwlName);
723         ASSERT_EQ(kwlInfo.activeCount, 42);
724         ASSERT_EQ(kwlInfo.lastChange, 42);
725         ASSERT_EQ(kwlInfo.maxTime, 42);
726         ASSERT_EQ(kwlInfo.totalTime, 42);
727         ASSERT_EQ(kwlInfo.isActive, true);
728         ASSERT_EQ(kwlInfo.activeTime, 42);
729         ASSERT_TRUE(kwlInfo.isKernelWakelock);
730 
731         ASSERT_EQ(kwlInfo.pid, -1);
732 
733         ASSERT_EQ(kwlInfo.eventCount, 42);
734         ASSERT_EQ(kwlInfo.expireCount, 42);
735         ASSERT_EQ(kwlInfo.preventSuspendTime, 42);
736         ASSERT_EQ(kwlInfo.wakeupCount, 42);
737 
738         // We sleep so that the wake lock stats entry get updated with a different timestamp.
739         std::this_thread::sleep_for(1s);
740     }
741     std::vector<WakeLockInfo> wlStats = getWakelockStats();
742     ASSERT_EQ(wlStats.size(), 2);
743 
744     // Native Wakelock Stats
745     WakeLockInfo nwlInfo;
746     ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeNwlName, &nwlInfo));
747     ASSERT_EQ(nwlInfo.name, fakeNwlName);
748     ASSERT_EQ(nwlInfo.activeCount, 1);
749     ASSERT_GE(nwlInfo.maxTime, 1000);
750     ASSERT_GE(nwlInfo.totalTime, 1000);
751     ASSERT_EQ(nwlInfo.isActive, false);
752     ASSERT_EQ(nwlInfo.activeTime, 0);  // No longer active
753     ASSERT_FALSE(nwlInfo.isKernelWakelock);
754 
755     ASSERT_EQ(nwlInfo.pid, getpid());
756 
757     ASSERT_EQ(nwlInfo.eventCount, 0);
758     ASSERT_EQ(nwlInfo.expireCount, 0);
759     ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
760     ASSERT_EQ(nwlInfo.wakeupCount, 0);
761 
762     // Kernel Wakelock Stats (No changes expected here)
763     WakeLockInfo kwlInfo;
764     ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName, &kwlInfo));
765     ASSERT_EQ(kwlInfo.name, fakeKwlName);
766     ASSERT_EQ(kwlInfo.activeCount, 42);
767     ASSERT_EQ(kwlInfo.lastChange, 42);
768     ASSERT_EQ(kwlInfo.maxTime, 42);
769     ASSERT_EQ(kwlInfo.totalTime, 42);
770     ASSERT_EQ(kwlInfo.isActive, true);
771     ASSERT_EQ(kwlInfo.activeTime, 42);
772     ASSERT_TRUE(kwlInfo.isKernelWakelock);
773 
774     ASSERT_EQ(kwlInfo.pid, -1);
775 
776     ASSERT_EQ(kwlInfo.eventCount, 42);
777     ASSERT_EQ(kwlInfo.expireCount, 42);
778     ASSERT_EQ(kwlInfo.preventSuspendTime, 42);
779     ASSERT_EQ(kwlInfo.wakeupCount, 42);
780 }
781 
782 // Test that the least recently used native wake lock stats entry is evicted after a given
783 // threshold.
TEST_F(SystemSuspendSameThreadTest,NativeWakeLockStatsLruEviction)784 TEST_F(SystemSuspendSameThreadTest, NativeWakeLockStatsLruEviction) {
785     std::string fakeWlName1 = "FakeLock1";
786     std::string fakeWlName2 = "FakeLock2";
787 
788     acquireWakeLock(fakeWlName1);
789     acquireWakeLock(fakeWlName2);
790 
791     std::vector<WakeLockInfo> wlStats = getWakelockStats();
792 
793     // Max number of native stats entries was set to 1 in SystemSuspend constructor.
794     ASSERT_EQ(wlStats.size(), 1);
795     ASSERT_EQ(wlStats.begin()->name, fakeWlName2);
796 
797     WakeLockInfo wlInfo;
798     ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName2, &wlInfo));
799     ASSERT_FALSE(findWakeLockInfoByName(wlStats, fakeWlName1, &wlInfo));  // Evicted
800 }
801 
802 // Test that GetSuspendStats has correct information.
TEST_F(SystemSuspendSameThreadTest,GetSuspendStats)803 TEST_F(SystemSuspendSameThreadTest, GetSuspendStats) {
804     addSuspendStats();
805 
806     Result<SuspendStats> res = getSuspendStats();
807     ASSERT_RESULT_OK(res);
808 
809     SuspendStats stats = res.value();
810 
811     ASSERT_EQ(stats.success, 42);
812     ASSERT_EQ(stats.fail, 42);
813     ASSERT_EQ(stats.failedFreeze, 42);
814     ASSERT_EQ(stats.failedPrepare, 42);
815     ASSERT_EQ(stats.failedSuspend, 42);
816     ASSERT_EQ(stats.failedSuspendLate, 42);
817     ASSERT_EQ(stats.failedSuspendNoirq, 42);
818     ASSERT_EQ(stats.failedResume, 42);
819     ASSERT_EQ(stats.failedResumeEarly, 42);
820     ASSERT_EQ(stats.failedResumeNoirq, 42);
821     ASSERT_EQ(stats.lastFailedDev, "fakeDev");
822     ASSERT_EQ(stats.lastFailedErrno, 42);
823     ASSERT_EQ(stats.lastFailedStep, "fakeStep");
824 }
825 
826 }  // namespace android
827 
main(int argc,char ** argv)828 int main(int argc, char** argv) {
829     android::hardware::details::setTrebleTestingOverride(true);
830     ::testing::InitGoogleMock(&argc, argv);
831     ::testing::InitGoogleTest(&argc, argv);
832     return RUN_ALL_TESTS();
833 }
834