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