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 <android/system/suspend/BnWakelockCallback.h>
23 #include <binder/IPCThreadState.h>
24 #include <binder/IServiceManager.h>
25 #include <binder/ProcessState.h>
26 #include <cutils/native_handle.h>
27 #include <ftw.h>
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30 #include <hidl/HidlTransportSupport.h>
31 #include <sys/poll.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
34
35 #include <chrono>
36 #include <cmath>
37 #include <csignal>
38 #include <cstdlib>
39 #include <future>
40 #include <string>
41 #include <thread>
42
43 #include "SuspendControlService.h"
44 #include "SystemSuspend.h"
45 #include "WakeupList.h"
46
47 using android::sp;
48 using android::base::Result;
49 using android::base::Socketpair;
50 using android::base::unique_fd;
51 using android::base::WriteStringToFd;
52 using android::base::WriteStringToFile;
53 using android::hardware::configureRpcThreadpool;
54 using android::hardware::joinRpcThreadpool;
55 using android::hardware::Return;
56 using android::hardware::Void;
57 using android::system::suspend::BnSuspendCallback;
58 using android::system::suspend::BnWakelockCallback;
59 using android::system::suspend::ISuspendControlService;
60 using android::system::suspend::internal::ISuspendControlServiceInternal;
61 using android::system::suspend::internal::WakeLockInfo;
62 using android::system::suspend::internal::WakeupInfo;
63 using android::system::suspend::V1_0::getTimeNow;
64 using android::system::suspend::V1_0::ISystemSuspend;
65 using android::system::suspend::V1_0::IWakeLock;
66 using android::system::suspend::V1_0::readFd;
67 using android::system::suspend::V1_0::SleepTimeConfig;
68 using android::system::suspend::V1_0::SuspendControlService;
69 using android::system::suspend::V1_0::SuspendControlServiceInternal;
70 using android::system::suspend::V1_0::SuspendStats;
71 using android::system::suspend::V1_0::SystemSuspend;
72 using android::system::suspend::V1_0::TimestampType;
73 using android::system::suspend::V1_0::WakeLockType;
74 using android::system::suspend::V1_0::WakeupList;
75 using namespace std::chrono_literals;
76
77 namespace android {
78
79 static constexpr char kServiceName[] = "TestService";
80 static constexpr char kControlServiceName[] = "TestControlService";
81 static constexpr char kControlServiceInternalName[] = "TestControlServiceInternal";
82
isReadBlocked(int fd,int timeout_ms=20)83 static bool isReadBlocked(int fd, int timeout_ms = 20) {
84 struct pollfd pfd {
85 .fd = fd, .events = POLLIN,
86 };
87 return poll(&pfd, 1, timeout_ms) == 0;
88 }
89
90 class SystemSuspendTest : public ::testing::Test {
91 protected:
registerTestService()92 static void registerTestService() {
93 std::thread testService([] {
94 configureRpcThreadpool(1, true /* callerWillJoin */);
95
96 sp<SuspendControlService> suspendControl = new SuspendControlService();
97 auto controlStatus = ::android::defaultServiceManager()->addService(
98 android::String16(kControlServiceName), suspendControl);
99 if (android::OK != controlStatus) {
100 LOG(FATAL) << "Unable to register service " << kControlServiceName << controlStatus;
101 }
102
103 sp<SuspendControlServiceInternal> suspendControlInternal =
104 new SuspendControlServiceInternal();
105 controlStatus = ::android::defaultServiceManager()->addService(
106 android::String16(kControlServiceInternalName), suspendControlInternal);
107 if (android::OK != controlStatus) {
108 LOG(FATAL) << "Unable to register service " << kControlServiceInternalName
109 << controlStatus;
110 }
111
112 // Create non-HW binder threadpool for SuspendControlService.
113 sp<android::ProcessState> ps{android::ProcessState::self()};
114 ps->startThreadPool();
115
116 wakeupReasonsFd =
117 unique_fd(TEMP_FAILURE_RETRY(open(wakeupReasonsFile.path, O_CLOEXEC | O_RDONLY)));
118
119 suspendTimeFd =
120 unique_fd(TEMP_FAILURE_RETRY(open(suspendTimeFile.path, O_CLOEXEC | O_RDONLY)));
121
122 sp<ISystemSuspend> suspend = new SystemSuspend(
123 std::move(wakeupCountFds[1]), std::move(stateFds[1]),
124 unique_fd(-1) /*suspendStatsFd*/, 1 /* maxNativeStatsEntries */,
125 unique_fd(-1) /* kernelWakelockStatsFd */, std::move(wakeupReasonsFd),
126 std::move(suspendTimeFd), kSleepTimeConfig, suspendControl, suspendControlInternal);
127 status_t status = suspend->registerAsService(kServiceName);
128 if (android::OK != status) {
129 LOG(FATAL) << "Unable to register service: " << status;
130 }
131
132 joinRpcThreadpool();
133 });
134 testService.detach();
135 }
136
SetUpTestSuite()137 static void SetUpTestSuite() {
138 Socketpair(SOCK_STREAM, &wakeupCountFds[0], &wakeupCountFds[1]);
139 Socketpair(SOCK_STREAM, &stateFds[0], &stateFds[1]);
140
141 registerTestService();
142 ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, kServiceName);
143 sp<ISystemSuspend> suspendService = ISystemSuspend::getService(kServiceName);
144 ASSERT_NE(suspendService, nullptr) << "failed to get suspend service";
145
146 sp<IBinder> control =
147 android::defaultServiceManager()->getService(android::String16(kControlServiceName));
148 ASSERT_NE(control, nullptr) << "failed to get the suspend control service";
149 sp<ISuspendControlService> controlService = interface_cast<ISuspendControlService>(control);
150
151 sp<IBinder> controlInternal = android::defaultServiceManager()->getService(
152 android::String16(kControlServiceInternalName));
153 ASSERT_NE(controlInternal, nullptr) << "failed to get the suspend control internal service";
154 sp<ISuspendControlServiceInternal> controlServiceInternal =
155 interface_cast<ISuspendControlServiceInternal>(controlInternal);
156
157 // Start auto-suspend.
158 bool enabled = false;
159 controlServiceInternal->enableAutosuspend(&enabled);
160 ASSERT_EQ(enabled, true) << "failed to start autosuspend";
161 }
162
163 public:
SetUp()164 virtual void SetUp() override {
165 ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, kServiceName);
166 suspendService = ISystemSuspend::getService(kServiceName);
167 ASSERT_NE(suspendService, nullptr) << "failed to get suspend service";
168
169 sp<IBinder> control =
170 android::defaultServiceManager()->getService(android::String16(kControlServiceName));
171 ASSERT_NE(control, nullptr) << "failed to get the suspend control service";
172 controlService = interface_cast<ISuspendControlService>(control);
173
174 sp<IBinder> controlInternal = android::defaultServiceManager()->getService(
175 android::String16(kControlServiceInternalName));
176 ASSERT_NE(controlInternal, nullptr) << "failed to get the suspend control internal service";
177 controlServiceInternal = interface_cast<ISuspendControlServiceInternal>(controlInternal);
178
179 wakeupCountFd = wakeupCountFds[0];
180 stateFd = stateFds[0];
181
182 // SystemSuspend HAL should not have written back to wakeupCountFd or stateFd yet.
183 ASSERT_TRUE(isReadBlocked(wakeupCountFd));
184 ASSERT_TRUE(isReadBlocked(stateFd));
185 }
186
TearDown()187 virtual void TearDown() override {
188 if (!isReadBlocked(wakeupCountFd)) readFd(wakeupCountFd);
189 if (!isReadBlocked(stateFd)) readFd(stateFd).empty();
190 ASSERT_TRUE(isReadBlocked(wakeupCountFd));
191 ASSERT_TRUE(isReadBlocked(stateFd));
192 }
193
unblockSystemSuspendFromWakeupCount()194 void unblockSystemSuspendFromWakeupCount() {
195 std::string wakeupCount = std::to_string(rand());
196 ASSERT_TRUE(WriteStringToFd(wakeupCount, wakeupCountFd));
197 }
198
isSystemSuspendBlocked(int timeout_ms=20)199 bool isSystemSuspendBlocked(int timeout_ms = 20) { return isReadBlocked(stateFd, timeout_ms); }
200
acquireWakeLock(const std::string & name="")201 sp<IWakeLock> acquireWakeLock(const std::string& name = "TestLock") {
202 return suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
203 }
204
getActiveWakeLockCount()205 size_t getActiveWakeLockCount() {
206 std::vector<WakeLockInfo> wlStats;
207 controlServiceInternal->getWakeLockStats(&wlStats);
208 return count_if(wlStats.begin(), wlStats.end(), [](auto entry) { return entry.isActive; });
209 }
210
checkLoop(int numIter)211 void checkLoop(int numIter) {
212 for (int i = 0; i < numIter; i++) {
213 // Mock value for /sys/power/wakeup_count.
214 std::string wakeupCount = std::to_string(rand());
215 ASSERT_TRUE(WriteStringToFd(wakeupCount, wakeupCountFd));
216 ASSERT_EQ(readFd(wakeupCountFd), wakeupCount)
217 << "wakeup count value written by SystemSuspend is not equal to value given to it";
218 ASSERT_EQ(readFd(stateFd), "mem")
219 << "SystemSuspend failed to write correct sleep state.";
220 }
221 }
222
checkWakelockLoop(int numIter,const std::string name)223 void checkWakelockLoop(int numIter, const std::string name) {
224 for (int i = 0; i < numIter; i++) {
225 sp<IWakeLock> testLock = acquireWakeLock(name);
226 testLock->release();
227 }
228 }
229
suspendFor(std::chrono::milliseconds suspendTime,int numberOfSuspends)230 void suspendFor(std::chrono::milliseconds suspendTime, int numberOfSuspends) {
231 std::string suspendStr =
232 "0.001 " /* placeholder */ +
233 std::to_string(
234 std::chrono::duration_cast<std::chrono::duration<double>>(suspendTime).count());
235 ASSERT_TRUE(WriteStringToFile(suspendStr, suspendTimeFile.path));
236 checkLoop(numberOfSuspends);
237 }
238
checkSleepTime(std::chrono::milliseconds expected)239 void checkSleepTime(std::chrono::milliseconds expected) {
240 SystemSuspend* s = static_cast<SystemSuspend*>(suspendService.get());
241 // There is a race window where sleepTime can be checked in the tests,
242 // before it is updated in autoSuspend
243 while (!isReadBlocked(wakeupCountFd)) {
244 }
245 std::chrono::milliseconds actual = s->getSleepTime();
246 ASSERT_EQ(actual.count(), expected.count()) << "incorrect sleep time";
247 }
248
249 sp<ISystemSuspend> suspendService;
250 sp<ISuspendControlService> controlService;
251 sp<ISuspendControlServiceInternal> controlServiceInternal;
252 static unique_fd wakeupCountFds[2];
253 static unique_fd stateFds[2];
254 static unique_fd wakeupReasonsFd;
255 static unique_fd suspendTimeFd;
256 static int wakeupCountFd;
257 static int stateFd;
258 static TemporaryFile wakeupReasonsFile;
259 static TemporaryFile suspendTimeFile;
260
261 static constexpr SleepTimeConfig kSleepTimeConfig = {
262 .baseSleepTime = 100ms,
263 .maxSleepTime = 400ms,
264 .sleepTimeScaleFactor = 1.9,
265 .backoffThreshold = 1,
266 .shortSuspendThreshold = 100ms,
267 .failedSuspendBackoffEnabled = true,
268 .shortSuspendBackoffEnabled = true,
269 };
270 };
271
272 // SystemSuspendTest test suite resources
273 unique_fd SystemSuspendTest::wakeupCountFds[2];
274 unique_fd SystemSuspendTest::stateFds[2];
275 unique_fd SystemSuspendTest::wakeupReasonsFd;
276 unique_fd SystemSuspendTest::suspendTimeFd;
277 int SystemSuspendTest::wakeupCountFd;
278 int SystemSuspendTest::stateFd;
279 TemporaryFile SystemSuspendTest::wakeupReasonsFile;
280 TemporaryFile SystemSuspendTest::suspendTimeFile;
281
282 // Tests that autosuspend thread can only be enabled once.
TEST_F(SystemSuspendTest,OnlyOneEnableAutosuspend)283 TEST_F(SystemSuspendTest, OnlyOneEnableAutosuspend) {
284 bool enabled = false;
285 controlServiceInternal->enableAutosuspend(&enabled);
286 ASSERT_EQ(enabled, false);
287 }
288
TEST_F(SystemSuspendTest,AutosuspendLoop)289 TEST_F(SystemSuspendTest, AutosuspendLoop) {
290 checkLoop(5);
291 }
292
293 // Tests that upon WakeLock destruction SystemSuspend HAL is unblocked.
TEST_F(SystemSuspendTest,WakeLockDestructor)294 TEST_F(SystemSuspendTest, WakeLockDestructor) {
295 {
296 sp<IWakeLock> wl = acquireWakeLock();
297 ASSERT_NE(wl, nullptr);
298 unblockSystemSuspendFromWakeupCount();
299 ASSERT_TRUE(isSystemSuspendBlocked());
300 }
301 ASSERT_FALSE(isSystemSuspendBlocked());
302 }
303
304 // Tests that upon WakeLock::release() SystemSuspend HAL is unblocked.
TEST_F(SystemSuspendTest,WakeLockRelease)305 TEST_F(SystemSuspendTest, WakeLockRelease) {
306 sp<IWakeLock> wl = acquireWakeLock();
307 ASSERT_NE(wl, nullptr);
308 unblockSystemSuspendFromWakeupCount();
309 ASSERT_TRUE(isSystemSuspendBlocked());
310 wl->release();
311 ASSERT_FALSE(isSystemSuspendBlocked());
312 }
313
314 // Tests that multiple WakeLocks correctly block SystemSuspend HAL.
TEST_F(SystemSuspendTest,MultipleWakeLocks)315 TEST_F(SystemSuspendTest, MultipleWakeLocks) {
316 {
317 sp<IWakeLock> wl1 = acquireWakeLock();
318 ASSERT_NE(wl1, nullptr);
319 ASSERT_TRUE(isSystemSuspendBlocked());
320 unblockSystemSuspendFromWakeupCount();
321 {
322 sp<IWakeLock> wl2 = acquireWakeLock();
323 ASSERT_NE(wl2, nullptr);
324 ASSERT_TRUE(isSystemSuspendBlocked());
325 }
326 ASSERT_TRUE(isSystemSuspendBlocked());
327 }
328 ASSERT_FALSE(isSystemSuspendBlocked());
329 }
330
331 // Tests that upon thread deallocation WakeLock is destructed and SystemSuspend HAL is unblocked.
TEST_F(SystemSuspendTest,ThreadCleanup)332 TEST_F(SystemSuspendTest, ThreadCleanup) {
333 std::thread clientThread([this] {
334 sp<IWakeLock> wl = acquireWakeLock();
335 ASSERT_NE(wl, nullptr);
336 unblockSystemSuspendFromWakeupCount();
337 ASSERT_TRUE(isSystemSuspendBlocked());
338 });
339 clientThread.join();
340 ASSERT_FALSE(isSystemSuspendBlocked());
341 }
342
343 // Test that binder driver correctly deallocates acquired WakeLocks, even if the client processs
344 // is terminated without ability to do clean up.
TEST_F(SystemSuspendTest,CleanupOnAbort)345 TEST_F(SystemSuspendTest, CleanupOnAbort) {
346 ASSERT_EXIT(
347 {
348 sp<IWakeLock> wl = acquireWakeLock();
349 ASSERT_NE(wl, nullptr);
350 std::abort();
351 },
352 ::testing::KilledBySignal(SIGABRT), "");
353 ASSERT_TRUE(isSystemSuspendBlocked());
354 unblockSystemSuspendFromWakeupCount();
355 // Timing of the wake lock clean-up after process death is scheduler-dependent.
356 // Increase the timeout to avoid flakes.
357 ASSERT_FALSE(isSystemSuspendBlocked(200));
358 }
359
360 // Stress test acquiring/releasing WakeLocks.
TEST_F(SystemSuspendTest,WakeLockStressTest)361 TEST_F(SystemSuspendTest, WakeLockStressTest) {
362 // numThreads threads will acquire/release numLocks locks each.
363 constexpr int numThreads = 10;
364 constexpr int numLocks = 10000;
365 std::thread tds[numThreads];
366
367 for (int i = 0; i < numThreads; i++) {
368 tds[i] = std::thread([this] {
369 for (int j = 0; j < numLocks; j++) {
370 sp<IWakeLock> wl1 = acquireWakeLock();
371 sp<IWakeLock> wl2 = acquireWakeLock();
372 wl2->release();
373 }
374 });
375 }
376 for (int i = 0; i < numThreads; i++) {
377 tds[i].join();
378 }
379 ASSERT_EQ(getActiveWakeLockCount(), 0);
380 }
381
TEST_F(SystemSuspendTest,SuspendBackoffLongSuspendTest)382 TEST_F(SystemSuspendTest, SuspendBackoffLongSuspendTest) {
383 // Sleep time shall be set to base sleep time after a long suspend
384 suspendFor(10000ms, 1);
385 checkSleepTime(kSleepTimeConfig.baseSleepTime);
386 }
387
TEST_F(SystemSuspendTest,BackoffThresholdTest)388 TEST_F(SystemSuspendTest, BackoffThresholdTest) {
389 // Sleep time shall be set to base sleep time after a long suspend
390 suspendFor(10000ms, 1);
391 checkSleepTime(kSleepTimeConfig.baseSleepTime);
392
393 // Sleep time shall back off after the configured backoff threshold
394 std::chrono::milliseconds expectedSleepTime = std::chrono::round<std::chrono::milliseconds>(
395 kSleepTimeConfig.baseSleepTime * kSleepTimeConfig.sleepTimeScaleFactor);
396 suspendFor(10ms, kSleepTimeConfig.backoffThreshold);
397 checkSleepTime(kSleepTimeConfig.baseSleepTime);
398 suspendFor(10ms, 1);
399 checkSleepTime(expectedSleepTime);
400
401 // Sleep time shall return to base sleep time after a long suspend
402 suspendFor(10000ms, 1);
403 checkSleepTime(kSleepTimeConfig.baseSleepTime);
404 }
405
TEST_F(SystemSuspendTest,SuspendBackoffMaxTest)406 TEST_F(SystemSuspendTest, SuspendBackoffMaxTest) {
407 // Sleep time shall be set to base sleep time after a long suspend
408 suspendFor(10000ms, 1);
409 checkSleepTime(kSleepTimeConfig.baseSleepTime);
410
411 // Sleep time shall be capped at the configured maximum
412 suspendFor(10ms, 3 + kSleepTimeConfig.backoffThreshold);
413 checkSleepTime(kSleepTimeConfig.maxSleepTime);
414
415 // Sleep time shall return to base sleep time after a long suspend
416 suspendFor(10000ms, 1);
417 checkSleepTime(kSleepTimeConfig.baseSleepTime);
418 }
419
420 // Callbacks are passed around as sp<>. However, mock expectations are verified when mock objects
421 // are destroyed, i.e. the test needs to control lifetime of the mock object.
422 // MockCallbackImpl can be destroyed independently of its wrapper MockCallback which is passed to
423 // SystemSuspend.
424 struct MockCallbackImpl {
425 binder::Status notifyWakeup([[maybe_unused]] bool success,
426 const std::vector<std::string>& wakeupReasons) {
427 mWakeupReasons = wakeupReasons;
428 mNumWakeups++;
429 return binder::Status::ok();
430 }
431
432 std::vector<std::string> mWakeupReasons;
433 int mNumWakeups = 0;
434 };
435
436 class MockCallback : public BnSuspendCallback {
437 public:
MockCallback(MockCallbackImpl * impl)438 MockCallback(MockCallbackImpl* impl) : mImpl(impl), mDisabled(false) {}
notifyWakeup(bool x,const std::vector<std::string> & wakeupReasons)439 binder::Status notifyWakeup(bool x, const std::vector<std::string>& wakeupReasons) {
440 return mDisabled ? binder::Status::ok() : mImpl->notifyWakeup(x, wakeupReasons);
441 }
442 // In case we pull the rug from under MockCallback, but SystemSuspend still has an sp<> to the
443 // object.
disable()444 void disable() { mDisabled = true; }
445
446 private:
447 MockCallbackImpl* mImpl;
448 bool mDisabled;
449 };
450
451 // Tests that nullptr can't be registered as callbacks.
TEST_F(SystemSuspendTest,RegisterInvalidCallback)452 TEST_F(SystemSuspendTest, RegisterInvalidCallback) {
453 bool retval = false;
454 controlService->registerCallback(nullptr, &retval);
455 ASSERT_FALSE(retval);
456 }
457
458 // Tests that SystemSuspend HAL correctly notifies wakeup events.
TEST_F(SystemSuspendTest,CallbackNotifyWakeup)459 TEST_F(SystemSuspendTest, CallbackNotifyWakeup) {
460 constexpr int numWakeups = 5;
461 MockCallbackImpl impl;
462 sp<MockCallback> cb = new MockCallback(&impl);
463 bool retval = false;
464 controlService->registerCallback(cb, &retval);
465 ASSERT_TRUE(retval);
466 checkLoop(numWakeups + 1);
467 cb->disable();
468 // SystemSuspend should suspend numWakeup + 1 times. However, it might
469 // only be able to notify numWakeup times. The test case might have
470 // finished by the time last notification completes.
471 ASSERT_GE(impl.mNumWakeups, numWakeups);
472 }
473
474 // Tests that SystemSuspend HAL correctly notifies wakeup subscribers with wakeup reasons.
TEST_F(SystemSuspendTest,CallbackNotifyWakeupReason)475 TEST_F(SystemSuspendTest, CallbackNotifyWakeupReason) {
476 int i;
477 const std::string wakeupReason0 = "";
478 const std::string wakeupReason1 = " ";
479 const std::string wakeupReason2 = "\n\n";
480 const std::string wakeupReason3 = "100 :android,wakeup-reason-1";
481 const std::string wakeupReason4 = "Abort: android,wakeup-reason-2\n";
482 const std::string wakeupReason5 =
483 "999 :android,wakeup-reason-3\nAbort: android,wakeup-reason-3\n";
484 const std::string referenceWakeupUnknown = "unknown";
485 const std::string referenceWakeupReason3 = "100 :android,wakeup-reason-1";
486 const std::string referenceWakeupReason4 = "Abort: android,wakeup-reason-2";
487 const std::vector<std::string> referenceWakeupReason5 = {"999 :android,wakeup-reason-3",
488 "Abort: android,wakeup-reason-3"};
489
490 unique_fd wakeupReasonsWriteFd = unique_fd(
491 TEMP_FAILURE_RETRY(open(SystemSuspendTest::wakeupReasonsFile.path, O_CLOEXEC | O_WRONLY)));
492
493 MockCallbackImpl impl;
494 sp<MockCallback> cb = new MockCallback(&impl);
495
496 bool retval = false;
497 controlService->registerCallback(cb, &retval);
498 ASSERT_TRUE(retval);
499
500 // wakeupReason0 empty wakeup reason
501 // Following assert check may happen before a callback been executed, iterate few checkLoop to
502 // make sure at least one callback been finished.
503 checkLoop(3);
504 ASSERT_EQ(impl.mWakeupReasons.size(), 1);
505 ASSERT_EQ(impl.mWakeupReasons[0], referenceWakeupUnknown);
506
507 // wakeupReason1 single invalid wakeup reason with only space.
508 ASSERT_TRUE(WriteStringToFd(wakeupReason1, wakeupReasonsWriteFd));
509 checkLoop(3);
510 ASSERT_EQ(impl.mWakeupReasons.size(), 1);
511 ASSERT_EQ(impl.mWakeupReasons[0], referenceWakeupUnknown);
512
513 // wakeupReason2 two empty wakeup reasons.
514 lseek(wakeupReasonsWriteFd, 0, SEEK_SET);
515 ASSERT_TRUE(WriteStringToFd(wakeupReason2, wakeupReasonsWriteFd));
516 checkLoop(3);
517 ASSERT_EQ(impl.mWakeupReasons.size(), 1);
518 ASSERT_EQ(impl.mWakeupReasons[0], referenceWakeupUnknown);
519
520 // wakeupReason3 single wakeup reasons.
521 lseek(wakeupReasonsWriteFd, 0, SEEK_SET);
522 ASSERT_TRUE(WriteStringToFd(wakeupReason3, wakeupReasonsWriteFd));
523 checkLoop(3);
524 ASSERT_EQ(impl.mWakeupReasons.size(), 1);
525 ASSERT_EQ(impl.mWakeupReasons[0], referenceWakeupReason3);
526
527 // wakeupReason4 two wakeup reasons with one empty.
528 lseek(wakeupReasonsWriteFd, 0, SEEK_SET);
529 ASSERT_TRUE(WriteStringToFd(wakeupReason4, wakeupReasonsWriteFd));
530 checkLoop(3);
531 ASSERT_EQ(impl.mWakeupReasons.size(), 1);
532 ASSERT_EQ(impl.mWakeupReasons[0], referenceWakeupReason4);
533
534 // wakeupReason5 two wakeup reasons.
535 lseek(wakeupReasonsWriteFd, 0, SEEK_SET);
536 ASSERT_TRUE(WriteStringToFd(wakeupReason5, wakeupReasonsWriteFd));
537 checkLoop(3);
538 ASSERT_EQ(impl.mWakeupReasons.size(), 2);
539 i = 0;
540 for (auto wakeupReason : impl.mWakeupReasons) {
541 ASSERT_EQ(wakeupReason, referenceWakeupReason5[i++]);
542 }
543 cb->disable();
544 }
545
546 // Tests that SystemSuspend HAL correctly deals with a dead callback.
TEST_F(SystemSuspendTest,DeadCallback)547 TEST_F(SystemSuspendTest, DeadCallback) {
548 ASSERT_EXIT(
549 {
550 sp<MockCallback> cb = new MockCallback(nullptr);
551 bool retval = false;
552 controlService->registerCallback(cb, &retval);
553 ASSERT_TRUE(retval);
554 std::exit(0);
555 },
556 ::testing::ExitedWithCode(0), "");
557
558 // Dead process callback must still be dealt with either by unregistering it
559 // or checking isOk() on every call.
560 checkLoop(3);
561 }
562
563 // Callback that registers another callback.
564 class CbRegisteringCb : public BnSuspendCallback {
565 public:
CbRegisteringCb(sp<ISuspendControlService> controlService)566 CbRegisteringCb(sp<ISuspendControlService> controlService) : mControlService(controlService) {}
567 binder::Status notifyWakeup([[maybe_unused]] bool x,
568 [[maybe_unused]] const std::vector<std::string>& wakeupReasons) {
569 sp<MockCallback> cb = new MockCallback(nullptr);
570 cb->disable();
571 bool retval = false;
572 mControlService->registerCallback(cb, &retval);
573 return binder::Status::ok();
574 }
575
576 private:
577 sp<ISuspendControlService> mControlService;
578 };
579
580 // Tests that callback registering another callback doesn't result in a deadlock.
TEST_F(SystemSuspendTest,CallbackRegisterCallbackNoDeadlock)581 TEST_F(SystemSuspendTest, CallbackRegisterCallbackNoDeadlock) {
582 sp<CbRegisteringCb> cb = new CbRegisteringCb(controlService);
583 bool retval = false;
584 controlService->registerCallback(cb, &retval);
585 ASSERT_TRUE(retval);
586 checkLoop(3);
587 }
588
589 struct MockWakelockCallbackImpl {
590 MOCK_METHOD0(notifyAcquired, binder::Status());
591 MOCK_METHOD0(notifyReleased, binder::Status());
592 };
593
594 class MockWakelockCallback : public BnWakelockCallback {
595 public:
MockWakelockCallback(MockWakelockCallbackImpl * impl)596 MockWakelockCallback(MockWakelockCallbackImpl* impl) : mImpl(impl), mDisabled(false) {}
notifyAcquired(void)597 binder::Status notifyAcquired(void) {
598 return mDisabled ? binder::Status::ok() : mImpl->notifyAcquired();
599 }
notifyReleased(void)600 binder::Status notifyReleased(void) {
601 return mDisabled ? binder::Status::ok() : mImpl->notifyReleased();
602 }
603 // In case we pull the rug from under MockWakelockCallback, but SystemSuspend still has an sp<>
604 // to the object.
disable()605 void disable() { mDisabled = true; }
606
607 private:
608 MockWakelockCallbackImpl* mImpl;
609 bool mDisabled;
610 };
611
612 // Tests that nullptr can't be registered as wakelock callbacks.
TEST_F(SystemSuspendTest,RegisterInvalidWakelockCallback)613 TEST_F(SystemSuspendTest, RegisterInvalidWakelockCallback) {
614 bool retval = false;
615 controlService->registerWakelockCallback(nullptr, "testLock", &retval);
616 ASSERT_FALSE(retval);
617 }
618
619 // Tests that the a callback cannot be registeed with a wakelock twice.
TEST_F(SystemSuspendTest,RegisterCallbackTwice)620 TEST_F(SystemSuspendTest, RegisterCallbackTwice) {
621 bool retval = false;
622 MockWakelockCallbackImpl impl;
623 sp<MockWakelockCallback> cb = new MockWakelockCallback(&impl);
624
625 controlService->registerWakelockCallback(cb, "testLock", &retval);
626 ASSERT_TRUE(retval);
627 controlService->registerWakelockCallback(cb, "testLock", &retval);
628 ASSERT_FALSE(retval);
629
630 cb->disable();
631 }
632
633 // Tests that the same callback can be registered with two wakelocks.
TEST_F(SystemSuspendTest,RegisterSameCallbackForTwoWakelocks)634 TEST_F(SystemSuspendTest, RegisterSameCallbackForTwoWakelocks) {
635 bool retval = false;
636 MockWakelockCallbackImpl impl;
637 sp<MockWakelockCallback> cb = new MockWakelockCallback(&impl);
638
639 controlService->registerWakelockCallback(cb, "testLock1", &retval);
640 ASSERT_TRUE(retval);
641 controlService->registerWakelockCallback(cb, "testLock2", &retval);
642 ASSERT_TRUE(retval);
643
644 cb->disable();
645 }
646
647 // Tests that the two callbacks can be registered with the same wakelock.
TEST_F(SystemSuspendTest,RegisterTwoCallbacksForSameWakelock)648 TEST_F(SystemSuspendTest, RegisterTwoCallbacksForSameWakelock) {
649 bool retval = false;
650 MockWakelockCallbackImpl impl;
651 sp<MockWakelockCallback> cb1 = new MockWakelockCallback(&impl);
652 sp<MockWakelockCallback> cb2 = new MockWakelockCallback(&impl);
653
654 controlService->registerWakelockCallback(cb1, "testLock", &retval);
655 ASSERT_TRUE(retval);
656 controlService->registerWakelockCallback(cb2, "testLock", &retval);
657 ASSERT_TRUE(retval);
658
659 cb1->disable();
660 cb2->disable();
661 }
662
663 // Tests that SystemSuspend HAL correctly deals with a dead wakelock callback.
TEST_F(SystemSuspendTest,DeadWakelockCallback)664 TEST_F(SystemSuspendTest, DeadWakelockCallback) {
665 ASSERT_EXIT(
666 {
667 sp<MockWakelockCallback> cb = new MockWakelockCallback(nullptr);
668 bool retval = false;
669 controlService->registerWakelockCallback(cb, "testLock", &retval);
670 ASSERT_TRUE(retval);
671 std::exit(0);
672 },
673 ::testing::ExitedWithCode(0), "");
674
675 // Dead process callback must still be dealt with either by unregistering it
676 // or checking isOk() on every call.
677 sp<IWakeLock> testLock = acquireWakeLock("testLock");
678 ASSERT_TRUE(testLock->release().isOk());
679 }
680
681 // Wakelock callback that registers another callback.
682 class WakelockCbRegisteringCb : public BnWakelockCallback {
683 public:
WakelockCbRegisteringCb(sp<ISuspendControlService> controlService)684 WakelockCbRegisteringCb(sp<ISuspendControlService> controlService)
685 : mControlService(controlService) {}
notifyAcquired(void)686 binder::Status notifyAcquired(void) {
687 sp<MockWakelockCallback> cb = new MockWakelockCallback(nullptr);
688 cb->disable();
689 bool retval = false;
690 mControlService->registerWakelockCallback(cb, "testLock", &retval);
691 return binder::Status::ok();
692 }
notifyReleased(void)693 binder::Status notifyReleased(void) {
694 sp<MockWakelockCallback> cb = new MockWakelockCallback(nullptr);
695 cb->disable();
696 bool retval = false;
697 mControlService->registerWakelockCallback(cb, "testLock", &retval);
698 return binder::Status::ok();
699 }
700
701 private:
702 sp<ISuspendControlService> mControlService;
703 };
704
TEST_F(SystemSuspendTest,WakelockCallbackRegisterCallbackNoDeadlock)705 TEST_F(SystemSuspendTest, WakelockCallbackRegisterCallbackNoDeadlock) {
706 sp<WakelockCbRegisteringCb> cb = new WakelockCbRegisteringCb(controlService);
707 bool retval = false;
708 controlService->registerWakelockCallback(cb, "testLock", &retval);
709 ASSERT_TRUE(retval);
710
711 checkWakelockLoop(3, "testLock");
712 }
713
714 // Tests that SystemSuspend HAL correctly notifies wakelock events.
TEST_F(SystemSuspendTest,CallbackNotifyWakelock)715 TEST_F(SystemSuspendTest, CallbackNotifyWakelock) {
716 bool retval = false;
717 MockWakelockCallbackImpl impl1;
718 MockWakelockCallbackImpl impl2;
719 sp<MockWakelockCallback> cb1 = new MockWakelockCallback(&impl1);
720 sp<MockWakelockCallback> cb2 = new MockWakelockCallback(&impl2);
721
722 controlService->registerWakelockCallback(cb1, "testLock1", &retval);
723 ASSERT_TRUE(retval);
724 controlService->registerWakelockCallback(cb2, "testLock2", &retval);
725 ASSERT_TRUE(retval);
726
727 EXPECT_CALL(impl1, notifyAcquired).Times(4);
728 EXPECT_CALL(impl1, notifyReleased).Times(4);
729 EXPECT_CALL(impl2, notifyAcquired).Times(3);
730 EXPECT_CALL(impl2, notifyReleased).Times(3);
731
732 checkWakelockLoop(4, "testLock1");
733 checkWakelockLoop(3, "testLock2");
734
735 cb1->disable();
736 cb2->disable();
737 }
738
739 class SystemSuspendSameThreadTest : public ::testing::Test {
740 public:
acquireWakeLock(const std::string & name="")741 sp<IWakeLock> acquireWakeLock(const std::string& name = "TestLock") {
742 return suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
743 }
744
745 /**
746 * Returns true if wake lock is found else false.
747 */
findWakeLockInfoByName(const std::vector<WakeLockInfo> & wlStats,const std::string & name,WakeLockInfo * info)748 bool findWakeLockInfoByName(const std::vector<WakeLockInfo>& wlStats, const std::string& name,
749 WakeLockInfo* info) {
750 auto it = std::find_if(wlStats.begin(), wlStats.end(),
751 [&name](const auto& x) { return x.name == name; });
752 if (it != wlStats.end()) {
753 *info = *it;
754 return true;
755 }
756 return false;
757 }
758
writeStatToFile(int statDirFd,const std::string & fileName,const std::string & stat)759 bool writeStatToFile(int statDirFd, const std::string& fileName, const std::string& stat) {
760 unique_fd statFd{TEMP_FAILURE_RETRY(
761 openat(statDirFd, fileName.c_str(), O_CREAT | O_CLOEXEC | O_RDWR, S_IRWXU))};
762 if (statFd < 0) {
763 PLOG(ERROR) << "SystemSuspend: Error opening " << fileName;
764 return false;
765 }
766
767 if (!WriteStringToFd(stat, statFd.get())) {
768 PLOG(ERROR) << "SystemSuspend: Error writing stat to " << fileName;
769 return false;
770 }
771
772 return true;
773 }
774
writeStatToFile(int statDirFd,const std::string & fileName,int64_t stat)775 bool writeStatToFile(int statDirFd, const std::string& fileName, int64_t stat) {
776 return writeStatToFile(statDirFd, fileName, std::to_string(stat));
777 }
778
779 /**
780 * Creates a kernel wakelock directory and stats files.
781 * Returns true on success else false.
782 */
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)783 bool addKernelWakelock(const std::string& name, int64_t activeCount = 42,
784 int64_t activeTime = 42, int64_t eventCount = 42,
785 int64_t expireCount = 42, int64_t lastChange = 42, int64_t maxTime = 42,
786 int64_t preventSuspendTime = 42, int64_t totalTime = 42,
787 int64_t wakeupCount = 42) {
788 static int id = 0;
789 std::string kwlId = "wakeup" + std::to_string(id++);
790
791 if ((mkdirat(kernelWakelockStatsFd, kwlId.c_str(), S_IRWXU)) < 0) {
792 PLOG(ERROR) << "SystemSuspend: Error creating directory for " << kwlId;
793 return false;
794 }
795
796 unique_fd kernelWakelockFd{TEMP_FAILURE_RETRY(
797 openat(kernelWakelockStatsFd, kwlId.c_str(), O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
798 if (kernelWakelockFd < 0) {
799 PLOG(ERROR) << "SystemSuspend: Error opening " << kwlId;
800 return false;
801 }
802
803 int fd = kernelWakelockFd.get();
804
805 return writeStatToFile(fd, "name", name) &&
806 writeStatToFile(fd, "active_count", activeCount) &&
807 writeStatToFile(fd, "active_time_ms", activeTime) &&
808 writeStatToFile(fd, "event_count", eventCount) &&
809 writeStatToFile(fd, "expire_count", expireCount) &&
810 writeStatToFile(fd, "last_change_ms", lastChange) &&
811 writeStatToFile(fd, "max_time_ms", maxTime) &&
812 writeStatToFile(fd, "prevent_suspend_time_ms", preventSuspendTime) &&
813 writeStatToFile(fd, "total_time_ms", totalTime) &&
814 writeStatToFile(fd, "wakeup_count", wakeupCount);
815 }
816
817 /**
818 * Adds Suspend stats files to suspendStatDir.
819 * Returns true on success else false.
820 */
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="",int64_t lastFailedErrno=42,const std::string & lastFailedStep="")821 bool addSuspendStats(int64_t success = 42, int64_t fail = 42, int64_t failedFreeze = 42,
822 int64_t failedPrepare = 42, int64_t failedSuspend = 42,
823 int64_t failedSuspendLate = 42, int64_t failedSuspendNoirq = 42,
824 int64_t failedResume = 42, int64_t failedResumeEarly = 42,
825 int64_t failedResumeNoirq = 42,
826 const std::string& lastFailedDev = "fakeDev", int64_t lastFailedErrno = 42,
827 const std::string& lastFailedStep = "fakeStep") {
828 int fd = suspendStatsFd.get();
829
830 return writeStatToFile(fd, "success", success) && writeStatToFile(fd, "fail", fail) &&
831 writeStatToFile(fd, "failed_freeze", failedFreeze) &&
832 writeStatToFile(fd, "failed_prepare", failedPrepare) &&
833 writeStatToFile(fd, "failed_suspend", failedSuspend) &&
834 writeStatToFile(fd, "failed_suspend_late", failedSuspendLate) &&
835 writeStatToFile(fd, "failed_suspend_noirq", failedSuspendNoirq) &&
836 writeStatToFile(fd, "failed_resume", failedResume) &&
837 writeStatToFile(fd, "failed_resume_early", failedResumeEarly) &&
838 writeStatToFile(fd, "failed_resume_noirq", failedResumeNoirq) &&
839 writeStatToFile(fd, "last_failed_dev", lastFailedDev) &&
840 writeStatToFile(fd, "last_failed_errno", lastFailedErrno) &&
841 writeStatToFile(fd, "last_failed_step", lastFailedStep);
842 }
843
removeDirectoryEntry(const std::string & path)844 bool removeDirectoryEntry(const std::string& path) {
845 auto callback = [](const char* child, const struct stat*, int file_type,
846 struct FTW*) -> int {
847 switch (file_type) {
848 case FTW_D:
849 case FTW_DP:
850 case FTW_DNR:
851 if (rmdir(child) == -1) {
852 PLOG(ERROR) << "rmdir " << child;
853 }
854 break;
855 case FTW_NS:
856 default:
857 if (rmdir(child) != -1) break;
858 // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
859 FALLTHROUGH_INTENDED;
860 case FTW_F:
861 case FTW_SL:
862 case FTW_SLN:
863 if (unlink(child) == -1) {
864 PLOG(ERROR) << "unlink " << child;
865 }
866 break;
867 }
868 return 0;
869 };
870 return nftw(path.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0;
871 }
872
873 /**
874 * Removes all entries from directory.
875 * Returns true on success else false.
876 */
clearDirectory(const std::string & dirPath)877 bool clearDirectory(const std::string& dirPath) {
878 std::unique_ptr<DIR, decltype(&closedir)> dp(opendir(dirPath.c_str()), &closedir);
879 if (!dp) {
880 return false;
881 }
882
883 rewinddir(dp.get());
884 struct dirent* de;
885 while ((de = readdir(dp.get()))) {
886 std::string name(de->d_name);
887 if ((name == ".") || (name == "..")) {
888 continue;
889 }
890 if (!removeDirectoryEntry(dirPath + "/" + name)) {
891 PLOG(ERROR) << "SystemSuspend: Failed to remove " << name;
892 return false;
893 }
894 }
895
896 return true;
897 }
898
899 /**
900 * Returns wakelock stats.
901 */
getWakelockStats()902 std::vector<WakeLockInfo> getWakelockStats() {
903 std::vector<WakeLockInfo> wlStats;
904 controlServiceInternal->getWakeLockStats(&wlStats);
905 return wlStats;
906 }
907
908 /**
909 * Returns suspend stats.
910 */
getSuspendStats()911 Result<SuspendStats> getSuspendStats() {
912 return reinterpret_cast<SystemSuspend*>(suspendService.get())->getSuspendStats();
913 }
914
SetUp()915 virtual void SetUp() override {
916 kernelWakelockStatsFd = unique_fd(TEMP_FAILURE_RETRY(
917 open(kernelWakelockStatsDir.path, O_DIRECTORY | O_CLOEXEC | O_RDONLY)));
918 if (kernelWakelockStatsFd < 0) {
919 PLOG(FATAL) << "SystemSuspend: Failed to open kernel wakelock stats directory";
920 }
921
922 suspendStatsFd = unique_fd(
923 TEMP_FAILURE_RETRY(open(suspendStatsDir.path, O_DIRECTORY | O_CLOEXEC | O_RDONLY)));
924 if (suspendStatsFd < 0) {
925 PLOG(FATAL) << "SystemSuspend: Failed to open suspend_stats directory";
926 }
927
928 // Set up same thread suspend services
929 sp<SuspendControlService> suspendControl = new SuspendControlService();
930 sp<SuspendControlServiceInternal> suspendControlInternal =
931 new SuspendControlServiceInternal();
932 controlService = suspendControl;
933 controlServiceInternal = suspendControlInternal;
934 suspendService =
935 new SystemSuspend(unique_fd(-1) /* wakeupCountFd */, unique_fd(-1) /* stateFd */,
936 unique_fd(dup(suspendStatsFd)), 1 /* maxNativeStatsEntries */,
937 unique_fd(dup(kernelWakelockStatsFd.get())),
938 unique_fd(-1) /* wakeupReasonsFd */, unique_fd(-1) /*suspendTimeFd*/,
939 kSleepTimeConfig, suspendControl, suspendControlInternal);
940 }
941
TearDown()942 virtual void TearDown() override {
943 ASSERT_TRUE(clearDirectory(kernelWakelockStatsDir.path));
944 ASSERT_TRUE(clearDirectory(suspendStatsDir.path));
945 }
946
947 sp<ISystemSuspend> suspendService;
948 sp<ISuspendControlService> controlService;
949 sp<ISuspendControlServiceInternal> controlServiceInternal;
950 unique_fd kernelWakelockStatsFd;
951 unique_fd suspendStatsFd;
952 TemporaryDir kernelWakelockStatsDir;
953 TemporaryDir suspendStatsDir;
954
955 const SleepTimeConfig kSleepTimeConfig = {
956 .baseSleepTime = 100ms,
957 .maxSleepTime = 400ms,
958 .sleepTimeScaleFactor = 1.9,
959 .backoffThreshold = 1,
960 .shortSuspendThreshold = 100ms,
961 .failedSuspendBackoffEnabled = true,
962 .shortSuspendBackoffEnabled = true,
963 };
964 };
965
966 // Test that getWakeLockStats has correct information about Native WakeLocks.
TEST_F(SystemSuspendSameThreadTest,GetNativeWakeLockStats)967 TEST_F(SystemSuspendSameThreadTest, GetNativeWakeLockStats) {
968 std::string fakeWlName = "FakeLock";
969 {
970 sp<IWakeLock> fakeLock = acquireWakeLock(fakeWlName);
971 std::vector<WakeLockInfo> wlStats = getWakelockStats();
972 ASSERT_EQ(wlStats.size(), 1);
973
974 WakeLockInfo nwlInfo;
975 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName, &nwlInfo));
976 ASSERT_EQ(nwlInfo.name, fakeWlName);
977 ASSERT_EQ(nwlInfo.activeCount, 1);
978 ASSERT_EQ(nwlInfo.isActive, true);
979 ASSERT_FALSE(nwlInfo.isKernelWakelock);
980
981 ASSERT_EQ(nwlInfo.pid, getpid());
982
983 ASSERT_EQ(nwlInfo.eventCount, 0);
984 ASSERT_EQ(nwlInfo.expireCount, 0);
985 ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
986 ASSERT_EQ(nwlInfo.wakeupCount, 0);
987
988 // We sleep so that the wake lock stats entry get updated with a different timestamp.
989 std::this_thread::sleep_for(1s);
990 }
991 std::vector<WakeLockInfo> wlStats = getWakelockStats();
992 ASSERT_EQ(wlStats.size(), 1);
993
994 WakeLockInfo nwlInfo;
995 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName, &nwlInfo));
996 ASSERT_EQ(nwlInfo.name, fakeWlName);
997 ASSERT_EQ(nwlInfo.activeCount, 1);
998 ASSERT_GE(nwlInfo.maxTime, 1000);
999 ASSERT_GE(nwlInfo.totalTime, 1000);
1000 ASSERT_EQ(nwlInfo.isActive, false);
1001 ASSERT_EQ(nwlInfo.activeTime, 0); // No longer active
1002 ASSERT_FALSE(nwlInfo.isKernelWakelock);
1003
1004 ASSERT_EQ(nwlInfo.pid, getpid());
1005
1006 ASSERT_EQ(nwlInfo.eventCount, 0);
1007 ASSERT_EQ(nwlInfo.expireCount, 0);
1008 ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
1009 ASSERT_EQ(nwlInfo.wakeupCount, 0);
1010 }
1011
1012 // Test that getWakeLockStats has correct information about Kernel WakeLocks.
TEST_F(SystemSuspendSameThreadTest,GetKernelWakeLockStats)1013 TEST_F(SystemSuspendSameThreadTest, GetKernelWakeLockStats) {
1014 std::string fakeKwlName1 = "fakeKwl1";
1015 std::string fakeKwlName2 = "fakeKwl2";
1016 addKernelWakelock(fakeKwlName1);
1017 addKernelWakelock(fakeKwlName2, 10 /* activeCount */);
1018
1019 std::vector<WakeLockInfo> wlStats = getWakelockStats();
1020
1021 ASSERT_EQ(wlStats.size(), 2);
1022
1023 WakeLockInfo kwlInfo1;
1024 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName1, &kwlInfo1));
1025 ASSERT_EQ(kwlInfo1.name, fakeKwlName1);
1026 ASSERT_EQ(kwlInfo1.activeCount, 42);
1027 ASSERT_EQ(kwlInfo1.lastChange, 42);
1028 ASSERT_EQ(kwlInfo1.maxTime, 42);
1029 ASSERT_EQ(kwlInfo1.totalTime, 42);
1030 ASSERT_EQ(kwlInfo1.isActive, true);
1031 ASSERT_EQ(kwlInfo1.activeTime, 42);
1032 ASSERT_TRUE(kwlInfo1.isKernelWakelock);
1033
1034 ASSERT_EQ(kwlInfo1.pid, -1);
1035
1036 ASSERT_EQ(kwlInfo1.eventCount, 42);
1037 ASSERT_EQ(kwlInfo1.expireCount, 42);
1038 ASSERT_EQ(kwlInfo1.preventSuspendTime, 42);
1039 ASSERT_EQ(kwlInfo1.wakeupCount, 42);
1040
1041 WakeLockInfo kwlInfo2;
1042 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName2, &kwlInfo2));
1043 ASSERT_EQ(kwlInfo2.name, fakeKwlName2);
1044 ASSERT_EQ(kwlInfo2.activeCount, 10);
1045 ASSERT_EQ(kwlInfo2.lastChange, 42);
1046 ASSERT_EQ(kwlInfo2.maxTime, 42);
1047 ASSERT_EQ(kwlInfo2.totalTime, 42);
1048 ASSERT_EQ(kwlInfo2.isActive, true);
1049 ASSERT_EQ(kwlInfo2.activeTime, 42);
1050 ASSERT_TRUE(kwlInfo2.isKernelWakelock);
1051
1052 ASSERT_EQ(kwlInfo2.pid, -1);
1053
1054 ASSERT_EQ(kwlInfo2.eventCount, 42);
1055 ASSERT_EQ(kwlInfo2.expireCount, 42);
1056 ASSERT_EQ(kwlInfo2.preventSuspendTime, 42);
1057 ASSERT_EQ(kwlInfo2.wakeupCount, 42);
1058 }
1059
1060 // Test that getWakeLockStats has correct information about Native AND Kernel WakeLocks.
TEST_F(SystemSuspendSameThreadTest,GetNativeAndKernelWakeLockStats)1061 TEST_F(SystemSuspendSameThreadTest, GetNativeAndKernelWakeLockStats) {
1062 std::string fakeNwlName = "fakeNwl";
1063 std::string fakeKwlName = "fakeKwl";
1064
1065 addKernelWakelock(fakeKwlName);
1066
1067 {
1068 sp<IWakeLock> fakeLock = acquireWakeLock(fakeNwlName);
1069 std::vector<WakeLockInfo> wlStats = getWakelockStats();
1070 ASSERT_EQ(wlStats.size(), 2);
1071
1072 // Native Wakelock Stats
1073 WakeLockInfo nwlInfo;
1074 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeNwlName, &nwlInfo));
1075 ASSERT_EQ(nwlInfo.name, fakeNwlName);
1076 ASSERT_EQ(nwlInfo.activeCount, 1);
1077 ASSERT_EQ(nwlInfo.isActive, true);
1078 ASSERT_FALSE(nwlInfo.isKernelWakelock);
1079
1080 ASSERT_EQ(nwlInfo.pid, getpid());
1081
1082 ASSERT_EQ(nwlInfo.eventCount, 0);
1083 ASSERT_EQ(nwlInfo.expireCount, 0);
1084 ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
1085 ASSERT_EQ(nwlInfo.wakeupCount, 0);
1086
1087 // Kernel Wakelock Stats
1088 WakeLockInfo kwlInfo;
1089 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName, &kwlInfo));
1090 ASSERT_EQ(kwlInfo.name, fakeKwlName);
1091 ASSERT_EQ(kwlInfo.activeCount, 42);
1092 ASSERT_EQ(kwlInfo.lastChange, 42);
1093 ASSERT_EQ(kwlInfo.maxTime, 42);
1094 ASSERT_EQ(kwlInfo.totalTime, 42);
1095 ASSERT_EQ(kwlInfo.isActive, true);
1096 ASSERT_EQ(kwlInfo.activeTime, 42);
1097 ASSERT_TRUE(kwlInfo.isKernelWakelock);
1098
1099 ASSERT_EQ(kwlInfo.pid, -1);
1100
1101 ASSERT_EQ(kwlInfo.eventCount, 42);
1102 ASSERT_EQ(kwlInfo.expireCount, 42);
1103 ASSERT_EQ(kwlInfo.preventSuspendTime, 42);
1104 ASSERT_EQ(kwlInfo.wakeupCount, 42);
1105
1106 // We sleep so that the wake lock stats entry get updated with a different timestamp.
1107 std::this_thread::sleep_for(1s);
1108 }
1109 std::vector<WakeLockInfo> wlStats = getWakelockStats();
1110 ASSERT_EQ(wlStats.size(), 2);
1111
1112 // Native Wakelock Stats
1113 WakeLockInfo nwlInfo;
1114 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeNwlName, &nwlInfo));
1115 ASSERT_EQ(nwlInfo.name, fakeNwlName);
1116 ASSERT_EQ(nwlInfo.activeCount, 1);
1117 ASSERT_GE(nwlInfo.maxTime, 1000);
1118 ASSERT_GE(nwlInfo.totalTime, 1000);
1119 ASSERT_EQ(nwlInfo.isActive, false);
1120 ASSERT_EQ(nwlInfo.activeTime, 0); // No longer active
1121 ASSERT_FALSE(nwlInfo.isKernelWakelock);
1122
1123 ASSERT_EQ(nwlInfo.pid, getpid());
1124
1125 ASSERT_EQ(nwlInfo.eventCount, 0);
1126 ASSERT_EQ(nwlInfo.expireCount, 0);
1127 ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
1128 ASSERT_EQ(nwlInfo.wakeupCount, 0);
1129
1130 // Kernel Wakelock Stats (No changes expected here)
1131 WakeLockInfo kwlInfo;
1132 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName, &kwlInfo));
1133 ASSERT_EQ(kwlInfo.name, fakeKwlName);
1134 ASSERT_EQ(kwlInfo.activeCount, 42);
1135 ASSERT_EQ(kwlInfo.lastChange, 42);
1136 ASSERT_EQ(kwlInfo.maxTime, 42);
1137 ASSERT_EQ(kwlInfo.totalTime, 42);
1138 ASSERT_EQ(kwlInfo.isActive, true);
1139 ASSERT_EQ(kwlInfo.activeTime, 42);
1140 ASSERT_TRUE(kwlInfo.isKernelWakelock);
1141
1142 ASSERT_EQ(kwlInfo.pid, -1);
1143
1144 ASSERT_EQ(kwlInfo.eventCount, 42);
1145 ASSERT_EQ(kwlInfo.expireCount, 42);
1146 ASSERT_EQ(kwlInfo.preventSuspendTime, 42);
1147 ASSERT_EQ(kwlInfo.wakeupCount, 42);
1148 }
1149
1150 // Test that the least recently used native wake lock stats entry is evicted after a given
1151 // threshold.
TEST_F(SystemSuspendSameThreadTest,NativeWakeLockStatsLruEviction)1152 TEST_F(SystemSuspendSameThreadTest, NativeWakeLockStatsLruEviction) {
1153 std::string fakeWlName1 = "FakeLock1";
1154 std::string fakeWlName2 = "FakeLock2";
1155
1156 acquireWakeLock(fakeWlName1);
1157 acquireWakeLock(fakeWlName2);
1158
1159 std::vector<WakeLockInfo> wlStats = getWakelockStats();
1160
1161 // Max number of native stats entries was set to 1 in SystemSuspend constructor.
1162 ASSERT_EQ(wlStats.size(), 1);
1163 ASSERT_EQ(wlStats.begin()->name, fakeWlName2);
1164
1165 WakeLockInfo wlInfo;
1166 ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName2, &wlInfo));
1167 ASSERT_FALSE(findWakeLockInfoByName(wlStats, fakeWlName1, &wlInfo)); // Evicted
1168 }
1169
1170 // Test that GetSuspendStats has correct information.
TEST_F(SystemSuspendSameThreadTest,GetSuspendStats)1171 TEST_F(SystemSuspendSameThreadTest, GetSuspendStats) {
1172 addSuspendStats();
1173
1174 Result<SuspendStats> res = getSuspendStats();
1175 ASSERT_RESULT_OK(res);
1176
1177 SuspendStats stats = res.value();
1178
1179 ASSERT_EQ(stats.success, 42);
1180 ASSERT_EQ(stats.fail, 42);
1181 ASSERT_EQ(stats.failedFreeze, 42);
1182 ASSERT_EQ(stats.failedPrepare, 42);
1183 ASSERT_EQ(stats.failedSuspend, 42);
1184 ASSERT_EQ(stats.failedSuspendLate, 42);
1185 ASSERT_EQ(stats.failedSuspendNoirq, 42);
1186 ASSERT_EQ(stats.failedResume, 42);
1187 ASSERT_EQ(stats.failedResumeEarly, 42);
1188 ASSERT_EQ(stats.failedResumeNoirq, 42);
1189 ASSERT_EQ(stats.lastFailedDev, "fakeDev");
1190 ASSERT_EQ(stats.lastFailedErrno, 42);
1191 ASSERT_EQ(stats.lastFailedStep, "fakeStep");
1192 }
1193
1194 class SuspendWakeupTest : public ::testing::Test {
1195 public:
SetUp()1196 virtual void SetUp() override {
1197 Socketpair(SOCK_STREAM, &wakeupCountTestFd, &wakeupCountServiceFd);
1198 Socketpair(SOCK_STREAM, &stateTestFd, &stateServiceFd);
1199
1200 suspendControl = new SuspendControlService();
1201
1202 suspendControlInternal = new SuspendControlServiceInternal();
1203
1204 suspendTimeFd =
1205 unique_fd(TEMP_FAILURE_RETRY(open(suspendTimeFile.path, O_CLOEXEC | O_RDONLY)));
1206
1207 wakeupReasonsFd =
1208 unique_fd(TEMP_FAILURE_RETRY(open(wakeupReasonsFile.path, O_CLOEXEC | O_RDONLY)));
1209
1210 suspend = new SystemSuspend(std::move(wakeupCountServiceFd), std::move(stateServiceFd),
1211 unique_fd(-1) /*suspendStatsFd*/, 100 /* maxStatsEntries */,
1212 unique_fd(-1) /* kernelWakelockStatsFd */,
1213 std::move(wakeupReasonsFd), std::move(suspendTimeFd),
1214 kSleepTimeConfig, suspendControl, suspendControlInternal);
1215
1216 // Start auto-suspend.
1217 bool enabled = false;
1218 suspendControlInternal->enableAutosuspend(&enabled);
1219 ASSERT_EQ(enabled, true) << "failed to start autosuspend";
1220 }
1221
TearDown()1222 virtual void TearDown() override {}
1223
wakeup(std::string wakeupReason)1224 void wakeup(std::string wakeupReason) {
1225 ASSERT_TRUE(WriteStringToFile(wakeupReason, wakeupReasonsFile.path));
1226 checkLoop(1);
1227 }
1228
checkLoop(int numIter)1229 void checkLoop(int numIter) {
1230 for (int i = 0; i < numIter; i++) {
1231 // Mock value for /sys/power/wakeup_count.
1232 std::string wakeupCount = std::to_string(rand());
1233 ASSERT_TRUE(WriteStringToFd(wakeupCount, wakeupCountTestFd));
1234 ASSERT_EQ(readFd(wakeupCountTestFd), wakeupCount)
1235 << "wakeup count value written by SystemSuspend is not equal to value given to it";
1236 ASSERT_EQ(readFd(stateTestFd), "mem")
1237 << "SystemSuspend failed to write correct sleep state.";
1238 // There is a race window where sleepTime can be checked in the tests,
1239 // before it is updated in autoSuspend
1240 while (!isReadBlocked(wakeupCountTestFd)) {
1241 }
1242 }
1243 }
1244
suspendFor(std::chrono::milliseconds suspendTime,std::chrono::milliseconds suspendOverhead,int numberOfSuspends)1245 void suspendFor(std::chrono::milliseconds suspendTime,
1246 std::chrono::milliseconds suspendOverhead, int numberOfSuspends) {
1247 std::string suspendStr =
1248 std::to_string(
1249 std::chrono::duration_cast<std::chrono::duration<double>>(suspendOverhead)
1250 .count()) +
1251 " " +
1252 std::to_string(
1253 std::chrono::duration_cast<std::chrono::duration<double>>(suspendTime).count());
1254 ASSERT_TRUE(WriteStringToFile(suspendStr, suspendTimeFile.path));
1255 checkLoop(numberOfSuspends);
1256 }
1257
checkSuspendInfo(const SuspendInfo & expected)1258 void checkSuspendInfo(const SuspendInfo& expected) {
1259 SystemSuspend* s = static_cast<SystemSuspend*>(suspend.get());
1260
1261 SuspendInfo actual;
1262 s->getSuspendInfo(&actual);
1263
1264 ASSERT_EQ(actual.suspendAttemptCount, expected.suspendAttemptCount);
1265 ASSERT_EQ(actual.failedSuspendCount, expected.failedSuspendCount);
1266 ASSERT_EQ(actual.shortSuspendCount, expected.shortSuspendCount);
1267 ASSERT_EQ(actual.suspendTimeMillis, expected.suspendTimeMillis);
1268 ASSERT_EQ(actual.shortSuspendTimeMillis, expected.shortSuspendTimeMillis);
1269 ASSERT_EQ(actual.suspendOverheadTimeMillis, expected.suspendOverheadTimeMillis);
1270 ASSERT_EQ(actual.failedSuspendOverheadTimeMillis, expected.failedSuspendOverheadTimeMillis);
1271 ASSERT_EQ(actual.newBackoffCount, expected.newBackoffCount);
1272 ASSERT_EQ(actual.backoffContinueCount, expected.backoffContinueCount);
1273 ASSERT_EQ(actual.sleepTimeMillis, expected.sleepTimeMillis);
1274 }
1275
1276 unique_fd wakeupCountServiceFd;
1277 unique_fd stateServiceFd;
1278 unique_fd stateTestFd;
1279 unique_fd wakeupCountTestFd;
1280 unique_fd wakeupReasonsFd;
1281 unique_fd suspendTimeFd;
1282 TemporaryFile wakeupReasonsFile;
1283 TemporaryFile suspendTimeFile;
1284 TemporaryFile stateFile;
1285 TemporaryFile wakeupCountFile;
1286 sp<SuspendControlService> suspendControl;
1287 sp<SuspendControlServiceInternal> suspendControlInternal;
1288 sp<ISystemSuspend> suspend;
1289
1290 const SleepTimeConfig kSleepTimeConfig = {
1291 .baseSleepTime = 100ms,
1292 .maxSleepTime = 400ms,
1293 .sleepTimeScaleFactor = 1.9,
1294 .backoffThreshold = 1,
1295 .shortSuspendThreshold = 100ms,
1296 .failedSuspendBackoffEnabled = true,
1297 .shortSuspendBackoffEnabled = true,
1298 };
1299
1300 const int64_t kLongSuspendMillis = 10000; // >= kSleepTimeConfig.shortSuspendThreshold
1301 const int64_t kShortSuspendMillis = 10; // < kSleepTimeConfig.shortSuspendThreshold
1302 const int64_t kSuspendOverheadMillis = 20;
1303 };
1304
TEST_F(SuspendWakeupTest,LongSuspendStat)1305 TEST_F(SuspendWakeupTest, LongSuspendStat) {
1306 suspendFor(std::chrono::milliseconds(kLongSuspendMillis),
1307 std::chrono::milliseconds(kSuspendOverheadMillis), 1);
1308 SuspendInfo expected;
1309 expected.suspendAttemptCount = 1;
1310 expected.suspendTimeMillis = kLongSuspendMillis;
1311 expected.suspendOverheadTimeMillis = kSuspendOverheadMillis;
1312 expected.sleepTimeMillis = kSleepTimeConfig.baseSleepTime.count();
1313 checkSuspendInfo(expected);
1314 }
1315
TEST_F(SuspendWakeupTest,ShortSuspendStat)1316 TEST_F(SuspendWakeupTest, ShortSuspendStat) {
1317 suspendFor(std::chrono::milliseconds(kShortSuspendMillis),
1318 std::chrono::milliseconds(kSuspendOverheadMillis), 1);
1319 SuspendInfo expected;
1320 expected.suspendAttemptCount = 1;
1321 expected.shortSuspendCount = 1;
1322 expected.shortSuspendTimeMillis = kShortSuspendMillis;
1323 expected.suspendTimeMillis = kShortSuspendMillis;
1324 expected.suspendOverheadTimeMillis = kSuspendOverheadMillis;
1325 expected.sleepTimeMillis = kSleepTimeConfig.baseSleepTime.count();
1326 checkSuspendInfo(expected);
1327 }
1328
TEST_F(SuspendWakeupTest,ShortSuspendBackoffStat)1329 TEST_F(SuspendWakeupTest, ShortSuspendBackoffStat) {
1330 suspendFor(std::chrono::milliseconds(kShortSuspendMillis),
1331 std::chrono::milliseconds(kSuspendOverheadMillis), 2);
1332 SuspendInfo expected;
1333 expected.suspendAttemptCount = 2;
1334 expected.shortSuspendCount = 2;
1335 expected.shortSuspendTimeMillis = kShortSuspendMillis * 2;
1336 expected.suspendTimeMillis = kShortSuspendMillis * 2;
1337 expected.suspendOverheadTimeMillis = kSuspendOverheadMillis * 2;
1338 expected.newBackoffCount = 1;
1339 expected.sleepTimeMillis = kSleepTimeConfig.baseSleepTime.count() * 2;
1340 checkSuspendInfo(expected);
1341 }
1342
TEST_F(SuspendWakeupTest,ShortSuspendBackoffContinueStat)1343 TEST_F(SuspendWakeupTest, ShortSuspendBackoffContinueStat) {
1344 suspendFor(std::chrono::milliseconds(kShortSuspendMillis),
1345 std::chrono::milliseconds(kSuspendOverheadMillis), 2);
1346 SuspendInfo expected;
1347 expected.suspendAttemptCount = 2;
1348 expected.shortSuspendCount = 2;
1349 expected.shortSuspendTimeMillis = kShortSuspendMillis * 2;
1350 expected.suspendTimeMillis = kShortSuspendMillis * 2;
1351 expected.suspendOverheadTimeMillis = kSuspendOverheadMillis * 2;
1352 expected.newBackoffCount = 1;
1353 expected.sleepTimeMillis = kSleepTimeConfig.baseSleepTime.count() * 2;
1354 checkSuspendInfo(expected);
1355
1356 suspendFor(std::chrono::milliseconds(kShortSuspendMillis),
1357 std::chrono::milliseconds(kSuspendOverheadMillis), 1);
1358 expected.suspendAttemptCount += 1;
1359 expected.shortSuspendCount += 1;
1360 expected.shortSuspendTimeMillis += kShortSuspendMillis;
1361 expected.suspendTimeMillis += kShortSuspendMillis;
1362 expected.suspendOverheadTimeMillis += kSuspendOverheadMillis;
1363 expected.backoffContinueCount += 1;
1364 expected.sleepTimeMillis +=
1365 std::chrono::round<std::chrono::milliseconds>(kSleepTimeConfig.baseSleepTime *
1366 kSleepTimeConfig.sleepTimeScaleFactor)
1367 .count();
1368 checkSuspendInfo(expected);
1369 }
1370
TEST_F(SuspendWakeupTest,GetSingleWakeupReasonStat)1371 TEST_F(SuspendWakeupTest, GetSingleWakeupReasonStat) {
1372 wakeup("abc");
1373
1374 std::vector<WakeupInfo> wStats;
1375 ASSERT_TRUE(suspendControlInternal->getWakeupStats(&wStats).isOk());
1376 ASSERT_EQ(wStats.size(), 1);
1377 ASSERT_EQ(wStats[0].name, "abc");
1378 ASSERT_EQ(wStats[0].count, 1);
1379 }
1380
TEST_F(SuspendWakeupTest,GetChainedWakeupReasonStat)1381 TEST_F(SuspendWakeupTest, GetChainedWakeupReasonStat) {
1382 wakeup("a\nb");
1383
1384 std::vector<WakeupInfo> wStats;
1385 ASSERT_TRUE(suspendControlInternal->getWakeupStats(&wStats).isOk());
1386 ASSERT_EQ(wStats.size(), 1);
1387 ASSERT_EQ(wStats[0].name, "a;b");
1388 ASSERT_EQ(wStats[0].count, 1);
1389 }
1390
TEST_F(SuspendWakeupTest,GetMultipleWakeupReasonStats)1391 TEST_F(SuspendWakeupTest, GetMultipleWakeupReasonStats) {
1392 wakeup("abc");
1393 wakeup("d\ne");
1394 wakeup("");
1395 wakeup("");
1396 wakeup("wxyz\nabc\n");
1397 wakeup("abc");
1398
1399 std::vector<WakeupInfo> wStats;
1400 ASSERT_TRUE(suspendControlInternal->getWakeupStats(&wStats).isOk());
1401 ASSERT_EQ(wStats.size(), 4);
1402 ASSERT_EQ(wStats[0].name, "abc");
1403 ASSERT_EQ(wStats[0].count, 2);
1404 ASSERT_EQ(wStats[1].name, "wxyz;abc");
1405 ASSERT_EQ(wStats[1].count, 1);
1406 ASSERT_EQ(wStats[2].name, "unknown");
1407 ASSERT_EQ(wStats[2].count, 2);
1408 ASSERT_EQ(wStats[3].name, "d;e");
1409 ASSERT_EQ(wStats[3].count, 1);
1410 }
1411
TEST(WakeupListTest,TestEmpty)1412 TEST(WakeupListTest, TestEmpty) {
1413 WakeupList wakeupList(3);
1414
1415 std::vector<WakeupInfo> wakeups;
1416 wakeupList.getWakeupStats(&wakeups);
1417
1418 ASSERT_TRUE(wakeups.empty());
1419 }
1420
TEST(WakeupListTest,TestNoCapacity)1421 TEST(WakeupListTest, TestNoCapacity) {
1422 WakeupList wakeupList(0);
1423
1424 wakeupList.update({"a"});
1425
1426 std::vector<WakeupInfo> wakeups;
1427 wakeupList.getWakeupStats(&wakeups);
1428
1429 ASSERT_TRUE(wakeups.empty());
1430 }
1431
TEST(WakeupListTest,TestConcat)1432 TEST(WakeupListTest, TestConcat) {
1433 WakeupList wakeupList(3);
1434
1435 wakeupList.update({"a", "b"});
1436
1437 std::vector<WakeupInfo> wakeups;
1438 wakeupList.getWakeupStats(&wakeups);
1439
1440 ASSERT_EQ(wakeups[0].name, "a;b");
1441 ASSERT_EQ(wakeups[0].count, 1);
1442 }
1443
TEST(WakeupListTest,TestNewEntry)1444 TEST(WakeupListTest, TestNewEntry) {
1445 WakeupList wakeupList(3);
1446
1447 wakeupList.update({"a"});
1448 wakeupList.update({"b"});
1449
1450 std::vector<WakeupInfo> wakeups;
1451 wakeupList.getWakeupStats(&wakeups);
1452
1453 ASSERT_EQ(wakeups[1].name, "a");
1454 ASSERT_EQ(wakeups[1].count, 1);
1455 ASSERT_EQ(wakeups[0].name, "b");
1456 ASSERT_EQ(wakeups[0].count, 1);
1457 }
1458
TEST(WakeupListTest,TestIncrement)1459 TEST(WakeupListTest, TestIncrement) {
1460 WakeupList wakeupList(3);
1461
1462 wakeupList.update({"a"});
1463 wakeupList.update({"b"});
1464 wakeupList.update({"a"});
1465
1466 std::vector<WakeupInfo> wakeups;
1467 wakeupList.getWakeupStats(&wakeups);
1468
1469 ASSERT_EQ(wakeups[0].name, "a");
1470 ASSERT_EQ(wakeups[0].count, 2);
1471 ASSERT_EQ(wakeups[1].name, "b");
1472 ASSERT_EQ(wakeups[1].count, 1);
1473 }
1474
TEST(WakeupListTest,TestCapacity)1475 TEST(WakeupListTest, TestCapacity) {
1476 WakeupList wakeupList(3);
1477
1478 wakeupList.update({"a"});
1479 wakeupList.update({"b"});
1480 wakeupList.update({"c"});
1481 wakeupList.update({"d"});
1482
1483 std::vector<WakeupInfo> wakeups;
1484 wakeupList.getWakeupStats(&wakeups);
1485
1486 ASSERT_EQ(wakeups.size(), 3);
1487 ASSERT_EQ(wakeups[0].name, "d");
1488 ASSERT_EQ(wakeups[0].count, 1);
1489 ASSERT_EQ(wakeups[1].name, "c");
1490 ASSERT_EQ(wakeups[1].count, 1);
1491 ASSERT_EQ(wakeups[2].name, "b");
1492 ASSERT_EQ(wakeups[2].count, 1);
1493 }
1494
TEST(WakeupListTest,TestLRUEvict)1495 TEST(WakeupListTest, TestLRUEvict) {
1496 WakeupList wakeupList(3);
1497
1498 wakeupList.update({"a"});
1499 wakeupList.update({"b"});
1500 wakeupList.update({"a"});
1501 wakeupList.update({"c"});
1502 wakeupList.update({"c"});
1503 wakeupList.update({"c"});
1504 wakeupList.update({"d"});
1505
1506 std::vector<WakeupInfo> wakeups;
1507 wakeupList.getWakeupStats(&wakeups);
1508
1509 ASSERT_EQ(wakeups.size(), 3);
1510 ASSERT_EQ(wakeups[0].name, "d");
1511 ASSERT_EQ(wakeups[0].count, 1);
1512 ASSERT_EQ(wakeups[1].name, "c");
1513 ASSERT_EQ(wakeups[1].count, 3);
1514 ASSERT_EQ(wakeups[2].name, "a");
1515 ASSERT_EQ(wakeups[2].count, 2);
1516 }
1517
1518 } // namespace android
1519
main(int argc,char ** argv)1520 int main(int argc, char** argv) {
1521 android::hardware::details::setTrebleTestingOverride(true);
1522 ::testing::InitGoogleMock(&argc, argv);
1523 ::testing::InitGoogleTest(&argc, argv);
1524 return RUN_ALL_TESTS();
1525 }
1526