1 /*
2  * Copyright (C) 2021 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 package com.android.settings.fuelgauge;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static org.mockito.Mockito.when;
21 
22 import android.content.ContentValues;
23 import android.database.MatrixCursor;
24 import android.os.BatteryManager;
25 import android.os.BatteryUsageStats;
26 import android.os.UserHandle;
27 
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.mockito.Mock;
32 import org.mockito.MockitoAnnotations;
33 import org.robolectric.RobolectricTestRunner;
34 
35 import java.util.TimeZone;
36 
37 @RunWith(RobolectricTestRunner.class)
38 public final class BatteryHistEntryTest {
39 
40     @Mock
41     private BatteryEntry mockBatteryEntry;
42     @Mock
43     private BatteryUsageStats mBatteryUsageStats;
44 
45     @Before
setUp()46     public void setUp() {
47         MockitoAnnotations.initMocks(this);
48     }
49 
50     @Test
testConstructor_contentValues_returnsExpectedResult()51     public void testConstructor_contentValues_returnsExpectedResult() {
52         final int expectedType = 3;
53         when(mockBatteryEntry.getUid()).thenReturn(1001);
54         when(mockBatteryEntry.getLabel()).thenReturn("Settings");
55         when(mockBatteryEntry.getDefaultPackageName())
56             .thenReturn("com.google.android.settings.battery");
57         when(mockBatteryEntry.isHidden()).thenReturn(true);
58         when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
59         when(mockBatteryEntry.getConsumedPower()).thenReturn(1.1);
60         mockBatteryEntry.percent = 0.3;
61         when(mockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
62         when(mockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
63         when(mockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
64         when(mockBatteryEntry.getConsumerType())
65             .thenReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
66         final ContentValues values =
67             ConvertUtils.convert(
68                 mockBatteryEntry,
69                 mBatteryUsageStats,
70                 /*batteryLevel=*/ 12,
71                 /*batteryStatus=*/ BatteryManager.BATTERY_STATUS_FULL,
72                 /*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD,
73                 /*bootTimestamp=*/ 101L,
74                 /*timestamp=*/ 10001L);
75 
76         assertBatteryHistEntry(
77             new BatteryHistEntry(values),
78             /*drainType=*/ expectedType,
79             /*percentOfTotal=*/ mockBatteryEntry.percent);
80     }
81 
82     @Test
testConstructor_invalidField_returnsInvalidEntry()83     public void testConstructor_invalidField_returnsInvalidEntry() {
84         final BatteryHistEntry entry = new BatteryHistEntry(new ContentValues());
85         assertThat(entry.isValidEntry()).isFalse();
86     }
87 
88     @Test
testConstructor_cursor_returnsExpectedResult()89     public void testConstructor_cursor_returnsExpectedResult() {
90         assertBatteryHistEntry(
91             createBatteryHistEntry(
92                 /*bootTimestamp=*/ 101L,
93                 /*timestamp=*/ 10001L,
94                 /*totalPower=*/ 5.1,
95                 /*consumePower=*/ 1.1,
96                 /*foregroundUsageTimeInMs=*/ 1234L,
97                 /*backgroundUsageTimeInMs=*/ 5689L,
98                 /*batteryLevel=*/ 12),
99             /*drainType=*/ 3,
100             /*percentOfTotal=*/ 0.3);
101     }
102 
103     @Test
testGetKey_consumerUidType_returnExpectedString()104     public void testGetKey_consumerUidType_returnExpectedString() {
105         final ContentValues values = getContentValuesWithType(
106             ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
107         values.put(BatteryHistEntry.KEY_UID, 3);
108         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
109 
110         assertThat(batteryHistEntry.getKey()).isEqualTo("3");
111     }
112 
113     @Test
testGetKey_consumerUserType_returnExpectedString()114     public void testGetKey_consumerUserType_returnExpectedString() {
115         final ContentValues values = getContentValuesWithType(
116             ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
117         values.put(BatteryHistEntry.KEY_USER_ID, 2);
118         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
119 
120         assertThat(batteryHistEntry.getKey()).isEqualTo("U|2");
121     }
122 
123     @Test
testGetKey_consumerSystemType_returnExpectedString()124     public void testGetKey_consumerSystemType_returnExpectedString() {
125         final ContentValues values = getContentValuesWithType(
126             ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
127         values.put(BatteryHistEntry.KEY_DRAIN_TYPE, 1);
128         final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
129 
130         assertThat(batteryHistEntry.getKey()).isEqualTo("S|1");
131     }
132 
133     @Test
testIsAppEntry_returnExpectedResult()134     public void testIsAppEntry_returnExpectedResult() {
135         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isAppEntry())
136             .isFalse();
137         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isAppEntry())
138             .isFalse();
139         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isAppEntry())
140             .isTrue();
141     }
142 
143     @Test
testIsUserEntry_returnExpectedResult()144     public void testIsUserEntry_returnExpectedResult() {
145         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isUserEntry())
146             .isFalse();
147         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isUserEntry())
148             .isTrue();
149         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isUserEntry())
150             .isFalse();
151     }
152 
153     @Test
testIsSystemEntry_returnExpectedResult()154     public void testIsSystemEntry_returnExpectedResult() {
155         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY).isSystemEntry())
156             .isTrue();
157         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_USER_BATTERY).isSystemEntry())
158             .isFalse();
159         assertThat(createEntry(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).isSystemEntry())
160             .isFalse();
161     }
162 
163     @Test
testInterpolate_returnExpectedResult()164     public void testInterpolate_returnExpectedResult() {
165         final long slotTimestamp = 200L;
166         final long upperTimestamp = 300L;
167         final long lowerTimestamp = 100L;
168         final double ratio = 0.5;
169         final BatteryHistEntry lowerHistEntry = createBatteryHistEntry(
170             /*bootTimestamp=*/ 1000L,
171             lowerTimestamp,
172             /*totalPower=*/ 50,
173             /*consumePower=*/ 10,
174             /*foregroundUsageTimeInMs=*/ 100,
175             /*backgroundUsageTimeInMs=*/ 200,
176             /*batteryLevel=*/ 90);
177         final BatteryHistEntry upperHistEntry = createBatteryHistEntry(
178             /*bootTimestamp=*/ 1200L,
179             upperTimestamp,
180             /*totalPower=*/ 80,
181             /*consumePower=*/ 20,
182             /*foregroundUsageTimeInMs=*/ 200,
183             /*backgroundUsageTimeInMs=*/ 300,
184             /*batteryLevel=*/ 80);
185 
186         final BatteryHistEntry newEntry =
187             BatteryHistEntry.interpolate(
188                 slotTimestamp,
189                 upperTimestamp,
190                 ratio,
191                 lowerHistEntry,
192                 upperHistEntry);
193 
194         assertBatteryHistEntry(
195             newEntry, 3, upperHistEntry.mPercentOfTotal,
196             /*bootTimestamp=*/ 1200 - 100,
197             /*timestamp=*/ slotTimestamp,
198             /*totalPower=*/ 50 + 0.5 * (80 - 50),
199             /*consumePower=*/ 10 + 0.5 * (20 - 10),
200             /*foregroundUsageTimeInMs=*/ Math.round(100 + 0.5 * (200 - 100)),
201             /*backgroundUsageTimeInMs=*/ Math.round(200 + 0.5 * (300 - 200)),
202             /*batteryLevel=*/ (int) Math.round(90 + 0.5 * (80 - 90)));
203     }
204 
205     @Test
testInterpolate_withoutLowerEntryData_returnExpectedResult()206     public void testInterpolate_withoutLowerEntryData_returnExpectedResult() {
207         final long slotTimestamp = 200L;
208         final long upperTimestamp = 300L;
209         final long lowerTimestamp = 100L;
210         final double ratio = 0.5;
211         final BatteryHistEntry upperHistEntry = createBatteryHistEntry(
212             /*bootTimestamp=*/ 1200L,
213             upperTimestamp,
214             /*totalPower=*/ 80,
215             /*consumePower=*/ 20,
216             /*foregroundUsageTimeInMs=*/ 200,
217             /*backgroundUsageTimeInMs=*/ 300,
218             /*batteryLevel=*/ 80);
219 
220         final BatteryHistEntry newEntry =
221             BatteryHistEntry.interpolate(
222                 slotTimestamp,
223                 upperTimestamp,
224                 ratio,
225                 /*lowerHistEntry=*/ null,
226                 upperHistEntry);
227 
228         assertBatteryHistEntry(
229             newEntry, 3, upperHistEntry.mPercentOfTotal,
230             /*bootTimestamp=*/ 1200 - 100,
231             /*timestamp=*/ slotTimestamp,
232             /*totalPower=*/ 0.5 * 80,
233             /*consumePower=*/ 0.5 * 20,
234             /*foregroundUsageTimeInMs=*/ Math.round(0.5 * 200),
235             /*backgroundUsageTimeInMs=*/ Math.round(0.5 * 300),
236             /*batteryLevel=*/ upperHistEntry.mBatteryLevel);
237     }
238 
createEntry(int consumerType)239     private static BatteryHistEntry createEntry(int consumerType) {
240         return new BatteryHistEntry(getContentValuesWithType(consumerType));
241     }
242 
getContentValuesWithType(int consumerType)243     private static ContentValues getContentValuesWithType(int consumerType) {
244         final ContentValues values = new ContentValues();
245         values.put(BatteryHistEntry.KEY_CONSUMER_TYPE,
246             Integer.valueOf(consumerType));
247         return values;
248     }
249 
assertBatteryHistEntry( BatteryHistEntry entry, int drainType, double percentOfTotal)250     private void assertBatteryHistEntry(
251             BatteryHistEntry entry, int drainType, double percentOfTotal) {
252         assertBatteryHistEntry(
253             entry, drainType, percentOfTotal,
254             /*bootTimestamp=*/ 101L,
255             /*timestamp=*/ 10001L,
256             /*totalPower=*/ 5.1,
257             /*consumePower=*/ 1.1,
258             /*foregroundUsageTimeInMs=*/ 1234L,
259             /*backgroundUsageTimeInMs=*/ 5689L,
260             /*batteryLevel=*/ 12);
261     }
262 
assertBatteryHistEntry( BatteryHistEntry entry, int drainType, double percentOfTotal, long bootTimestamp, long timestamp, double totalPower, double consumePower, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs, int batteryLevel)263     private void assertBatteryHistEntry(
264             BatteryHistEntry entry,
265             int drainType,
266             double percentOfTotal,
267             long bootTimestamp,
268             long timestamp,
269             double totalPower,
270             double consumePower,
271             long foregroundUsageTimeInMs,
272             long backgroundUsageTimeInMs,
273             int batteryLevel) {
274         assertThat(entry.isValidEntry()).isTrue();
275         assertThat(entry.mUid).isEqualTo(1001);
276         assertThat(entry.mUserId).isEqualTo(UserHandle.getUserId(1001));
277         assertThat(entry.mAppLabel).isEqualTo("Settings");
278         assertThat(entry.mPackageName)
279             .isEqualTo("com.google.android.settings.battery");
280         assertThat(entry.mIsHidden).isTrue();
281         assertThat(entry.mBootTimestamp).isEqualTo(bootTimestamp);
282         assertThat(entry.mTimestamp).isEqualTo(timestamp);
283         assertThat(entry.mZoneId).isEqualTo(TimeZone.getDefault().getID());
284         assertThat(entry.mTotalPower).isEqualTo(totalPower);
285         assertThat(entry.mConsumePower).isEqualTo(consumePower);
286         assertThat(entry.mPercentOfTotal).isEqualTo(percentOfTotal);
287         assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(foregroundUsageTimeInMs);
288         assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
289         assertThat(entry.mDrainType).isEqualTo(drainType);
290         assertThat(entry.mConsumerType)
291             .isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
292         assertThat(entry.mBatteryLevel).isEqualTo(batteryLevel);
293         assertThat(entry.mBatteryStatus)
294             .isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
295         assertThat(entry.mBatteryHealth)
296             .isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
297     }
298 
createBatteryHistEntry( long bootTimestamp, long timestamp, double totalPower, double consumePower, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs, int batteryLevel)299     private BatteryHistEntry createBatteryHistEntry(
300             long bootTimestamp,
301             long timestamp,
302             double totalPower,
303             double consumePower,
304             long foregroundUsageTimeInMs,
305             long backgroundUsageTimeInMs,
306             int batteryLevel) {
307         final MatrixCursor cursor = new MatrixCursor(
308             new String[] {
309                 BatteryHistEntry.KEY_UID,
310                 BatteryHistEntry.KEY_USER_ID,
311                 BatteryHistEntry.KEY_APP_LABEL,
312                 BatteryHistEntry.KEY_PACKAGE_NAME,
313                 BatteryHistEntry.KEY_IS_HIDDEN,
314                 BatteryHistEntry.KEY_BOOT_TIMESTAMP,
315                 BatteryHistEntry.KEY_TIMESTAMP,
316                 BatteryHistEntry.KEY_ZONE_ID,
317                 BatteryHistEntry.KEY_TOTAL_POWER,
318                 BatteryHistEntry.KEY_CONSUME_POWER,
319                 BatteryHistEntry.KEY_PERCENT_OF_TOTAL,
320                 BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME,
321                 BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME,
322                 BatteryHistEntry.KEY_DRAIN_TYPE,
323                 BatteryHistEntry.KEY_CONSUMER_TYPE,
324                 BatteryHistEntry.KEY_BATTERY_LEVEL,
325                 BatteryHistEntry.KEY_BATTERY_STATUS,
326                 BatteryHistEntry.KEY_BATTERY_HEALTH});
327         cursor.addRow(
328             new Object[] {
329                 Long.valueOf(1001),
330                 Long.valueOf(UserHandle.getUserId(1001)),
331                 "Settings",
332                 "com.google.android.settings.battery",
333                 Integer.valueOf(1),
334                 Long.valueOf(bootTimestamp),
335                 Long.valueOf(timestamp),
336                 TimeZone.getDefault().getID(),
337                 Double.valueOf(totalPower),
338                 Double.valueOf(consumePower),
339                 Double.valueOf(0.3),
340                 Long.valueOf(foregroundUsageTimeInMs),
341                 Long.valueOf(backgroundUsageTimeInMs),
342                 Integer.valueOf(3),
343                 Integer.valueOf(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY),
344                 Integer.valueOf(batteryLevel),
345                 Integer.valueOf(BatteryManager.BATTERY_STATUS_FULL),
346                 Integer.valueOf(BatteryManager.BATTERY_HEALTH_COLD)});
347         cursor.moveToFirst();
348         return new BatteryHistEntry(cursor);
349     }
350 }
351