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