1 /*
2 * Copyright (C) 2020 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 "BatteryDefender.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include <utils/Timers.h>
23
24 #include <android-base/file.h>
25 #include <android-base/properties.h>
26
27 class HealthInterface {
28 public:
~HealthInterface()29 virtual ~HealthInterface() {}
30 virtual bool ReadFileToString(const std::string &path, std::string *content,
31 bool follow_symlinks);
32 virtual int GetIntProperty(const std::string &key, int default_value, int min, int max);
33 virtual bool GetBoolProperty(const std::string &key, bool default_value);
34 virtual bool SetProperty(const std::string &key, const std::string &value);
35 virtual bool WriteStringToFile(const std::string &content, const std::string &path,
36 bool follow_symlinks);
37 };
38
39 class HealthInterfaceMock : public HealthInterface {
40 public:
~HealthInterfaceMock()41 virtual ~HealthInterfaceMock() {}
42
43 MOCK_METHOD3(ReadFileToString,
44 bool(const std::string &path, std::string *content, bool follow_symlinks));
45 MOCK_METHOD4(GetIntProperty, int(const std::string &key, int default_value, int min, int max));
46 MOCK_METHOD2(GetBoolProperty, bool(const std::string &key, bool default_value));
47 MOCK_METHOD2(SetProperty, bool(const std::string &key, const std::string &value));
48 MOCK_METHOD3(WriteStringToFile,
49 bool(const std::string &content, const std::string &path, bool follow_symlinks));
50 };
51
52 HealthInterfaceMock *mock;
53
54 namespace android {
55 namespace base {
56
ReadFileToString(const std::string & path,std::string * content,bool follow_symlinks)57 bool ReadFileToString(const std::string &path, std::string *content, bool follow_symlinks) {
58 return mock->ReadFileToString(path, content, follow_symlinks);
59 }
60
WriteStringToFile(const std::string & content,const std::string & path,bool follow_symlinks)61 bool WriteStringToFile(const std::string &content, const std::string &path, bool follow_symlinks) {
62 return mock->WriteStringToFile(content, path, follow_symlinks);
63 }
64
65 template <typename T>
GetIntProperty(const std::string & key,T default_value,T min,T max)66 T GetIntProperty(const std::string &key, T default_value, T min, T max) {
67 return (T)(mock->GetIntProperty(key, default_value, min, max));
68 }
69
GetBoolProperty(const std::string & key,bool default_value)70 bool GetBoolProperty(const std::string &key, bool default_value) {
71 return mock->GetBoolProperty(key, default_value);
72 }
73
74 template int8_t GetIntProperty(const std::string &, int8_t, int8_t, int8_t);
75 template int16_t GetIntProperty(const std::string &, int16_t, int16_t, int16_t);
76 template int32_t GetIntProperty(const std::string &, int32_t, int32_t, int32_t);
77 template int64_t GetIntProperty(const std::string &, int64_t, int64_t, int64_t);
78
SetProperty(const std::string & key,const std::string & value)79 bool SetProperty(const std::string &key, const std::string &value) {
80 return mock->SetProperty(key, value);
81 }
82
83 } // namespace base
84 } // namespace android
85
86 nsecs_t testvar_systemTimeSecs = 0;
systemTime(int clock)87 nsecs_t systemTime(int clock) {
88 UNUSED(clock);
89 return seconds_to_nanoseconds(testvar_systemTimeSecs);
90 }
91
92 namespace hardware {
93 namespace google {
94 namespace pixel {
95 namespace health {
96
97 using ::testing::_;
98 using ::testing::AnyNumber;
99 using ::testing::AtLeast;
100 using ::testing::DoAll;
101 using ::testing::InSequence;
102 using ::testing::Return;
103 using ::testing::SetArgPointee;
104
105 class BatteryDefenderTest : public ::testing::Test {
106 public:
BatteryDefenderTest()107 BatteryDefenderTest() {}
108
SetUp()109 void SetUp() {
110 mock = &mockFixture;
111
112 EXPECT_CALL(*mock, SetProperty(_, _)).Times(AnyNumber());
113 EXPECT_CALL(*mock, ReadFileToString(_, _, _)).Times(AnyNumber());
114 EXPECT_CALL(*mock, GetIntProperty(_, _, _, _)).Times(AnyNumber());
115 EXPECT_CALL(*mock, GetBoolProperty(_, _)).Times(AnyNumber());
116 EXPECT_CALL(*mock, WriteStringToFile(_, _, _)).Times(AnyNumber());
117
118 ON_CALL(*mock, ReadFileToString(_, _, _))
119 .WillByDefault(DoAll(SetArgPointee<1>(std::string("0")), Return(true)));
120
121 ON_CALL(*mock, WriteStringToFile(_, _, _)).WillByDefault(Return(true));
122 }
123
TearDown()124 void TearDown() {}
125
126 private:
127 HealthInterfaceMock mockFixture;
128 };
129
130 const char *kPathWirelessChargerOnline = "/sys/class/power_supply/wireless/online";
131 const char *kPathWiredChargerPresent = "/sys/class/power_supply/usb/present";
132 const char *kPathBatteryCapacity = "/sys/class/power_supply/battery/capacity";
133 const char *kPathPersistChargerPresentTime = "/mnt/vendor/persist/battery/defender_charger_time";
134 const char *kPathPersistDefenderActiveTime = "/mnt/vendor/persist/battery/defender_active_time";
135 const char *kPathStartLevel = "/sys/devices/platform/soc/soc:google,charger/charge_start_level";
136 const char *kPathStopLevel = "/sys/devices/platform/soc/soc:google,charger/charge_stop_level";
137
138 const char *kPropChargeLevelVendorStart = "persist.vendor.charge.start.level";
139 const char *kPropChargeLevelVendorStop = "persist.vendor.charge.stop.level";
140 const char *kPropBatteryDefenderState = "vendor.battery.defender.state";
141 const char *kPropBatteryDefenderDisable = "vendor.battery.defender.disable";
142 const char *kPropBatteryDefenderThreshold = "vendor.battery.defender.threshold";
143 const char *kPropDebuggable = "ro.debuggable";
144
enableDefender(void)145 static void enableDefender(void) {
146 ON_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStart, _, _, _)).WillByDefault(Return(0));
147 ON_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStop, _, _, _)).WillByDefault(Return(100));
148 ON_CALL(*mock, GetBoolProperty(kPropBatteryDefenderDisable, _)).WillByDefault(Return(false));
149 ON_CALL(*mock, GetBoolProperty(kPropDebuggable, _)).WillByDefault(Return(true));
150 }
151
powerAvailable(void)152 static void powerAvailable(void) {
153 ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
154 .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
155 ON_CALL(*mock, ReadFileToString(kPathWiredChargerPresent, _, _))
156 .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
157 }
158
defaultThreshold(void)159 static void defaultThreshold(void) {
160 ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderThreshold, _, _, _))
161 .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
162 }
163
capacityReached(void)164 static void capacityReached(void) {
165 ON_CALL(*mock, ReadFileToString(kPathBatteryCapacity, _, _))
166 .WillByDefault(DoAll(SetArgPointee<1>(std::to_string(100)), Return(true)));
167 }
168
initToConnectedCapacityReached(void)169 static void initToConnectedCapacityReached(void) {
170 ON_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
171 .WillByDefault(DoAll(SetArgPointee<1>(std::to_string(1000)), Return(true)));
172 }
173
initToActive(void)174 static void initToActive(void) {
175 ON_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
176 .WillByDefault(
177 DoAll(SetArgPointee<1>(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1)),
178 Return(true)));
179 }
180
TEST_F(BatteryDefenderTest,EnableAndDisconnected)181 TEST_F(BatteryDefenderTest, EnableAndDisconnected) {
182 BatteryDefender battDefender;
183
184 enableDefender();
185 // No power
186
187 // Enable Battery Defender
188 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISCONNECTED"));
189 battDefender.update();
190 }
191
TEST_F(BatteryDefenderTest,DisableNonDefaultLevels)192 TEST_F(BatteryDefenderTest, DisableNonDefaultLevels) {
193 BatteryDefender battDefender;
194
195 // Enable Battery Defender
196 EXPECT_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStart, _, _, _)).WillOnce(Return(30));
197 EXPECT_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStop, _, _, _)).WillOnce(Return(35));
198
199 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISABLED"));
200 battDefender.update();
201 }
202
TEST_F(BatteryDefenderTest,DisableDebuggable)203 TEST_F(BatteryDefenderTest, DisableDebuggable) {
204 BatteryDefender battDefender;
205
206 // Enable Battery Defender
207 EXPECT_CALL(*mock, GetBoolProperty(kPropDebuggable, _)).WillOnce(Return(false));
208
209 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISABLED"));
210 battDefender.update();
211 }
212
TEST_F(BatteryDefenderTest,DisableExplicit)213 TEST_F(BatteryDefenderTest, DisableExplicit) {
214 BatteryDefender battDefender;
215
216 // Enable Battery Defender
217 EXPECT_CALL(*mock, GetBoolProperty(kPropBatteryDefenderDisable, _)).WillOnce(Return(true));
218
219 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISABLED"));
220 battDefender.update();
221 }
222
TEST_F(BatteryDefenderTest,InitActive)223 TEST_F(BatteryDefenderTest, InitActive) {
224 BatteryDefender battDefender;
225
226 enableDefender();
227 powerAvailable();
228 defaultThreshold();
229
230 EXPECT_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
231 .WillOnce(DoAll(SetArgPointee<1>(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1)),
232 Return(true)));
233 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
234 battDefender.update();
235 }
236
TEST_F(BatteryDefenderTest,InitConnectedCapacityReached)237 TEST_F(BatteryDefenderTest, InitConnectedCapacityReached) {
238 BatteryDefender battDefender;
239
240 enableDefender();
241 powerAvailable();
242 defaultThreshold();
243
244 InSequence s;
245
246 EXPECT_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
247 .WillOnce(DoAll(SetArgPointee<1>(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS - 1)),
248 Return(true)));
249 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
250 battDefender.update();
251
252 testvar_systemTimeSecs++;
253 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS),
254 kPathPersistChargerPresentTime, _));
255 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
256 battDefender.update();
257 }
258
TEST_F(BatteryDefenderTest,InitConnected)259 TEST_F(BatteryDefenderTest, InitConnected) {
260 BatteryDefender battDefender;
261
262 enableDefender();
263 powerAvailable();
264 defaultThreshold();
265
266 InSequence s;
267
268 EXPECT_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
269 .WillOnce(DoAll(SetArgPointee<1>(std::to_string(0)), Return(true)));
270 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
271 battDefender.update();
272
273 // mHasReachedHighCapacityLevel shall be false
274 testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
275 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
276 battDefender.update();
277 }
278
TEST_F(BatteryDefenderTest,TriggerTime)279 TEST_F(BatteryDefenderTest, TriggerTime) {
280 BatteryDefender battDefender;
281
282 enableDefender();
283 powerAvailable();
284 defaultThreshold();
285
286 InSequence s;
287
288 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
289 testvar_systemTimeSecs += 1;
290 battDefender.update();
291
292 // Reached 100% capacity at least once
293 EXPECT_CALL(*mock, ReadFileToString(kPathBatteryCapacity, _, _))
294 .WillOnce(DoAll(SetArgPointee<1>(std::to_string(100)), Return(true)));
295 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
296 testvar_systemTimeSecs += 1;
297 battDefender.update();
298
299 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS),
300 kPathPersistChargerPresentTime, _));
301 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
302 testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS;
303 battDefender.update();
304
305 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1),
306 kPathPersistChargerPresentTime, _));
307 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
308 testvar_systemTimeSecs += 1;
309 battDefender.update();
310 }
311
TEST_F(BatteryDefenderTest,ChargeLevels)312 TEST_F(BatteryDefenderTest, ChargeLevels) {
313 BatteryDefender battDefender;
314
315 enableDefender();
316 powerAvailable();
317 defaultThreshold();
318 initToConnectedCapacityReached();
319
320 InSequence s;
321
322 // No expectations needed; default values already set
323 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
324 testvar_systemTimeSecs += 0;
325 battDefender.update();
326
327 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathStartLevel, _));
328 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStopLevel, _));
329 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
330 testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
331 battDefender.update();
332 }
333
TEST_F(BatteryDefenderTest,ActiveTime)334 TEST_F(BatteryDefenderTest, ActiveTime) {
335 BatteryDefender battDefender;
336
337 enableDefender();
338 powerAvailable();
339 defaultThreshold();
340 initToActive();
341
342 InSequence s;
343
344 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathStartLevel, _));
345 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStopLevel, _));
346 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
347 battDefender.update();
348 }
349
TEST_F(BatteryDefenderTest,ConnectDisconnectCycle)350 TEST_F(BatteryDefenderTest, ConnectDisconnectCycle) {
351 BatteryDefender battDefender;
352
353 enableDefender();
354 defaultThreshold();
355 initToConnectedCapacityReached();
356
357 InSequence s;
358
359 // Power ON
360 ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
361 .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
362
363 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(1000), kPathPersistChargerPresentTime, _));
364 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
365 testvar_systemTimeSecs += 60;
366 battDefender.update();
367
368 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(1060), kPathPersistChargerPresentTime, _));
369 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
370 testvar_systemTimeSecs += 60;
371 battDefender.update();
372
373 // Power OFF
374 ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
375 .WillByDefault(DoAll(SetArgPointee<1>(std::string("0")), Return(true)));
376
377 // Maintain kPathPersistChargerPresentTime = 1060
378 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
379 testvar_systemTimeSecs += 60;
380 battDefender.update();
381
382 // Maintain kPathPersistChargerPresentTime = 1060
383 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
384 testvar_systemTimeSecs += 60 * 4;
385 battDefender.update();
386
387 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(0), kPathPersistChargerPresentTime, _));
388 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISCONNECTED"));
389 testvar_systemTimeSecs += 1;
390 battDefender.update();
391
392 // Power ON
393 ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
394 .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
395
396 // Maintain kPathPersistChargerPresentTime = 0
397 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
398 testvar_systemTimeSecs += 60;
399 battDefender.update();
400
401 capacityReached();
402 // Maintain kPathPersistChargerPresentTime = 0
403 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
404 testvar_systemTimeSecs += 60;
405 battDefender.update();
406
407 EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathPersistChargerPresentTime, _));
408 EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
409 testvar_systemTimeSecs += 60;
410 battDefender.update();
411 }
412
413 } // namespace health
414 } // namespace pixel
415 } // namespace google
416 } // namespace hardware
417