• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
19 import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND;
20 import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE;
21 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
22 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING;
23 import static com.google.common.truth.Truth.assertThat;
24 import static org.mockito.Matchers.any;
25 import static org.mockito.Matchers.anyInt;
26 import static org.mockito.Matchers.anyLong;
27 import static org.mockito.Matchers.eq;
28 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
29 import static org.mockito.Mockito.doNothing;
30 import static org.mockito.Mockito.doReturn;
31 import static org.mockito.Mockito.doThrow;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.spy;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
37 
38 import android.app.AppOpsManager;
39 import android.content.Context;
40 import android.content.pm.ActivityInfo;
41 import android.content.pm.ApplicationInfo;
42 import android.content.pm.PackageManager;
43 import android.content.pm.ResolveInfo;
44 import android.os.BatteryStats;
45 import android.os.Build;
46 import android.os.Bundle;
47 import android.os.Process;
48 import android.os.SystemClock;
49 import android.os.UserManager;
50 import android.text.format.DateUtils;
51 
52 import com.android.internal.os.BatterySipper;
53 import com.android.internal.os.BatteryStatsHelper;
54 import com.android.settings.R;
55 import com.android.settings.fuelgauge.anomaly.Anomaly;
56 import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
57 import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
58 import com.android.settings.testutils.FakeFeatureFactory;
59 import com.android.settings.testutils.SettingsRobolectricTestRunner;
60 import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
61 
62 import org.junit.Before;
63 import org.junit.Test;
64 import org.junit.runner.RunWith;
65 import org.mockito.Answers;
66 import org.mockito.Mock;
67 import org.mockito.MockitoAnnotations;
68 import org.robolectric.RuntimeEnvironment;
69 
70 import java.util.ArrayList;
71 import java.util.List;
72 
73 @RunWith(SettingsRobolectricTestRunner.class)
74 public class BatteryUtilsTest {
75 
76     // unit that used to converted ms to us
77     private static final long UNIT = 1000;
78     private static final long TIME_STATE_TOP = 1500 * UNIT;
79     private static final long TIME_STATE_FOREGROUND_SERVICE = 2000 * UNIT;
80     private static final long TIME_STATE_TOP_SLEEPING = 2500 * UNIT;
81     private static final long TIME_STATE_FOREGROUND = 3000 * UNIT;
82     private static final long TIME_STATE_BACKGROUND = 6000 * UNIT;
83     private static final long TIME_FOREGROUND_ZERO = 0;
84     private static final long TIME_FOREGROUND = 100 * DateUtils.MINUTE_IN_MILLIS;
85     private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 120 * 60 * 1000;
86     private static final long TIME_SINCE_LAST_FULL_CHARGE_US =
87             TIME_SINCE_LAST_FULL_CHARGE_MS * 1000;
88 
89     private static final int UID = 12345;
90     private static final long TIME_EXPECTED_FOREGROUND = 1500;
91     private static final long TIME_EXPECTED_BACKGROUND = 6000;
92     private static final long TIME_EXPECTED_ALL = 7500;
93     private static final double BATTERY_SCREEN_USAGE = 300;
94     private static final double BATTERY_IDLE_USAGE = 600;
95     private static final double BATTERY_SYSTEM_USAGE = 600;
96     private static final double BATTERY_OVERACCOUNTED_USAGE = 500;
97     private static final double BATTERY_UNACCOUNTED_USAGE = 700;
98     private static final double BATTERY_APP_USAGE = 100;
99     private static final double BATTERY_WIFI_USAGE = 200;
100     private static final double BATTERY_BLUETOOTH_USAGE = 300;
101     private static final double TOTAL_BATTERY_USAGE = 1000;
102     private static final double HIDDEN_USAGE = 200;
103     private static final int DISCHARGE_AMOUNT = 80;
104     private static final double PERCENT_SYSTEM_USAGE = 60;
105     private static final double PRECISION = 0.001;
106     private static final int SDK_VERSION = Build.VERSION_CODES.L;
107     private static final String PACKAGE_NAME = "com.android.app";
108     private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
109     private static final String LOW_SDK_PACKAGE = "com.android.package.low";
110 
111     private static final String INFO_EXCESSIVE = "anomaly_type=4,auto_restriction=false";
112     private static final String INFO_WAKELOCK = "anomaly_type=1,auto_restriction=false";
113 
114     @Mock
115     private BatteryStats.Uid mUid;
116     @Mock
117     private BatteryStats.Timer mTimer;
118     @Mock
119     private BatterySipper mNormalBatterySipper;
120     @Mock
121     private BatterySipper mWifiBatterySipper;
122     @Mock
123     private BatterySipper mBluetoothBatterySipper;
124     @Mock
125     private BatterySipper mScreenBatterySipper;
126     @Mock
127     private BatterySipper mOvercountedBatterySipper;
128     @Mock
129     private BatterySipper mUnaccountedBatterySipper;
130     @Mock
131     private BatterySipper mSystemBatterySipper;
132     @Mock
133     private BatterySipper mCellBatterySipper;
134     @Mock
135     private BatterySipper mIdleBatterySipper;
136     @Mock
137     private Bundle mBundle;
138     @Mock
139     private UserManager mUserManager;
140     @Mock
141     private PackageManager mPackageManager;
142     @Mock
143     private AppOpsManager mAppOpsManager;
144     @Mock
145     private ApplicationInfo mApplicationInfo;
146     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
147     private BatteryStatsHelper mBatteryStatsHelper;
148     @Mock
149     private ApplicationInfo mHighApplicationInfo;
150     @Mock
151     private ApplicationInfo mLowApplicationInfo;
152     @Mock
153     private PowerWhitelistBackend mPowerWhitelistBackend;
154     private AnomalyInfo mAnomalyInfo;
155     private BatteryUtils mBatteryUtils;
156     private FakeFeatureFactory mFeatureFactory;
157     private PowerUsageFeatureProvider mProvider;
158     private List<BatterySipper> mUsageList;
159 
160     @Before
setUp()161     public void setUp() throws PackageManager.NameNotFoundException {
162         MockitoAnnotations.initMocks(this);
163 
164         mFeatureFactory = FakeFeatureFactory.setupForTest();
165         mProvider = mFeatureFactory.powerUsageFeatureProvider;
166 
167         doReturn(TIME_STATE_TOP).when(mUid).getProcessStateTime(eq(PROCESS_STATE_TOP), anyLong(),
168                 anyInt());
169         doReturn(TIME_STATE_FOREGROUND_SERVICE).when(mUid).getProcessStateTime(
170                 eq(PROCESS_STATE_FOREGROUND_SERVICE), anyLong(), anyInt());
171         doReturn(TIME_STATE_TOP_SLEEPING).when(mUid).getProcessStateTime(
172                 eq(PROCESS_STATE_TOP_SLEEPING), anyLong(), anyInt());
173         doReturn(TIME_STATE_FOREGROUND).when(mUid).getProcessStateTime(eq(PROCESS_STATE_FOREGROUND),
174                 anyLong(), anyInt());
175         doReturn(TIME_STATE_BACKGROUND).when(mUid).getProcessStateTime(eq(PROCESS_STATE_BACKGROUND),
176                 anyLong(), anyInt());
177         when(mBatteryStatsHelper.getStats().computeBatteryRealtime(anyLong(), anyInt())).thenReturn(
178                 TIME_SINCE_LAST_FULL_CHARGE_US);
179 
180         when(mPackageManager.getApplicationInfo(eq(HIGH_SDK_PACKAGE), anyInt()))
181                 .thenReturn(mHighApplicationInfo);
182         when(mPackageManager.getApplicationInfo(eq(LOW_SDK_PACKAGE), anyInt()))
183                 .thenReturn(mLowApplicationInfo);
184         mHighApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
185         mLowApplicationInfo.targetSdkVersion = Build.VERSION_CODES.L;
186 
187         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
188         mNormalBatterySipper.totalPowerMah = TOTAL_BATTERY_USAGE;
189         doReturn(UID).when(mNormalBatterySipper).getUid();
190 
191         mWifiBatterySipper.drainType = BatterySipper.DrainType.WIFI;
192         mWifiBatterySipper.totalPowerMah = BATTERY_WIFI_USAGE;
193 
194         mBluetoothBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
195         mBluetoothBatterySipper.totalPowerMah = BATTERY_BLUETOOTH_USAGE;
196 
197         mScreenBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
198         mScreenBatterySipper.totalPowerMah = BATTERY_SCREEN_USAGE;
199 
200         mSystemBatterySipper.drainType = BatterySipper.DrainType.APP;
201         mSystemBatterySipper.totalPowerMah = BATTERY_SYSTEM_USAGE;
202         when(mSystemBatterySipper.getUid()).thenReturn(Process.SYSTEM_UID);
203 
204         mOvercountedBatterySipper.drainType = BatterySipper.DrainType.OVERCOUNTED;
205         mOvercountedBatterySipper.totalPowerMah = BATTERY_OVERACCOUNTED_USAGE;
206 
207         mUnaccountedBatterySipper.drainType = BatterySipper.DrainType.UNACCOUNTED;
208         mUnaccountedBatterySipper.totalPowerMah = BATTERY_UNACCOUNTED_USAGE;
209 
210         mIdleBatterySipper.drainType = BatterySipper.DrainType.IDLE;
211         mIdleBatterySipper.totalPowerMah = BATTERY_IDLE_USAGE;
212 
213         final Context shadowContext = spy(RuntimeEnvironment.application);
214         doReturn(mPackageManager).when(shadowContext).getPackageManager();
215         doReturn(mAppOpsManager).when(shadowContext).getSystemService(Context.APP_OPS_SERVICE);
216         mBatteryUtils = spy(new BatteryUtils(shadowContext));
217         mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
218         doReturn(0L).when(mBatteryUtils)
219             .getForegroundServiceTotalTimeUs(any(BatteryStats.Uid.class), anyLong());
220         mAnomalyInfo = new AnomalyInfo(INFO_WAKELOCK);
221 
222         mUsageList = new ArrayList<>();
223         mUsageList.add(mNormalBatterySipper);
224         mUsageList.add(mScreenBatterySipper);
225         mUsageList.add(mCellBatterySipper);
226         when(mBatteryStatsHelper.getUsageList()).thenReturn(mUsageList);
227         when(mBatteryStatsHelper.getTotalPower())
228             .thenReturn(TOTAL_BATTERY_USAGE + BATTERY_SCREEN_USAGE);
229         when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt()))
230             .thenReturn(DISCHARGE_AMOUNT);
231     }
232 
233     @Test
testGetProcessTimeMs_typeForeground_timeCorrect()234     public void testGetProcessTimeMs_typeForeground_timeCorrect() {
235         doReturn(TIME_STATE_FOREGROUND + 500).when(mBatteryUtils)
236             .getForegroundActivityTotalTimeUs(eq(mUid), anyLong());
237 
238         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.FOREGROUND, mUid,
239                 BatteryStats.STATS_SINCE_CHARGED);
240 
241         assertThat(time).isEqualTo(TIME_EXPECTED_FOREGROUND);
242     }
243 
244     @Test
testGetProcessTimeMs_typeBackground_timeCorrect()245     public void testGetProcessTimeMs_typeBackground_timeCorrect() {
246         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.BACKGROUND, mUid,
247                 BatteryStats.STATS_SINCE_CHARGED);
248 
249         assertThat(time).isEqualTo(TIME_EXPECTED_BACKGROUND);
250     }
251 
252     @Test
testGetProcessTimeMs_typeAll_timeCorrect()253     public void testGetProcessTimeMs_typeAll_timeCorrect() {
254         doReturn(TIME_STATE_FOREGROUND + 500).when(mBatteryUtils)
255             .getForegroundActivityTotalTimeUs(eq(mUid), anyLong());
256 
257         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.ALL, mUid,
258                 BatteryStats.STATS_SINCE_CHARGED);
259 
260         assertThat(time).isEqualTo(TIME_EXPECTED_ALL);
261     }
262 
263     @Test
testGetProcessTimeMs_uidNull_returnZero()264     public void testGetProcessTimeMs_uidNull_returnZero() {
265         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.ALL, null,
266                 BatteryStats.STATS_SINCE_CHARGED);
267 
268         assertThat(time).isEqualTo(0);
269     }
270 
271     @Test
testRemoveHiddenBatterySippers_ContainsHiddenSippers_RemoveAndReturnValue()272     public void testRemoveHiddenBatterySippers_ContainsHiddenSippers_RemoveAndReturnValue() {
273         final List<BatterySipper> sippers = new ArrayList<>();
274         sippers.add(mNormalBatterySipper);
275         sippers.add(mScreenBatterySipper);
276         sippers.add(mSystemBatterySipper);
277         sippers.add(mOvercountedBatterySipper);
278         sippers.add(mUnaccountedBatterySipper);
279         sippers.add(mWifiBatterySipper);
280         sippers.add(mBluetoothBatterySipper);
281         sippers.add(mIdleBatterySipper);
282         when(mProvider.isTypeSystem(mSystemBatterySipper)).thenReturn(true);
283         doNothing().when(mBatteryUtils).smearScreenBatterySipper(any(), any());
284 
285         final double totalUsage = mBatteryUtils.removeHiddenBatterySippers(sippers);
286 
287         assertThat(sippers).containsExactly(mNormalBatterySipper);
288         assertThat(totalUsage).isWithin(PRECISION).of(BATTERY_SYSTEM_USAGE);
289     }
290 
291     @Test
testShouldHideSipper_TypeUnAccounted_ReturnTrue()292     public void testShouldHideSipper_TypeUnAccounted_ReturnTrue() {
293         mNormalBatterySipper.drainType = BatterySipper.DrainType.UNACCOUNTED;
294         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
295     }
296 
297     @Test
testShouldHideSipper_TypeOverAccounted_ReturnTrue()298     public void testShouldHideSipper_TypeOverAccounted_ReturnTrue() {
299         mNormalBatterySipper.drainType = BatterySipper.DrainType.OVERCOUNTED;
300         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
301     }
302 
303     @Test
testShouldHideSipper_TypeIdle_ReturnTrue()304     public void testShouldHideSipper_TypeIdle_ReturnTrue() {
305         mNormalBatterySipper.drainType = BatterySipper.DrainType.IDLE;
306         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
307     }
308 
309     @Test
testShouldHideSipper_TypeCell_ReturnTrue()310     public void testShouldHideSipper_TypeCell_ReturnTrue() {
311         mNormalBatterySipper.drainType = BatterySipper.DrainType.CELL;
312         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
313     }
314 
315     @Test
testShouldHideSipper_TypeScreen_ReturnTrue()316     public void testShouldHideSipper_TypeScreen_ReturnTrue() {
317         mNormalBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
318         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
319     }
320 
321     @Test
testShouldHideSipper_TypeWifi_ReturnTrue()322     public void testShouldHideSipper_TypeWifi_ReturnTrue() {
323         mNormalBatterySipper.drainType = BatterySipper.DrainType.WIFI;
324         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
325     }
326 
327     @Test
testShouldHideSipper_TypeBluetooth_ReturnTrue()328     public void testShouldHideSipper_TypeBluetooth_ReturnTrue() {
329         mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
330         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
331     }
332 
333     @Test
testShouldHideSipper_TypeSystem_ReturnTrue()334     public void testShouldHideSipper_TypeSystem_ReturnTrue() {
335         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
336         when(mNormalBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
337         when(mProvider.isTypeSystem(any())).thenReturn(true);
338         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
339     }
340 
341     @Test
testShouldHideSipper_UidNormal_ReturnFalse()342     public void testShouldHideSipper_UidNormal_ReturnFalse() {
343         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
344         when(mNormalBatterySipper.getUid()).thenReturn(UID);
345         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isFalse();
346     }
347 
348     @Test
testShouldHideSipper_TypeService_ReturnTrue()349     public void testShouldHideSipper_TypeService_ReturnTrue() {
350         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
351         when(mNormalBatterySipper.getUid()).thenReturn(UID);
352         when(mProvider.isTypeService(any())).thenReturn(true);
353 
354         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
355     }
356 
357     @Test
testCalculateBatteryPercent()358     public void testCalculateBatteryPercent() {
359         assertThat(mBatteryUtils.calculateBatteryPercent(BATTERY_SYSTEM_USAGE, TOTAL_BATTERY_USAGE,
360                 HIDDEN_USAGE, DISCHARGE_AMOUNT))
361                 .isWithin(PRECISION).of(PERCENT_SYSTEM_USAGE);
362     }
363 
364     @Test
testSmearScreenBatterySipper()365     public void testSmearScreenBatterySipper() {
366         final BatterySipper sipperNull = createTestSmearBatterySipper(TIME_FOREGROUND_ZERO,
367                 BATTERY_APP_USAGE, 0 /* uid */, true /* isUidNull */);
368         final BatterySipper sipperBg = createTestSmearBatterySipper(TIME_FOREGROUND_ZERO,
369                 BATTERY_APP_USAGE, 1 /* uid */, false /* isUidNull */);
370         final BatterySipper sipperFg = createTestSmearBatterySipper(TIME_FOREGROUND,
371                 BATTERY_APP_USAGE, 2 /* uid */, false /* isUidNull */);
372         final BatterySipper sipperFg2 = createTestSmearBatterySipper(TIME_FOREGROUND,
373                 BATTERY_APP_USAGE, 3 /* uid */, false /* isUidNull */);
374 
375         final List<BatterySipper> sippers = new ArrayList<>();
376         sippers.add(sipperNull);
377         sippers.add(sipperBg);
378         sippers.add(sipperFg);
379         sippers.add(sipperFg2);
380 
381         mBatteryUtils.smearScreenBatterySipper(sippers, mScreenBatterySipper);
382 
383         assertThat(sipperNull.totalPowerMah).isWithin(PRECISION).of(BATTERY_APP_USAGE);
384         assertThat(sipperBg.totalPowerMah).isWithin(PRECISION).of(BATTERY_APP_USAGE);
385         assertThat(sipperFg.totalPowerMah).isWithin(PRECISION).of(
386                 BATTERY_APP_USAGE + BATTERY_SCREEN_USAGE / 2);
387         assertThat(sipperFg2.totalPowerMah).isWithin(PRECISION).of(
388                 BATTERY_APP_USAGE + BATTERY_SCREEN_USAGE / 2);
389     }
390 
391     @Test
testSmearScreenBatterySipper_screenSipperNull_shouldNotCrash()392     public void testSmearScreenBatterySipper_screenSipperNull_shouldNotCrash() {
393         final BatterySipper sipperFg = createTestSmearBatterySipper(TIME_FOREGROUND,
394                 BATTERY_APP_USAGE, 2 /* uid */, false /* isUidNull */);
395 
396         final List<BatterySipper> sippers = new ArrayList<>();
397         sippers.add(sipperFg);
398 
399         // Shouldn't crash
400         mBatteryUtils.smearScreenBatterySipper(sippers, null /* screenSipper */);
401     }
402 
403     @Test
testCalculateRunningTimeBasedOnStatsType()404     public void testCalculateRunningTimeBasedOnStatsType() {
405         assertThat(mBatteryUtils.calculateRunningTimeBasedOnStatsType(mBatteryStatsHelper,
406                 BatteryStats.STATS_SINCE_CHARGED)).isEqualTo(TIME_SINCE_LAST_FULL_CHARGE_MS);
407     }
408 
409     @Test
testSortUsageList()410     public void testSortUsageList() {
411         final List<BatterySipper> sippers = new ArrayList<>();
412         sippers.add(mNormalBatterySipper);
413         sippers.add(mScreenBatterySipper);
414         sippers.add(mSystemBatterySipper);
415 
416         mBatteryUtils.sortUsageList(sippers);
417 
418         assertThat(sippers).containsExactly(mNormalBatterySipper, mSystemBatterySipper,
419                 mScreenBatterySipper);
420     }
421 
422     @Test
testCalculateLastFullChargeTime()423     public void testCalculateLastFullChargeTime() {
424         final long currentTimeMs = System.currentTimeMillis();
425         when(mBatteryStatsHelper.getStats().getStartClockTime()).thenReturn(
426                 currentTimeMs - TIME_SINCE_LAST_FULL_CHARGE_MS);
427 
428         assertThat(mBatteryUtils.calculateLastFullChargeTime(
429                 mBatteryStatsHelper, currentTimeMs)).isEqualTo(TIME_SINCE_LAST_FULL_CHARGE_MS);
430     }
431 
432     @Test
testGetSummaryResIdFromAnomalyType()433     public void testGetSummaryResIdFromAnomalyType() {
434         assertThat(mBatteryUtils.getSummaryResIdFromAnomalyType(Anomaly.AnomalyType.WAKE_LOCK))
435                 .isEqualTo(R.string.battery_abnormal_wakelock_summary);
436         assertThat(mBatteryUtils.getSummaryResIdFromAnomalyType(Anomaly.AnomalyType.WAKEUP_ALARM))
437                 .isEqualTo(R.string.battery_abnormal_wakeup_alarm_summary);
438         assertThat(mBatteryUtils.getSummaryResIdFromAnomalyType(Anomaly.AnomalyType.BLUETOOTH_SCAN))
439                 .isEqualTo(R.string.battery_abnormal_location_summary);
440     }
441 
442     @Test
testGetForegroundActivityTotalTimeMs_returnMilliseconds()443     public void testGetForegroundActivityTotalTimeMs_returnMilliseconds() {
444         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
445         doReturn(mTimer).when(mUid).getForegroundActivityTimer();
446         doReturn(TIME_SINCE_LAST_FULL_CHARGE_US).when(mTimer)
447                 .getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
448 
449         assertThat(mBatteryUtils.getForegroundActivityTotalTimeUs(mUid, rawRealtimeUs)).isEqualTo(
450                 TIME_SINCE_LAST_FULL_CHARGE_US);
451     }
452 
453     @Test
testGetTargetSdkVersion_packageExist_returnSdk()454     public void testGetTargetSdkVersion_packageExist_returnSdk() throws
455             PackageManager.NameNotFoundException {
456         doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(PACKAGE_NAME,
457                 PackageManager.GET_META_DATA);
458         mApplicationInfo.targetSdkVersion = SDK_VERSION;
459 
460         assertThat(mBatteryUtils.getTargetSdkVersion(PACKAGE_NAME)).isEqualTo(SDK_VERSION);
461     }
462 
463     @Test
testGetTargetSdkVersion_packageNotExist_returnSdkNull()464     public void testGetTargetSdkVersion_packageNotExist_returnSdkNull() throws
465             PackageManager.NameNotFoundException {
466         doThrow(new PackageManager.NameNotFoundException()).when(
467                 mPackageManager).getApplicationInfo(PACKAGE_NAME, PackageManager.GET_META_DATA);
468 
469         assertThat(mBatteryUtils.getTargetSdkVersion(PACKAGE_NAME)).isEqualTo(
470                 BatteryUtils.SDK_NULL);
471     }
472 
473     @Test
testBackgroundRestrictionOn_restrictionOn_returnTrue()474     public void testBackgroundRestrictionOn_restrictionOn_returnTrue() {
475         doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager).checkOpNoThrow(
476                 AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME);
477 
478         assertThat(mBatteryUtils.isBackgroundRestrictionEnabled(SDK_VERSION, UID,
479                 PACKAGE_NAME)).isTrue();
480     }
481 
482     @Test
testBackgroundRestrictionOn_restrictionOff_returnFalse()483     public void testBackgroundRestrictionOn_restrictionOff_returnFalse() {
484         doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).checkOpNoThrow(
485                 AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME);
486 
487         assertThat(mBatteryUtils.isBackgroundRestrictionEnabled(SDK_VERSION, UID, PACKAGE_NAME))
488             .isFalse();
489     }
490 
createTestSmearBatterySipper( long topTime, double totalPowerMah, int uidCode, boolean isUidNull)491     private BatterySipper createTestSmearBatterySipper(
492         long topTime, double totalPowerMah, int uidCode, boolean isUidNull) {
493         final BatterySipper sipper = mock(BatterySipper.class);
494         sipper.drainType = BatterySipper.DrainType.APP;
495         sipper.totalPowerMah = totalPowerMah;
496         doReturn(uidCode).when(sipper).getUid();
497         if (!isUidNull) {
498             final BatteryStats.Uid uid = mock(BatteryStats.Uid.class, RETURNS_DEEP_STUBS);
499             doReturn(topTime).when(mBatteryUtils).getProcessTimeMs(
500                     eq(BatteryUtils.StatusType.SCREEN_USAGE), eq(uid), anyInt());
501             doReturn(uidCode).when(uid).getUid();
502             sipper.uidObj = uid;
503         }
504 
505         return sipper;
506     }
507 
508     @Test
testInitBatteryStatsHelper_init()509     public void testInitBatteryStatsHelper_init() {
510         mBatteryUtils.initBatteryStatsHelper(mBatteryStatsHelper, mBundle, mUserManager);
511 
512         verify(mBatteryStatsHelper).create(mBundle);
513         verify(mBatteryStatsHelper).refreshStats(BatteryStats.STATS_SINCE_CHARGED,
514                 mUserManager.getUserProfiles());
515     }
516 
517     @Test
testFindBatterySipperByType_findTypeScreen()518     public void testFindBatterySipperByType_findTypeScreen() {
519         BatterySipper sipper = mBatteryUtils.findBatterySipperByType(mUsageList,
520                 BatterySipper.DrainType.SCREEN);
521 
522         assertThat(sipper).isSameAs(mScreenBatterySipper);
523     }
524 
525     @Test
testFindBatterySipperByType_findTypeApp()526     public void testFindBatterySipperByType_findTypeApp() {
527         BatterySipper sipper = mBatteryUtils.findBatterySipperByType(mUsageList,
528                 BatterySipper.DrainType.APP);
529 
530         assertThat(sipper).isSameAs(mNormalBatterySipper);
531     }
532 
533     @Test
testCalculateScreenUsageTime_returnCorrectTime()534     public void testCalculateScreenUsageTime_returnCorrectTime() {
535         mScreenBatterySipper.usageTimeMs = TIME_EXPECTED_FOREGROUND;
536 
537         assertThat(mBatteryUtils.calculateScreenUsageTime(mBatteryStatsHelper)).isEqualTo(
538                 TIME_EXPECTED_FOREGROUND);
539     }
540 
541     @Test
testIsPreOApp_SdkLowerThanO_ReturnTrue()542     public void testIsPreOApp_SdkLowerThanO_ReturnTrue() {
543         assertThat(mBatteryUtils.isPreOApp(LOW_SDK_PACKAGE)).isTrue();
544     }
545 
546     @Test
testIsPreOApp_SdkLargerOrEqualThanO_ReturnFalse()547     public void testIsPreOApp_SdkLargerOrEqualThanO_ReturnFalse() {
548         assertThat(mBatteryUtils.isPreOApp(HIGH_SDK_PACKAGE)).isFalse();
549     }
550 
551     @Test
testIsPreOApp_containPreOApp_ReturnTrue()552     public void testIsPreOApp_containPreOApp_ReturnTrue() {
553         assertThat(
554                 mBatteryUtils.isPreOApp(new String[]{HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE})).isTrue();
555     }
556 
557     @Test
testIsPreOApp_emptyList_ReturnFalse()558     public void testIsPreOApp_emptyList_ReturnFalse() {
559         assertThat(mBatteryUtils.isPreOApp(new String[]{})).isFalse();
560     }
561 
562     @Test
testSetForceAppStandby_forcePreOApp_forceTwoRestrictions()563     public void testSetForceAppStandby_forcePreOApp_forceTwoRestrictions() {
564         mBatteryUtils.setForceAppStandby(UID, LOW_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
565 
566         // Restrict both OP_RUN_IN_BACKGROUND and OP_RUN_ANY_IN_BACKGROUND
567         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID, LOW_SDK_PACKAGE,
568                 AppOpsManager.MODE_IGNORED);
569         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID, LOW_SDK_PACKAGE,
570                 AppOpsManager.MODE_IGNORED);
571     }
572 
573     @Test
testSetForceAppStandby_forceOApp_forceOneRestriction()574     public void testSetForceAppStandby_forceOApp_forceOneRestriction() {
575         mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
576 
577         // Don't restrict OP_RUN_IN_BACKGROUND because it is already been restricted for O app
578         verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID,
579                 HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
580         // Restrict OP_RUN_ANY_IN_BACKGROUND
581         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
582                 HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
583     }
584 
585     @Test
testIsForceAppStandbyEnabled_enabled_returnTrue()586     public void testIsForceAppStandbyEnabled_enabled_returnTrue() {
587         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
588                 PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_IGNORED);
589 
590         assertThat(mBatteryUtils.isForceAppStandbyEnabled(UID, PACKAGE_NAME)).isTrue();
591     }
592 
593     @Test
testIsForceAppStandbyEnabled_disabled_returnFalse()594     public void testIsForceAppStandbyEnabled_disabled_returnFalse() {
595         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
596                 PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_ALLOWED);
597 
598         assertThat(mBatteryUtils.isForceAppStandbyEnabled(UID, PACKAGE_NAME)).isFalse();
599     }
600 
601     @Test
testShouldHideAnomaly_systemAppWithLauncher_returnTrue()602     public void testShouldHideAnomaly_systemAppWithLauncher_returnTrue() {
603         final List<ResolveInfo> resolveInfos = new ArrayList<>();
604         final ResolveInfo resolveInfo = new ResolveInfo();
605         resolveInfo.activityInfo = new ActivityInfo();
606         resolveInfo.activityInfo.packageName = HIGH_SDK_PACKAGE;
607 
608         doReturn(resolveInfos).when(mPackageManager).queryIntentActivities(any(), anyInt());
609         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
610         mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
611 
612         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
613                 mAnomalyInfo)).isTrue();
614     }
615 
616     @Test
testShouldHideAnomaly_systemAppWithoutLauncher_returnTrue()617     public void testShouldHideAnomaly_systemAppWithoutLauncher_returnTrue() {
618         doReturn(new ArrayList<>()).when(mPackageManager).queryIntentActivities(any(), anyInt());
619         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
620         mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
621 
622         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
623                 mAnomalyInfo)).isTrue();
624     }
625 
626     @Test
testShouldHideAnomaly_systemUid_returnTrue()627     public void testShouldHideAnomaly_systemUid_returnTrue() {
628         final int systemUid = Process.ROOT_UID;
629         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(systemUid);
630 
631         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, systemUid,
632                 mAnomalyInfo)).isTrue();
633     }
634 
635     @Test
testShouldHideAnomaly_AppInDozeList_returnTrue()636     public void testShouldHideAnomaly_AppInDozeList_returnTrue() {
637         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
638         doReturn(true).when(mPowerWhitelistBackend).isWhitelisted(new String[]{HIGH_SDK_PACKAGE});
639 
640         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
641                 mAnomalyInfo)).isTrue();
642     }
643 
644     @Test
testShouldHideAnomaly_normalApp_returnFalse()645     public void testShouldHideAnomaly_normalApp_returnFalse() {
646         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
647 
648         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
649                 mAnomalyInfo)).isFalse();
650     }
651 
652     @Test
testShouldHideAnomaly_excessivePriorOApp_returnFalse()653     public void testShouldHideAnomaly_excessivePriorOApp_returnFalse() {
654         doReturn(new String[]{LOW_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
655         mAnomalyInfo = new AnomalyInfo(INFO_EXCESSIVE);
656 
657         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
658                 mAnomalyInfo)).isFalse();
659     }
660 
661     @Test
testShouldHideAnomaly_excessiveOApp_returnTrue()662     public void testShouldHideAnomaly_excessiveOApp_returnTrue() {
663         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
664         mAnomalyInfo = new AnomalyInfo(INFO_EXCESSIVE);
665 
666         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
667                 mAnomalyInfo)).isTrue();
668     }
669 }
670