• 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 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.ArgumentMatchers.anyLong;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.ArgumentMatchers.nullable;
31 import static org.mockito.Mockito.doReturn;
32 import static org.mockito.Mockito.doThrow;
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.BroadcastReceiver;
40 import android.content.Context;
41 import android.content.Intent;
42 import android.content.IntentFilter;
43 import android.content.pm.ActivityInfo;
44 import android.content.pm.ApplicationInfo;
45 import android.content.pm.PackageManager;
46 import android.content.pm.ResolveInfo;
47 import android.os.BatteryConsumer;
48 import android.os.BatteryStats;
49 import android.os.BatteryStatsManager;
50 import android.os.BatteryUsageStats;
51 import android.os.Build;
52 import android.os.Process;
53 import android.os.SystemClock;
54 
55 import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
56 import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
57 import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
58 import com.android.settings.testutils.FakeFeatureFactory;
59 import com.android.settings.testutils.shadow.ShadowThreadUtils;
60 import com.android.settingslib.fuelgauge.Estimate;
61 import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
62 
63 import org.junit.Before;
64 import org.junit.Ignore;
65 import org.junit.Test;
66 import org.junit.runner.RunWith;
67 import org.mockito.Answers;
68 import org.mockito.Mock;
69 import org.mockito.MockitoAnnotations;
70 import org.robolectric.RobolectricTestRunner;
71 import org.robolectric.RuntimeEnvironment;
72 
73 import java.util.ArrayList;
74 import java.util.List;
75 
76 @RunWith(RobolectricTestRunner.class)
77 public class BatteryUtilsTest {
78 
79     private static final String TAG = "BatteryUtilsTest";
80 
81     // unit that used to converted ms to us
82     private static final long UNIT = 1000;
83     private static final long TIME_STATE_TOP = 1500 * UNIT;
84     private static final long TIME_STATE_FOREGROUND_SERVICE = 2000 * UNIT;
85     private static final long TIME_STATE_TOP_SLEEPING = 2500 * UNIT;
86     private static final long TIME_STATE_FOREGROUND = 3000 * UNIT;
87     private static final long TIME_STATE_BACKGROUND = 6000 * UNIT;
88     private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 120 * 60 * 1000;
89     private static final long TIME_SINCE_LAST_FULL_CHARGE_US =
90             TIME_SINCE_LAST_FULL_CHARGE_MS * 1000;
91 
92     private static final int UID = 12345;
93     private static final long TIME_EXPECTED_FOREGROUND = 1500;
94     private static final long TIME_EXPECTED_BACKGROUND = 6000;
95     private static final long TIME_EXPECTED_ALL = 7500;
96     private static final double BATTERY_SYSTEM_USAGE = 600;
97     private static final double TOTAL_BATTERY_USAGE = 1000;
98     private static final int DISCHARGE_AMOUNT = 80;
99     private static final double PERCENT_SYSTEM_USAGE = 48;
100     private static final double PRECISION = 0.001;
101     private static final int SDK_VERSION = Build.VERSION_CODES.L;
102     private static final String PACKAGE_NAME = "com.android.app";
103     private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
104     private static final String LOW_SDK_PACKAGE = "com.android.package.low";
105 
106     private static final String INFO_EXCESSIVE = "anomaly_type=4,auto_restriction=false";
107     private static final String INFO_WAKELOCK = "anomaly_type=1,auto_restriction=false";
108 
109     @Mock
110     private BatteryStats.Uid mUid;
111     @Mock
112     private BatteryStats.Timer mTimer;
113     @Mock
114     private BatteryUsageStats mBatteryUsageStats;
115     @Mock
116     private BatteryConsumer mAggregateBatteryConsumer;
117     @Mock
118     private BatteryInfo mBatteryInfo;
119     @Mock
120     private PackageManager mPackageManager;
121     @Mock
122     private AppOpsManager mAppOpsManager;
123     @Mock
124     private ApplicationInfo mApplicationInfo;
125     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
126     private BatteryStatsManager mBatteryStatsManager;
127     @Mock
128     private ApplicationInfo mHighApplicationInfo;
129     @Mock
130     private ApplicationInfo mLowApplicationInfo;
131     @Mock
132     private PowerAllowlistBackend mPowerAllowlistBackend;
133     @Mock
134     private BatteryDatabaseManager mBatteryDatabaseManager;
135     private AnomalyInfo mAnomalyInfo;
136     private BatteryUtils mBatteryUtils;
137     private FakeFeatureFactory mFeatureFactory;
138     private PowerUsageFeatureProvider mProvider;
139     private Context mContext;
140 
141     @Before
setUp()142     public void setUp() throws PackageManager.NameNotFoundException {
143         MockitoAnnotations.initMocks(this);
144 
145         mFeatureFactory = FakeFeatureFactory.setupForTest();
146         mProvider = mFeatureFactory.powerUsageFeatureProvider;
147 
148         doReturn(TIME_STATE_TOP).when(mUid).getProcessStateTime(eq(PROCESS_STATE_TOP), anyLong(),
149                 anyInt());
150         doReturn(TIME_STATE_FOREGROUND_SERVICE).when(mUid).getProcessStateTime(
151                 eq(PROCESS_STATE_FOREGROUND_SERVICE), anyLong(), anyInt());
152         doReturn(TIME_STATE_TOP_SLEEPING).when(mUid).getProcessStateTime(
153                 eq(PROCESS_STATE_TOP_SLEEPING), anyLong(), anyInt());
154         doReturn(TIME_STATE_FOREGROUND).when(mUid).getProcessStateTime(eq(PROCESS_STATE_FOREGROUND),
155                 anyLong(), anyInt());
156         doReturn(TIME_STATE_BACKGROUND).when(mUid).getProcessStateTime(eq(PROCESS_STATE_BACKGROUND),
157                 anyLong(), anyInt());
158 
159         when(mPackageManager.getApplicationInfo(eq(HIGH_SDK_PACKAGE), anyInt()))
160                 .thenReturn(mHighApplicationInfo);
161         when(mPackageManager.getApplicationInfo(eq(LOW_SDK_PACKAGE), anyInt()))
162                 .thenReturn(mLowApplicationInfo);
163         mHighApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
164         mLowApplicationInfo.targetSdkVersion = Build.VERSION_CODES.L;
165 
166         mContext = spy(RuntimeEnvironment.application);
167         doReturn(mPackageManager).when(mContext).getPackageManager();
168         doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
169         doReturn(mBatteryStatsManager).when(mContext)
170                 .getSystemService(Context.BATTERY_STATS_SERVICE);
171         mBatteryUtils = spy(new BatteryUtils(mContext));
172         mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
173         doReturn(0L).when(mBatteryUtils)
174             .getForegroundServiceTotalTimeUs(any(BatteryStats.Uid.class), anyLong());
175         mAnomalyInfo = new AnomalyInfo(INFO_WAKELOCK);
176 
177         BatteryDatabaseManager.setUpForTest(mBatteryDatabaseManager);
178         ShadowThreadUtils.setIsMainThread(true);
179     }
180 
181     @Test
testGetProcessTimeMs_typeForeground_timeCorrect()182     public void testGetProcessTimeMs_typeForeground_timeCorrect() {
183         doReturn(TIME_STATE_FOREGROUND + 500).when(mBatteryUtils)
184             .getForegroundActivityTotalTimeUs(eq(mUid), anyLong());
185 
186         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.FOREGROUND, mUid,
187                 BatteryStats.STATS_SINCE_CHARGED);
188 
189         assertThat(time).isEqualTo(TIME_EXPECTED_FOREGROUND);
190     }
191 
192     @Test
testGetProcessTimeMs_typeBackground_timeCorrect()193     public void testGetProcessTimeMs_typeBackground_timeCorrect() {
194         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.BACKGROUND, mUid,
195                 BatteryStats.STATS_SINCE_CHARGED);
196 
197         assertThat(time).isEqualTo(TIME_EXPECTED_BACKGROUND);
198     }
199 
200     @Test
testGetProcessTimeMs_typeAll_timeCorrect()201     public void testGetProcessTimeMs_typeAll_timeCorrect() {
202         doReturn(TIME_STATE_FOREGROUND + 500).when(mBatteryUtils)
203             .getForegroundActivityTotalTimeUs(eq(mUid), anyLong());
204 
205         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.ALL, mUid,
206                 BatteryStats.STATS_SINCE_CHARGED);
207 
208         assertThat(time).isEqualTo(TIME_EXPECTED_ALL);
209     }
210 
211     @Test
testGetProcessTimeMs_uidNull_returnZero()212     public void testGetProcessTimeMs_uidNull_returnZero() {
213         final long time = mBatteryUtils.getProcessTimeMs(BatteryUtils.StatusType.ALL, null,
214                 BatteryStats.STATS_SINCE_CHARGED);
215 
216         assertThat(time).isEqualTo(0);
217     }
218 
219     @Test
testShouldHideSystemConsumer_TypeIdle_ReturnTrue()220     public void testShouldHideSystemConsumer_TypeIdle_ReturnTrue() {
221         assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer,
222                 BatteryConsumer.POWER_COMPONENT_IDLE)).isTrue();
223     }
224 
225     @Test
testShouldHideSystemConsumer_TypeMobileRadio_ReturnTrue()226     public void testShouldHideSystemConsumer_TypeMobileRadio_ReturnTrue() {
227         assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer,
228                 BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)).isTrue();
229     }
230 
231     @Test
testShouldHideSystemConsumer_TypeScreen_ReturnTrue()232     public void testShouldHideSystemConsumer_TypeScreen_ReturnTrue() {
233         assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer,
234                 BatteryConsumer.POWER_COMPONENT_SCREEN)).isTrue();
235     }
236 
237     @Test
testShouldHideSystemConsumer_TypeBluetooth_ReturnTrue()238     public void testShouldHideSystemConsumer_TypeBluetooth_ReturnTrue() {
239         assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer,
240                 BatteryConsumer.POWER_COMPONENT_BLUETOOTH)).isTrue();    }
241 
242     @Test
testShouldHideSystemConsumer_TypeWifi_ReturnTrue()243     public void testShouldHideSystemConsumer_TypeWifi_ReturnTrue() {
244         assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer,
245                 BatteryConsumer.POWER_COMPONENT_WIFI)).isTrue();
246     }
247 
248     @Test
testShouldHideSystemConsumer_OtherType_ReturnFalse()249     public void testShouldHideSystemConsumer_OtherType_ReturnFalse() {
250         assertThat(mBatteryUtils.shouldHideDevicePowerComponent(mAggregateBatteryConsumer,
251                 BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)).isFalse();
252     }
253 
254     @Test
testCalculateBatteryPercent()255     public void testCalculateBatteryPercent() {
256         assertThat(mBatteryUtils.calculateBatteryPercent(BATTERY_SYSTEM_USAGE, TOTAL_BATTERY_USAGE,
257                 DISCHARGE_AMOUNT))
258                 .isWithin(PRECISION).of(PERCENT_SYSTEM_USAGE);
259     }
260 
261     @Test
testCalculateLastFullChargeTime()262     public void testCalculateLastFullChargeTime() {
263         final long currentTimeMs = System.currentTimeMillis();
264         when(mBatteryUsageStats.getStatsStartTimestamp()).thenReturn(
265                 currentTimeMs - TIME_SINCE_LAST_FULL_CHARGE_MS);
266 
267         assertThat(mBatteryUtils.calculateLastFullChargeTime(mBatteryUsageStats, currentTimeMs))
268                 .isEqualTo(TIME_SINCE_LAST_FULL_CHARGE_MS);
269     }
270 
271     @Test
testGetForegroundActivityTotalTimeMs_returnMilliseconds()272     public void testGetForegroundActivityTotalTimeMs_returnMilliseconds() {
273         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
274         doReturn(mTimer).when(mUid).getForegroundActivityTimer();
275         doReturn(TIME_SINCE_LAST_FULL_CHARGE_US).when(mTimer)
276                 .getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
277 
278         assertThat(mBatteryUtils.getForegroundActivityTotalTimeUs(mUid, rawRealtimeUs)).isEqualTo(
279                 TIME_SINCE_LAST_FULL_CHARGE_US);
280     }
281 
282     @Test
testGetTargetSdkVersion_packageExist_returnSdk()283     public void testGetTargetSdkVersion_packageExist_returnSdk() throws
284             PackageManager.NameNotFoundException {
285         doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(PACKAGE_NAME,
286                 PackageManager.GET_META_DATA);
287         mApplicationInfo.targetSdkVersion = SDK_VERSION;
288 
289         assertThat(mBatteryUtils.getTargetSdkVersion(PACKAGE_NAME)).isEqualTo(SDK_VERSION);
290     }
291 
292     @Test
testGetTargetSdkVersion_packageNotExist_returnSdkNull()293     public void testGetTargetSdkVersion_packageNotExist_returnSdkNull() throws
294             PackageManager.NameNotFoundException {
295         doThrow(new PackageManager.NameNotFoundException()).when(
296                 mPackageManager).getApplicationInfo(PACKAGE_NAME, PackageManager.GET_META_DATA);
297 
298         assertThat(mBatteryUtils.getTargetSdkVersion(PACKAGE_NAME)).isEqualTo(
299                 BatteryUtils.SDK_NULL);
300     }
301 
302     @Test
testBackgroundRestrictionOn_restrictionOn_returnTrue()303     public void testBackgroundRestrictionOn_restrictionOn_returnTrue() {
304         doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager).checkOpNoThrow(
305                 AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME);
306 
307         assertThat(mBatteryUtils.isBackgroundRestrictionEnabled(SDK_VERSION, UID,
308                 PACKAGE_NAME)).isTrue();
309     }
310 
311     @Test
testBackgroundRestrictionOn_restrictionOff_returnFalse()312     public void testBackgroundRestrictionOn_restrictionOff_returnFalse() {
313         doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).checkOpNoThrow(
314                 AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME);
315 
316         assertThat(mBatteryUtils.isBackgroundRestrictionEnabled(SDK_VERSION, UID, PACKAGE_NAME))
317             .isFalse();
318     }
319 
320     @Test
testIsPreOApp_SdkLowerThanO_ReturnTrue()321     public void testIsPreOApp_SdkLowerThanO_ReturnTrue() {
322         assertThat(mBatteryUtils.isPreOApp(LOW_SDK_PACKAGE)).isTrue();
323     }
324 
325     @Test
testIsPreOApp_SdkLargerOrEqualThanO_ReturnFalse()326     public void testIsPreOApp_SdkLargerOrEqualThanO_ReturnFalse() {
327         assertThat(mBatteryUtils.isPreOApp(HIGH_SDK_PACKAGE)).isFalse();
328     }
329 
330     @Test
testIsPreOApp_containPreOApp_ReturnTrue()331     public void testIsPreOApp_containPreOApp_ReturnTrue() {
332         assertThat(
333                 mBatteryUtils.isPreOApp(new String[]{HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE})).isTrue();
334     }
335 
336     @Test
testIsPreOApp_emptyList_ReturnFalse()337     public void testIsPreOApp_emptyList_ReturnFalse() {
338         assertThat(mBatteryUtils.isPreOApp(new String[]{})).isFalse();
339     }
340 
341     @Ignore
342     @Test
testSetForceAppStandby_forcePreOApp_forceTwoRestrictions()343     public void testSetForceAppStandby_forcePreOApp_forceTwoRestrictions() {
344         mBatteryUtils.setForceAppStandby(UID, LOW_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
345 
346         // Restrict both OP_RUN_IN_BACKGROUND and OP_RUN_ANY_IN_BACKGROUND
347         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID, LOW_SDK_PACKAGE,
348                 AppOpsManager.MODE_IGNORED);
349         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID, LOW_SDK_PACKAGE,
350                 AppOpsManager.MODE_IGNORED);
351     }
352 
353     @Ignore
354     @Test
testSetForceAppStandby_forceOApp_forceOneRestriction()355     public void testSetForceAppStandby_forceOApp_forceOneRestriction() {
356         mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
357 
358         // Don't restrict OP_RUN_IN_BACKGROUND because it is already been restricted for O app
359         verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID,
360                 HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
361         // Restrict OP_RUN_ANY_IN_BACKGROUND
362         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
363                 HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
364     }
365 
366     @Test
testSetForceAppStandby_restrictApp_recordTime()367     public void testSetForceAppStandby_restrictApp_recordTime() {
368         mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
369 
370         verify(mBatteryDatabaseManager).insertAction(
371                 eq(AnomalyDatabaseHelper.ActionType.RESTRICTION), eq(UID),
372                 eq(HIGH_SDK_PACKAGE), anyLong());
373     }
374 
375     @Test
testSetForceAppStandby_unrestrictApp_deleteTime()376     public void testSetForceAppStandby_unrestrictApp_deleteTime() {
377         mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
378 
379         verify(mBatteryDatabaseManager).deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
380                 UID, HIGH_SDK_PACKAGE);
381     }
382 
383     @Test
testIsForceAppStandbyEnabled_enabled_returnTrue()384     public void testIsForceAppStandbyEnabled_enabled_returnTrue() {
385         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
386                 PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_IGNORED);
387 
388         assertThat(mBatteryUtils.isForceAppStandbyEnabled(UID, PACKAGE_NAME)).isTrue();
389     }
390 
391     @Test
testIsForceAppStandbyEnabled_disabled_returnFalse()392     public void testIsForceAppStandbyEnabled_disabled_returnFalse() {
393         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
394                 PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_ALLOWED);
395 
396         assertThat(mBatteryUtils.isForceAppStandbyEnabled(UID, PACKAGE_NAME)).isFalse();
397     }
398 
399     @Test
testShouldHideAnomaly_systemAppWithLauncher_returnTrue()400     public void testShouldHideAnomaly_systemAppWithLauncher_returnTrue() {
401         final List<ResolveInfo> resolveInfos = new ArrayList<>();
402         final ResolveInfo resolveInfo = new ResolveInfo();
403         resolveInfo.activityInfo = new ActivityInfo();
404         resolveInfo.activityInfo.packageName = HIGH_SDK_PACKAGE;
405 
406         doReturn(resolveInfos).when(mPackageManager).queryIntentActivities(any(), anyInt());
407         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
408         mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
409 
410         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, UID,
411                 mAnomalyInfo)).isTrue();
412     }
413 
414     @Test
testShouldHideAnomaly_systemAppWithoutLauncher_returnTrue()415     public void testShouldHideAnomaly_systemAppWithoutLauncher_returnTrue() {
416         doReturn(new ArrayList<>()).when(mPackageManager).queryIntentActivities(any(), anyInt());
417         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
418         mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
419 
420         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, UID,
421                 mAnomalyInfo)).isTrue();
422     }
423 
424     @Test
testShouldHideAnomaly_systemUid_returnTrue()425     public void testShouldHideAnomaly_systemUid_returnTrue() {
426         final int systemUid = Process.ROOT_UID;
427         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(systemUid);
428 
429         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, systemUid,
430                 mAnomalyInfo)).isTrue();
431     }
432 
433     @Test
testShouldHideAnomaly_AppInDozeList_returnTrue()434     public void testShouldHideAnomaly_AppInDozeList_returnTrue() {
435         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
436         doReturn(true).when(mPowerAllowlistBackend).isAllowlisted(new String[]{HIGH_SDK_PACKAGE});
437 
438         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, UID,
439                 mAnomalyInfo)).isTrue();
440     }
441 
442     @Test
testShouldHideAnomaly_normalApp_returnFalse()443     public void testShouldHideAnomaly_normalApp_returnFalse() {
444         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
445 
446         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, UID,
447                 mAnomalyInfo)).isFalse();
448     }
449 
450     @Test
testShouldHideAnomaly_excessivePriorOApp_returnFalse()451     public void testShouldHideAnomaly_excessivePriorOApp_returnFalse() {
452         doReturn(new String[]{LOW_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
453         mAnomalyInfo = new AnomalyInfo(INFO_EXCESSIVE);
454 
455         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, UID,
456                 mAnomalyInfo)).isFalse();
457     }
458 
459     @Test
testShouldHideAnomaly_excessiveOApp_returnTrue()460     public void testShouldHideAnomaly_excessiveOApp_returnTrue() {
461         doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
462         mAnomalyInfo = new AnomalyInfo(INFO_EXCESSIVE);
463 
464         assertThat(mBatteryUtils.shouldHideAnomaly(mPowerAllowlistBackend, UID,
465                 mAnomalyInfo)).isTrue();
466     }
467 
468     @Test
clearForceAppStandby_appRestricted_clearAndReturnTrue()469     public void clearForceAppStandby_appRestricted_clearAndReturnTrue() {
470         when(mBatteryUtils.getPackageUid(HIGH_SDK_PACKAGE)).thenReturn(UID);
471         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
472                 HIGH_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
473 
474         assertThat(mBatteryUtils.clearForceAppStandby(HIGH_SDK_PACKAGE)).isTrue();
475         verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
476                 HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
477     }
478 
479     @Test
clearForceAppStandby_appInvalid_returnFalse()480     public void clearForceAppStandby_appInvalid_returnFalse() {
481         when(mBatteryUtils.getPackageUid(PACKAGE_NAME)).thenReturn(BatteryUtils.UID_NULL);
482 
483         assertThat(mBatteryUtils.clearForceAppStandby(PACKAGE_NAME)).isFalse();
484         verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
485                 PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
486     }
487 
488     @Test
clearForceAppStandby_appUnrestricted_returnFalse()489     public void clearForceAppStandby_appUnrestricted_returnFalse() {
490         when(mBatteryUtils.getPackageUid(PACKAGE_NAME)).thenReturn(UID);
491         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
492                 PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_ALLOWED);
493 
494         assertThat(mBatteryUtils.clearForceAppStandby(PACKAGE_NAME)).isFalse();
495         verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
496                 PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
497     }
498 
499     @Test
getBatteryInfo_providerNull_shouldNotCrash()500     public void getBatteryInfo_providerNull_shouldNotCrash() {
501         when(mProvider.isEnhancedBatteryPredictionEnabled(mContext)).thenReturn(true);
502         when(mProvider.getEnhancedBatteryPrediction(mContext)).thenReturn(null);
503         when(mContext.registerReceiver(nullable(BroadcastReceiver.class),
504                 any(IntentFilter.class))).thenReturn(new Intent());
505 
506         //Should not crash
507         assertThat(mBatteryUtils.getBatteryInfo(TAG)).isNotNull();
508     }
509 
510     @Test
getEnhancedEstimate_doesNotUpdateCache_ifEstimateFresh()511     public void getEnhancedEstimate_doesNotUpdateCache_ifEstimateFresh() {
512         Estimate estimate = new Estimate(1000, true, 1000);
513         Estimate.storeCachedEstimate(mContext, estimate);
514 
515         estimate = mBatteryUtils.getEnhancedEstimate();
516 
517         // only pass if estimate has not changed
518         assertThat(estimate).isNotNull();
519         assertThat(estimate.isBasedOnUsage()).isTrue();
520         assertThat(estimate.getAverageDischargeTime()).isEqualTo(1000);
521     }
522 
523     @Test
testIsBatteryDefenderOn_isOverheatedAndIsCharging_returnTrue()524     public void testIsBatteryDefenderOn_isOverheatedAndIsCharging_returnTrue() {
525         mBatteryInfo.isOverheated = true;
526         mBatteryInfo.discharging = false;
527 
528         assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isTrue();
529     }
530 
531     @Test
testIsBatteryDefenderOn_isOverheatedAndDischarging_returnFalse()532     public void testIsBatteryDefenderOn_isOverheatedAndDischarging_returnFalse() {
533         mBatteryInfo.isOverheated = true;
534         mBatteryInfo.discharging = true;
535 
536         assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse();
537     }
538 
539     @Test
testIsBatteryDefenderOn_notOverheatedAndDischarging_returnFalse()540     public void testIsBatteryDefenderOn_notOverheatedAndDischarging_returnFalse() {
541         mBatteryInfo.isOverheated = false;
542         mBatteryInfo.discharging = true;
543 
544         assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse();
545     }
546 
547     @Test
testIsBatteryDefenderOn_notOverheatedAndIsCharging_returnFalse()548     public void testIsBatteryDefenderOn_notOverheatedAndIsCharging_returnFalse() {
549         mBatteryInfo.isOverheated = false;
550         mBatteryInfo.discharging = false;
551 
552         assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse();
553     }
554 }
555