1 //
2 // Copyright (C) 2012 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 "shill/power_manager.h"
18
19 #include <memory>
20 #include <string>
21
22 #include <base/bind.h>
23 #if defined(__ANDROID__)
24 #include <dbus/service_constants.h>
25 #else
26 #include <chromeos/dbus/service_constants.h>
27 #endif // __ANDROID__
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30
31 #include "shill/mock_control.h"
32 #include "shill/mock_event_dispatcher.h"
33 #include "shill/mock_metrics.h"
34 #include "shill/mock_power_manager_proxy.h"
35 #include "shill/power_manager_proxy_interface.h"
36
37 using base::Bind;
38 using base::Unretained;
39 using std::map;
40 using std::string;
41 using testing::_;
42 using testing::DoAll;
43 using testing::IgnoreResult;
44 using testing::InvokeWithoutArgs;
45 using testing::Mock;
46 using testing::Return;
47 using testing::SetArgumentPointee;
48 using testing::Test;
49
50 namespace shill {
51
52 namespace {
53
54 class FakeControl : public MockControl {
55 public:
FakeControl()56 FakeControl()
57 : delegate_(nullptr),
58 power_manager_proxy_raw_(new MockPowerManagerProxy),
59 power_manager_proxy_(power_manager_proxy_raw_) {}
60
CreatePowerManagerProxy(PowerManagerProxyDelegate * delegate,const base::Closure & service_appeared_callback,const base::Closure & service_vanished_callback)61 virtual PowerManagerProxyInterface* CreatePowerManagerProxy(
62 PowerManagerProxyDelegate* delegate,
63 const base::Closure& service_appeared_callback,
64 const base::Closure& service_vanished_callback) {
65 CHECK(power_manager_proxy_);
66 delegate_ = delegate;
67 // Passes ownership.
68 return power_manager_proxy_.release();
69 }
70
delegate() const71 PowerManagerProxyDelegate* delegate() const { return delegate_; }
72 // Can not guarantee that the returned object is alive.
power_manager_proxy() const73 MockPowerManagerProxy* power_manager_proxy() const {
74 return power_manager_proxy_raw_;
75 }
76
77 private:
78 PowerManagerProxyDelegate* delegate_;
79 MockPowerManagerProxy* const power_manager_proxy_raw_;
80 std::unique_ptr<MockPowerManagerProxy> power_manager_proxy_;
81 };
82
83 } // namespace
84
85 class PowerManagerTest : public Test {
86 public:
87 static const char kDescription[];
88 static const char kDarkDescription[];
89 static const char kPowerManagerDefaultOwner[];
90 static const int kSuspendId1 = 123;
91 static const int kSuspendId2 = 456;
92 static const int kDelayId = 4;
93 static const int kDelayId2 = 5;
94
PowerManagerTest()95 PowerManagerTest()
96 : kTimeout(base::TimeDelta::FromSeconds(3)),
97 power_manager_(&dispatcher_, &control_),
98 power_manager_proxy_(control_.power_manager_proxy()),
99 delegate_(control_.delegate()) {
100 suspend_imminent_callback_ =
101 Bind(&PowerManagerTest::SuspendImminentAction, Unretained(this));
102 suspend_done_callback_ =
103 Bind(&PowerManagerTest::SuspendDoneAction, Unretained(this));
104 dark_suspend_imminent_callback_ =
105 Bind(&PowerManagerTest::DarkSuspendImminentAction, Unretained(this));
106 }
107
108 MOCK_METHOD0(SuspendImminentAction, void());
109 MOCK_METHOD0(SuspendDoneAction, void());
110 MOCK_METHOD0(DarkSuspendImminentAction, void());
111
112 protected:
SetUp()113 virtual void SetUp() {
114 power_manager_.Start(kTimeout, suspend_imminent_callback_,
115 suspend_done_callback_,
116 dark_suspend_imminent_callback_);
117 }
118
TearDown()119 virtual void TearDown() {
120 power_manager_.Stop();
121 }
122
AddProxyExpectationForRegisterSuspendDelay(int delay_id,bool return_value)123 void AddProxyExpectationForRegisterSuspendDelay(int delay_id,
124 bool return_value) {
125 EXPECT_CALL(*power_manager_proxy_,
126 RegisterSuspendDelay(kTimeout, kDescription, _))
127 .WillOnce(DoAll(SetArgumentPointee<2>(delay_id), Return(return_value)));
128 }
129
AddProxyExpectationForUnregisterSuspendDelay(int delay_id,bool return_value)130 void AddProxyExpectationForUnregisterSuspendDelay(int delay_id,
131 bool return_value) {
132 EXPECT_CALL(*power_manager_proxy_, UnregisterSuspendDelay(delay_id))
133 .WillOnce(Return(return_value));
134 }
135
AddProxyExpectationForReportSuspendReadiness(int delay_id,int suspend_id,bool return_value)136 void AddProxyExpectationForReportSuspendReadiness(int delay_id,
137 int suspend_id,
138 bool return_value) {
139 EXPECT_CALL(*power_manager_proxy_,
140 ReportSuspendReadiness(delay_id, suspend_id))
141 .WillOnce(Return(return_value));
142 }
143
AddProxyExpectationForRecordDarkResumeWakeReason(const string & wake_reason,bool return_value)144 void AddProxyExpectationForRecordDarkResumeWakeReason(
145 const string& wake_reason, bool return_value) {
146 EXPECT_CALL(*power_manager_proxy_, RecordDarkResumeWakeReason(wake_reason))
147 .WillOnce(Return(return_value));
148 }
149
AddProxyExpectationForRegisterDarkSuspendDelay(int delay_id,bool return_value)150 void AddProxyExpectationForRegisterDarkSuspendDelay(int delay_id,
151 bool return_value) {
152 EXPECT_CALL(*power_manager_proxy_,
153 RegisterDarkSuspendDelay(kTimeout, kDarkDescription, _))
154 .WillOnce(DoAll(SetArgumentPointee<2>(delay_id), Return(return_value)));
155 }
156
AddProxyExpectationForReportDarkSuspendReadiness(int delay_id,int suspend_id,bool return_value)157 void AddProxyExpectationForReportDarkSuspendReadiness(int delay_id,
158 int suspend_id,
159 bool return_value) {
160 EXPECT_CALL(*power_manager_proxy_,
161 ReportDarkSuspendReadiness(delay_id, suspend_id))
162 .WillOnce(Return(return_value));
163 }
164
AddProxyExpectationForUnregisterDarkSuspendDelay(int delay_id,bool return_value)165 void AddProxyExpectationForUnregisterDarkSuspendDelay(int delay_id,
166 bool return_value) {
167 EXPECT_CALL(*power_manager_proxy_, UnregisterDarkSuspendDelay(delay_id))
168 .WillOnce(Return(return_value));
169 }
170
RegisterSuspendDelays()171 void RegisterSuspendDelays() {
172 AddProxyExpectationForRegisterSuspendDelay(kDelayId, true);
173 AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId, true);
174 OnPowerManagerAppeared();
175 Mock::VerifyAndClearExpectations(power_manager_proxy_);
176 }
177
OnSuspendImminent(int suspend_id)178 void OnSuspendImminent(int suspend_id) {
179 control_.delegate()->OnSuspendImminent(suspend_id);
180 EXPECT_TRUE(power_manager_.suspending());
181 }
182
OnSuspendDone(int suspend_id)183 void OnSuspendDone(int suspend_id) {
184 control_.delegate()->OnSuspendDone(suspend_id);
185 EXPECT_FALSE(power_manager_.suspending());
186 }
187
OnDarkSuspendImminent(int suspend_id)188 void OnDarkSuspendImminent(int suspend_id) {
189 control_.delegate()->OnDarkSuspendImminent(suspend_id);
190 }
191
OnPowerManagerAppeared()192 void OnPowerManagerAppeared() {
193 power_manager_.OnPowerManagerAppeared();
194 }
195
OnPowerManagerVanished()196 void OnPowerManagerVanished() {
197 power_manager_.OnPowerManagerVanished();
198 }
199
200 // This is non-static since it's a non-POD type.
201 const base::TimeDelta kTimeout;
202
203 MockEventDispatcher dispatcher_;
204 FakeControl control_;
205 PowerManager power_manager_;
206 MockPowerManagerProxy* const power_manager_proxy_;
207 PowerManagerProxyDelegate* const delegate_;
208 PowerManager::SuspendImminentCallback suspend_imminent_callback_;
209 PowerManager::SuspendDoneCallback suspend_done_callback_;
210 PowerManager::DarkSuspendImminentCallback dark_suspend_imminent_callback_;
211 };
212
213 const char PowerManagerTest::kDescription[] = "shill";
214 const char PowerManagerTest::kDarkDescription[] = "shill";
215 const char PowerManagerTest::kPowerManagerDefaultOwner[] =
216 "PowerManagerDefaultOwner";
217
TEST_F(PowerManagerTest,SuspendingState)218 TEST_F(PowerManagerTest, SuspendingState) {
219 const int kSuspendId = 3;
220 EXPECT_FALSE(power_manager_.suspending());
221 OnSuspendImminent(kSuspendId);
222 EXPECT_TRUE(power_manager_.suspending());
223 OnSuspendDone(kSuspendId);
224 EXPECT_FALSE(power_manager_.suspending());
225 }
226
TEST_F(PowerManagerTest,RegisterSuspendDelayFailure)227 TEST_F(PowerManagerTest, RegisterSuspendDelayFailure) {
228 AddProxyExpectationForRegisterSuspendDelay(kDelayId, false);
229 OnPowerManagerAppeared();
230 Mock::VerifyAndClearExpectations(power_manager_proxy_);
231
232 // Outstanding shill callbacks should still be invoked.
233 // - suspend_done_callback: If powerd died in the middle of a suspend
234 // we want to wake shill up with suspend_done_action, so this callback
235 // should be invoked anyway.
236 // See PowerManagerTest::PowerManagerDiedInSuspend and
237 // PowerManagerTest::PowerManagerReappearedInSuspend.
238 EXPECT_CALL(*this, SuspendDoneAction());
239 // - suspend_imminent_callback: The only case this can happen is if this
240 // callback was put on the queue, and then powerd reappeared, but we failed
241 // to registered a suspend delay with it.
242 // It is safe to go through the suspend_imminent -> timeout -> suspend_done
243 // path in this black swan case.
244 EXPECT_CALL(*this, SuspendImminentAction());
245 OnSuspendImminent(kSuspendId1);
246 OnSuspendDone(kSuspendId1);
247 Mock::VerifyAndClearExpectations(this);
248 }
249
TEST_F(PowerManagerTest,RegisterDarkSuspendDelayFailure)250 TEST_F(PowerManagerTest, RegisterDarkSuspendDelayFailure) {
251 AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId, false);
252 OnPowerManagerAppeared();
253 Mock::VerifyAndClearExpectations(power_manager_proxy_);
254
255 // Outstanding dark suspend imminent signal should be ignored, since we
256 // probably won't have time to cleanly do dark resume actions. Might as well
257 // ignore the signal.
258 EXPECT_CALL(*this, DarkSuspendImminentAction()).Times(0);
259 OnDarkSuspendImminent(kSuspendId1);
260 }
261
TEST_F(PowerManagerTest,ReportSuspendReadinessFailure)262 TEST_F(PowerManagerTest, ReportSuspendReadinessFailure) {
263 RegisterSuspendDelays();
264 EXPECT_CALL(*this, SuspendImminentAction());
265 OnSuspendImminent(kSuspendId1);
266 AddProxyExpectationForReportSuspendReadiness(kDelayId, kSuspendId1, false);
267 EXPECT_FALSE(power_manager_.ReportSuspendReadiness());
268 }
269
TEST_F(PowerManagerTest,RecordDarkResumeWakeReasonFailure)270 TEST_F(PowerManagerTest, RecordDarkResumeWakeReasonFailure) {
271 const string kWakeReason = "WiFi.Disconnect";
272 RegisterSuspendDelays();
273 EXPECT_CALL(*this, DarkSuspendImminentAction());
274 OnDarkSuspendImminent(kSuspendId1);
275 AddProxyExpectationForRecordDarkResumeWakeReason(kWakeReason, false);
276 EXPECT_FALSE(power_manager_.RecordDarkResumeWakeReason(kWakeReason));
277 }
278
TEST_F(PowerManagerTest,RecordDarkResumeWakeReasonSuccess)279 TEST_F(PowerManagerTest, RecordDarkResumeWakeReasonSuccess) {
280 const string kWakeReason = "WiFi.Disconnect";
281 RegisterSuspendDelays();
282 EXPECT_CALL(*this, DarkSuspendImminentAction());
283 OnDarkSuspendImminent(kSuspendId1);
284 AddProxyExpectationForRecordDarkResumeWakeReason(kWakeReason, true);
285 EXPECT_TRUE(power_manager_.RecordDarkResumeWakeReason(kWakeReason));
286 }
287
TEST_F(PowerManagerTest,ReportDarkSuspendReadinessFailure)288 TEST_F(PowerManagerTest, ReportDarkSuspendReadinessFailure) {
289 RegisterSuspendDelays();
290 EXPECT_CALL(*this, DarkSuspendImminentAction());
291 OnDarkSuspendImminent(kSuspendId1);
292 AddProxyExpectationForReportDarkSuspendReadiness(kDelayId, kSuspendId1,
293 false);
294 EXPECT_FALSE(power_manager_.ReportDarkSuspendReadiness());
295 }
296
TEST_F(PowerManagerTest,ReportSuspendReadinessFailsOutsideSuspend)297 TEST_F(PowerManagerTest, ReportSuspendReadinessFailsOutsideSuspend) {
298 RegisterSuspendDelays();
299 EXPECT_CALL(*power_manager_proxy_, ReportSuspendReadiness(_, _)).Times(0);
300 EXPECT_FALSE(power_manager_.ReportSuspendReadiness());
301 }
302
TEST_F(PowerManagerTest,ReportSuspendReadinessSynchronous)303 TEST_F(PowerManagerTest, ReportSuspendReadinessSynchronous) {
304 // Verifies that a synchronous ReportSuspendReadiness call by shill on a
305 // SuspendImminent callback is routed back to powerd.
306 RegisterSuspendDelays();
307 EXPECT_CALL(*power_manager_proxy_, ReportSuspendReadiness(_, _))
308 .WillOnce(Return(true));
309 EXPECT_CALL(*this, SuspendImminentAction())
310 .WillOnce(IgnoreResult(InvokeWithoutArgs(
311 &power_manager_, &PowerManager::ReportSuspendReadiness)));
312 OnSuspendImminent(kSuspendId1);
313 }
314
TEST_F(PowerManagerTest,ReportDarkSuspendReadinessSynchronous)315 TEST_F(PowerManagerTest, ReportDarkSuspendReadinessSynchronous) {
316 // Verifies that a synchronous ReportDarkSuspendReadiness call by shill on a
317 // DarkSuspendImminent callback is routed back to powerd.
318 RegisterSuspendDelays();
319 EXPECT_CALL(*power_manager_proxy_, ReportDarkSuspendReadiness(_, _))
320 .WillOnce(Return(true));
321 EXPECT_CALL(*this, DarkSuspendImminentAction())
322 .WillOnce(IgnoreResult(InvokeWithoutArgs(
323 &power_manager_, &PowerManager::ReportDarkSuspendReadiness)));
324 OnDarkSuspendImminent(kSuspendId1);
325 }
326
TEST_F(PowerManagerTest,Stop)327 TEST_F(PowerManagerTest, Stop) {
328 RegisterSuspendDelays();
329 AddProxyExpectationForUnregisterSuspendDelay(kDelayId, true);
330 AddProxyExpectationForUnregisterDarkSuspendDelay(kDelayId, true);
331 power_manager_.Stop();
332 }
333
TEST_F(PowerManagerTest,StopFailure)334 TEST_F(PowerManagerTest, StopFailure) {
335 RegisterSuspendDelays();
336
337 AddProxyExpectationForUnregisterSuspendDelay(kDelayId, false);
338 power_manager_.Stop();
339 Mock::VerifyAndClearExpectations(power_manager_proxy_);
340
341 // As a result, callbacks should still be invoked.
342 EXPECT_CALL(*this, SuspendImminentAction());
343 EXPECT_CALL(*this, SuspendDoneAction());
344 OnSuspendImminent(kSuspendId1);
345 OnSuspendDone(kSuspendId1);
346 }
347
TEST_F(PowerManagerTest,OnPowerManagerReappeared)348 TEST_F(PowerManagerTest, OnPowerManagerReappeared) {
349 RegisterSuspendDelays();
350
351 // Check that we re-register suspend delay on powerd restart.
352 AddProxyExpectationForRegisterSuspendDelay(kDelayId2, true);
353 AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId2, true);
354 OnPowerManagerVanished();
355 OnPowerManagerAppeared();
356 Mock::VerifyAndClearExpectations(power_manager_proxy_);
357
358 // Check that a |ReportSuspendReadiness| message is sent with the new delay
359 // id.
360 EXPECT_CALL(*this, SuspendImminentAction());
361 OnSuspendImminent(kSuspendId1);
362 AddProxyExpectationForReportSuspendReadiness(kDelayId2, kSuspendId1, true);
363 EXPECT_TRUE(power_manager_.ReportSuspendReadiness());
364 Mock::VerifyAndClearExpectations(power_manager_proxy_);
365
366 // Check that a |ReportDarkSuspendReadiness| message is sent with the new
367 // delay id.
368 EXPECT_CALL(*this, DarkSuspendImminentAction());
369 OnDarkSuspendImminent(kSuspendId1);
370 AddProxyExpectationForReportDarkSuspendReadiness(kDelayId2, kSuspendId1,
371 true);
372 EXPECT_TRUE(power_manager_.ReportDarkSuspendReadiness());
373 }
374
TEST_F(PowerManagerTest,PowerManagerDiedInSuspend)375 TEST_F(PowerManagerTest, PowerManagerDiedInSuspend) {
376 RegisterSuspendDelays();
377 EXPECT_CALL(*this, SuspendImminentAction());
378 OnSuspendImminent(kSuspendId1);
379 Mock::VerifyAndClearExpectations(this);
380
381 EXPECT_CALL(*this, SuspendDoneAction());
382 OnPowerManagerVanished();
383 EXPECT_FALSE(power_manager_.suspending());
384 }
385
TEST_F(PowerManagerTest,PowerManagerReappearedInSuspend)386 TEST_F(PowerManagerTest, PowerManagerReappearedInSuspend) {
387 RegisterSuspendDelays();
388 EXPECT_CALL(*this, SuspendImminentAction());
389 OnSuspendImminent(kSuspendId1);
390 Mock::VerifyAndClearExpectations(this);
391
392 AddProxyExpectationForRegisterSuspendDelay(kDelayId2, true);
393 AddProxyExpectationForRegisterDarkSuspendDelay(kDelayId2, true);
394 EXPECT_CALL(*this, SuspendDoneAction());
395 OnPowerManagerVanished();
396 OnPowerManagerAppeared();
397 EXPECT_FALSE(power_manager_.suspending());
398 Mock::VerifyAndClearExpectations(this);
399
400 // Let's check a normal suspend request after the fact.
401 EXPECT_CALL(*this, SuspendImminentAction());
402 OnSuspendImminent(kSuspendId2);
403 }
404
405 } // namespace shill
406