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 17 package com.android.settings.fuelgauge; 18 19 import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyLong; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.ArgumentMatchers.nullable; 28 import static org.mockito.Mockito.doAnswer; 29 import static org.mockito.Mockito.doReturn; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.verifyZeroInteractions; 34 import static org.mockito.Mockito.when; 35 36 import android.app.AppOpsManager; 37 import android.app.backup.BackupManager; 38 import android.app.settings.SettingsEnums; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.content.pm.ApplicationInfo; 42 import android.content.pm.PackageManager; 43 import android.graphics.drawable.Drawable; 44 import android.os.BatteryStats; 45 import android.os.Bundle; 46 import android.os.UserHandle; 47 import android.util.Pair; 48 49 import androidx.fragment.app.FragmentActivity; 50 import androidx.loader.app.LoaderManager; 51 import androidx.preference.Preference; 52 import androidx.recyclerview.widget.RecyclerView; 53 54 import com.android.settings.R; 55 import com.android.settings.SettingsActivity; 56 import com.android.settings.testutils.FakeFeatureFactory; 57 import com.android.settings.testutils.shadow.ShadowActivityManager; 58 import com.android.settings.testutils.shadow.ShadowEntityHeaderController; 59 import com.android.settings.widget.EntityHeaderController; 60 import com.android.settingslib.applications.AppUtils; 61 import com.android.settingslib.applications.ApplicationsState; 62 import com.android.settingslib.applications.instantapps.InstantAppDataProvider; 63 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 64 import com.android.settingslib.core.lifecycle.Lifecycle; 65 import com.android.settingslib.widget.FooterPreference; 66 import com.android.settingslib.widget.LayoutPreference; 67 import com.android.settingslib.widget.RadioButtonPreference; 68 69 import org.junit.After; 70 import org.junit.Before; 71 import org.junit.Test; 72 import org.junit.runner.RunWith; 73 import org.mockito.Answers; 74 import org.mockito.ArgumentCaptor; 75 import org.mockito.Mock; 76 import org.mockito.MockitoAnnotations; 77 import org.mockito.stubbing.Answer; 78 import org.robolectric.RobolectricTestRunner; 79 import org.robolectric.RuntimeEnvironment; 80 import org.robolectric.annotation.Config; 81 import org.robolectric.util.ReflectionHelpers; 82 83 @RunWith(RobolectricTestRunner.class) 84 @Config(shadows = {ShadowEntityHeaderController.class, ShadowActivityManager.class}) 85 public class AdvancedPowerUsageDetailTest { 86 private static final String APP_LABEL = "app label"; 87 private static final String SUMMARY = "summary"; 88 private static final String[] PACKAGE_NAME = {"com.android.app"}; 89 private static final String USAGE_PERCENT = "16%"; 90 private static final String SLOT_TIME = "12 am-2 am"; 91 private static final int ICON_ID = 123; 92 private static final int UID = 1; 93 private static final int POWER_MAH = 150; 94 private static final long BACKGROUND_TIME_MS = 100; 95 private static final long FOREGROUND_ACTIVITY_TIME_MS = 123; 96 private static final long FOREGROUND_SERVICE_TIME_MS = 444; 97 private static final long FOREGROUND_TIME_MS = 98 FOREGROUND_ACTIVITY_TIME_MS + FOREGROUND_SERVICE_TIME_MS; 99 private static final long FOREGROUND_SERVICE_TIME_US = FOREGROUND_SERVICE_TIME_MS * 1000; 100 private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref"; 101 private static final String KEY_PREF_OPTIMIZED = "optimized_pref"; 102 private static final String KEY_PREF_RESTRICTED = "restricted_pref"; 103 104 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 105 private FragmentActivity mActivity; 106 @Mock 107 private EntityHeaderController mEntityHeaderController; 108 @Mock 109 private LayoutPreference mHeaderPreference; 110 @Mock 111 private ApplicationsState mState; 112 @Mock 113 private ApplicationsState.AppEntry mAppEntry; 114 @Mock 115 private Bundle mBundle; 116 @Mock 117 private BatteryEntry mBatteryEntry; 118 @Mock 119 private PackageManager mPackageManager; 120 @Mock 121 private AppOpsManager mAppOpsManager; 122 @Mock 123 private LoaderManager mLoaderManager; 124 @Mock 125 private BatteryUtils mBatteryUtils; 126 @Mock 127 private BatteryOptimizeUtils mBatteryOptimizeUtils; 128 @Mock 129 private BackupManager mBackupManager; 130 131 private Context mContext; 132 private Preference mForegroundPreference; 133 private Preference mBackgroundPreference; 134 private FooterPreference mFooterPreference; 135 private RadioButtonPreference mRestrictedPreference; 136 private RadioButtonPreference mOptimizePreference; 137 private RadioButtonPreference mUnrestrictedPreference; 138 private AdvancedPowerUsageDetail mFragment; 139 private SettingsActivity mTestActivity; 140 private FakeFeatureFactory mFeatureFactory; 141 private MetricsFeatureProvider mMetricsFeatureProvider; 142 143 @Before setUp()144 public void setUp() { 145 MockitoAnnotations.initMocks(this); 146 147 mContext = spy(RuntimeEnvironment.application); 148 when(mContext.getPackageName()).thenReturn("foo"); 149 mFeatureFactory = FakeFeatureFactory.setupForTest(); 150 mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider; 151 152 mFragment = spy(new AdvancedPowerUsageDetail()); 153 doReturn(mContext).when(mFragment).getContext(); 154 doReturn(mActivity).when(mFragment).getActivity(); 155 doReturn(SUMMARY).when(mFragment).getString(anyInt()); 156 doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class)); 157 when(mFragment.getArguments()).thenReturn(mBundle); 158 doReturn(mLoaderManager).when(mFragment).getLoaderManager(); 159 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 160 .thenReturn(true); 161 162 ShadowEntityHeaderController.setUseMock(mEntityHeaderController); 163 doReturn(mEntityHeaderController).when(mEntityHeaderController) 164 .setRecyclerView(nullable(RecyclerView.class), nullable(Lifecycle.class)); 165 doReturn(mEntityHeaderController).when(mEntityHeaderController) 166 .setButtonActions(anyInt(), anyInt()); 167 doReturn(mEntityHeaderController).when(mEntityHeaderController) 168 .setIcon(nullable(Drawable.class)); 169 doReturn(mEntityHeaderController).when(mEntityHeaderController).setIcon(nullable( 170 ApplicationsState.AppEntry.class)); 171 doReturn(mEntityHeaderController).when(mEntityHeaderController) 172 .setLabel(nullable(String.class)); 173 doReturn(mEntityHeaderController).when(mEntityHeaderController) 174 .setLabel(nullable(String.class)); 175 doReturn(mEntityHeaderController).when(mEntityHeaderController) 176 .setLabel(nullable(ApplicationsState.AppEntry.class)); 177 doReturn(mEntityHeaderController).when(mEntityHeaderController) 178 .setSummary(nullable(String.class)); 179 180 when(mBatteryEntry.getUid()).thenReturn(UID); 181 when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL); 182 when(mBatteryEntry.getTimeInBackgroundMs()).thenReturn(BACKGROUND_TIME_MS); 183 when(mBatteryEntry.getTimeInForegroundMs()).thenReturn(FOREGROUND_TIME_MS); 184 mBatteryEntry.iconId = ICON_ID; 185 186 mFragment.mHeaderPreference = mHeaderPreference; 187 mFragment.mState = mState; 188 mFragment.mEnableTriState = true; 189 mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application); 190 mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils; 191 mFragment.mBackupManager = mBackupManager; 192 mAppEntry.info = mock(ApplicationInfo.class); 193 194 mTestActivity = spy(new SettingsActivity()); 195 doReturn(mPackageManager).when(mTestActivity).getPackageManager(); 196 doReturn(mPackageManager).when(mActivity).getPackageManager(); 197 doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE); 198 199 mBatteryUtils = spy(new BatteryUtils(mContext)); 200 doReturn(FOREGROUND_SERVICE_TIME_US).when(mBatteryUtils).getForegroundServiceTotalTimeUs( 201 any(BatteryStats.Uid.class), anyLong()); 202 203 final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 204 205 Answer<Void> callable = invocation -> { 206 mBundle = captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS); 207 System.out.println("mBundle = " + mBundle); 208 return null; 209 }; 210 doAnswer(callable).when(mActivity).startActivityAsUser(captor.capture(), 211 nullable(UserHandle.class)); 212 doAnswer(callable).when(mActivity).startActivity(captor.capture()); 213 214 mForegroundPreference = new Preference(mContext); 215 mBackgroundPreference = new Preference(mContext); 216 mFooterPreference = new FooterPreference(mContext); 217 mRestrictedPreference = new RadioButtonPreference(mContext); 218 mOptimizePreference = new RadioButtonPreference(mContext); 219 mUnrestrictedPreference = new RadioButtonPreference(mContext); 220 mFragment.mForegroundPreference = mForegroundPreference; 221 mFragment.mBackgroundPreference = mBackgroundPreference; 222 mFragment.mFooterPreference = mFooterPreference; 223 mFragment.mRestrictedPreference = mRestrictedPreference; 224 mFragment.mOptimizePreference = mOptimizePreference; 225 mFragment.mUnrestrictedPreference = mUnrestrictedPreference; 226 } 227 228 @After reset()229 public void reset() { 230 ShadowEntityHeaderController.reset(); 231 } 232 233 @Test testGetPreferenceScreenResId_returnNewLayout()234 public void testGetPreferenceScreenResId_returnNewLayout() { 235 assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.power_usage_detail); 236 } 237 238 @Test testGetPreferenceScreenResId_disableTriState_returnLegacyLayout()239 public void testGetPreferenceScreenResId_disableTriState_returnLegacyLayout() { 240 mFragment.mEnableTriState = false; 241 assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.power_usage_detail_legacy); 242 } 243 244 @Test testInitHeader_NoAppEntry_BuildByBundle()245 public void testInitHeader_NoAppEntry_BuildByBundle() { 246 mFragment.mAppEntry = null; 247 mFragment.initHeader(); 248 249 verify(mEntityHeaderController).setIcon(nullable(Drawable.class)); 250 verify(mEntityHeaderController).setLabel(APP_LABEL); 251 } 252 253 @Test testInitHeader_HasAppEntry_BuildByAppEntry()254 public void testInitHeader_HasAppEntry_BuildByAppEntry() { 255 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 256 new InstantAppDataProvider() { 257 @Override 258 public boolean isInstantApp(ApplicationInfo info) { 259 return false; 260 } 261 }); 262 mFragment.mAppEntry = mAppEntry; 263 mFragment.initHeader(); 264 265 verify(mEntityHeaderController).setIcon(mAppEntry); 266 verify(mEntityHeaderController).setLabel(mAppEntry); 267 verify(mEntityHeaderController).setIsInstantApp(false); 268 } 269 270 @Test testInitHeader_HasAppEntry_InstantApp()271 public void testInitHeader_HasAppEntry_InstantApp() { 272 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 273 new InstantAppDataProvider() { 274 @Override 275 public boolean isInstantApp(ApplicationInfo info) { 276 return true; 277 } 278 }); 279 mFragment.mAppEntry = mAppEntry; 280 mFragment.initHeader(); 281 282 verify(mEntityHeaderController).setIcon(mAppEntry); 283 verify(mEntityHeaderController).setLabel(mAppEntry); 284 verify(mEntityHeaderController).setIsInstantApp(true); 285 } 286 287 @Test testInitHeader_noUsageTimeAndGraphDisabled_hasCorrectSummary()288 public void testInitHeader_noUsageTimeAndGraphDisabled_hasCorrectSummary() { 289 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 290 .thenReturn(false); 291 292 Bundle bundle = new Bundle(2); 293 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0); 294 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0); 295 when(mFragment.getArguments()).thenReturn(bundle); 296 297 mFragment.initHeader(); 298 299 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 300 verify(mEntityHeaderController).setSummary(captor.capture()); 301 assertThat(captor.getValue().toString()) 302 .isEqualTo("No usage from last full charge"); 303 } 304 305 @Test testInitHeader_bgTwoMinFgZeroAndGraphDisabled_hasCorrectSummary()306 public void testInitHeader_bgTwoMinFgZeroAndGraphDisabled_hasCorrectSummary() { 307 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 308 .thenReturn(false); 309 310 final long backgroundTimeTwoMinutes = 120000; 311 final long foregroundTimeZero = 0; 312 Bundle bundle = new Bundle(2); 313 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes); 314 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero); 315 when(mFragment.getArguments()).thenReturn(bundle); 316 317 mFragment.initHeader(); 318 319 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 320 verify(mEntityHeaderController).setSummary(captor.capture()); 321 assertThat(captor.getValue().toString()) 322 .isEqualTo("2 min background from last full charge"); 323 } 324 325 @Test testInitHeader_bgLessThanAMinFgZeroAndGraphDisabled_hasCorrectSummary()326 public void testInitHeader_bgLessThanAMinFgZeroAndGraphDisabled_hasCorrectSummary() { 327 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 328 .thenReturn(false); 329 330 final long backgroundTimeLessThanAMinute = 59999; 331 final long foregroundTimeZero = 0; 332 Bundle bundle = new Bundle(2); 333 bundle.putLong( 334 AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute); 335 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero); 336 when(mFragment.getArguments()).thenReturn(bundle); 337 338 mFragment.initHeader(); 339 340 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 341 verify(mEntityHeaderController).setSummary(captor.capture()); 342 assertThat(captor.getValue().toString()) 343 .isEqualTo("Background less than a minute from last full charge"); 344 } 345 346 @Test testInitHeader_totalUsageLessThanAMinAndGraphDisabled_hasCorrectSummary()347 public void testInitHeader_totalUsageLessThanAMinAndGraphDisabled_hasCorrectSummary() { 348 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 349 .thenReturn(false); 350 351 final long backgroundTimeLessThanHalfMinute = 20000; 352 final long foregroundTimeLessThanHalfMinute = 20000; 353 Bundle bundle = new Bundle(2); 354 bundle.putLong( 355 AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute); 356 bundle.putLong( 357 AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute); 358 when(mFragment.getArguments()).thenReturn(bundle); 359 360 mFragment.initHeader(); 361 362 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 363 verify(mEntityHeaderController).setSummary(captor.capture()); 364 assertThat(captor.getValue().toString()) 365 .isEqualTo("Total less than a minute from last full charge"); 366 } 367 368 @Test testInitHeader_TotalAMinutesBgLessThanAMinAndGraphDisabled_hasCorrectSummary()369 public void testInitHeader_TotalAMinutesBgLessThanAMinAndGraphDisabled_hasCorrectSummary() { 370 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 371 .thenReturn(false); 372 373 final long backgroundTimeZero = 59999; 374 final long foregroundTimeTwoMinutes = 1; 375 Bundle bundle = new Bundle(2); 376 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero); 377 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes); 378 when(mFragment.getArguments()).thenReturn(bundle); 379 380 mFragment.initHeader(); 381 382 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 383 verify(mEntityHeaderController).setSummary(captor.capture()); 384 assertThat(captor.getValue().toString()) 385 .isEqualTo("1 min total • background less than a minute\nfrom last full charge"); 386 } 387 388 @Test testInitHeader_TotalAMinBackgroundZeroAndGraphDisabled_hasCorrectSummary()389 public void testInitHeader_TotalAMinBackgroundZeroAndGraphDisabled_hasCorrectSummary() { 390 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 391 .thenReturn(false); 392 final long backgroundTimeZero = 0; 393 final long foregroundTimeAMinutes = 60000; 394 Bundle bundle = new Bundle(2); 395 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero); 396 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes); 397 when(mFragment.getArguments()).thenReturn(bundle); 398 399 mFragment.initHeader(); 400 401 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 402 verify(mEntityHeaderController).setSummary(captor.capture()); 403 assertThat(captor.getValue().toString()) 404 .isEqualTo("1 min total from last full charge"); 405 } 406 407 @Test testInitHeader_fgTwoMinBgFourMinAndGraphDisabled_hasCorrectSummary()408 public void testInitHeader_fgTwoMinBgFourMinAndGraphDisabled_hasCorrectSummary() { 409 when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext)) 410 .thenReturn(false); 411 final long backgroundTimeFourMinute = 240000; 412 final long foregroundTimeTwoMinutes = 120000; 413 Bundle bundle = new Bundle(2); 414 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute); 415 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes); 416 when(mFragment.getArguments()).thenReturn(bundle); 417 mFragment.initHeader(); 418 419 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 420 verify(mEntityHeaderController).setSummary(captor.capture()); 421 assertThat(captor.getValue().toString()) 422 .isEqualTo("6 min total • 4 min background\nfrom last full charge"); 423 } 424 425 @Test testInitHeader_noUsageTime_hasCorrectSummary()426 public void testInitHeader_noUsageTime_hasCorrectSummary() { 427 Bundle bundle = new Bundle(2); 428 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0); 429 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0); 430 when(mFragment.getArguments()).thenReturn(bundle); 431 432 mFragment.initHeader(); 433 434 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 435 verify(mEntityHeaderController).setSummary(captor.capture()); 436 assertThat(captor.getValue().toString()) 437 .isEqualTo("No usage for past 24 hr"); 438 } 439 440 @Test testInitHeader_noUsageTimeButConsumedPower_hasEmptySummary()441 public void testInitHeader_noUsageTimeButConsumedPower_hasEmptySummary() { 442 Bundle bundle = new Bundle(3); 443 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0); 444 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0); 445 bundle.putInt(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_AMOUNT, /* value */ 10); 446 when(mFragment.getArguments()).thenReturn(bundle); 447 448 mFragment.initHeader(); 449 450 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 451 verify(mEntityHeaderController).setSummary(captor.capture()); 452 assertThat(captor.getValue().toString()).isEmpty(); 453 } 454 455 @Test testInitHeader_backgroundTwoMinForegroundZero_hasCorrectSummary()456 public void testInitHeader_backgroundTwoMinForegroundZero_hasCorrectSummary() { 457 final long backgroundTimeTwoMinutes = 120000; 458 final long foregroundTimeZero = 0; 459 Bundle bundle = new Bundle(2); 460 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes); 461 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero); 462 when(mFragment.getArguments()).thenReturn(bundle); 463 464 mFragment.initHeader(); 465 466 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 467 verify(mEntityHeaderController).setSummary(captor.capture()); 468 assertThat(captor.getValue().toString()) 469 .isEqualTo("2 min background for past 24 hr"); 470 } 471 472 @Test testInitHeader_backgroundLessThanAMinForegroundZero_hasCorrectSummary()473 public void testInitHeader_backgroundLessThanAMinForegroundZero_hasCorrectSummary() { 474 final long backgroundTimeLessThanAMinute = 59999; 475 final long foregroundTimeZero = 0; 476 Bundle bundle = new Bundle(2); 477 bundle.putLong( 478 AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute); 479 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero); 480 when(mFragment.getArguments()).thenReturn(bundle); 481 482 mFragment.initHeader(); 483 484 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 485 verify(mEntityHeaderController).setSummary(captor.capture()); 486 assertThat(captor.getValue().toString()) 487 .isEqualTo("Background less than a minute for past 24 hr"); 488 } 489 490 @Test testInitHeader_totalUsageLessThanAMin_hasCorrectSummary()491 public void testInitHeader_totalUsageLessThanAMin_hasCorrectSummary() { 492 final long backgroundTimeLessThanHalfMinute = 20000; 493 final long foregroundTimeLessThanHalfMinute = 20000; 494 Bundle bundle = new Bundle(2); 495 bundle.putLong( 496 AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute); 497 bundle.putLong( 498 AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute); 499 when(mFragment.getArguments()).thenReturn(bundle); 500 501 mFragment.initHeader(); 502 503 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 504 verify(mEntityHeaderController).setSummary(captor.capture()); 505 assertThat(captor.getValue().toString()) 506 .isEqualTo("Total less than a minute for past 24 hr"); 507 } 508 509 @Test testInitHeader_TotalAMinutesBackgroundLessThanAMin_hasCorrectSummary()510 public void testInitHeader_TotalAMinutesBackgroundLessThanAMin_hasCorrectSummary() { 511 final long backgroundTimeZero = 59999; 512 final long foregroundTimeTwoMinutes = 1; 513 Bundle bundle = new Bundle(2); 514 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero); 515 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes); 516 when(mFragment.getArguments()).thenReturn(bundle); 517 518 mFragment.initHeader(); 519 520 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 521 verify(mEntityHeaderController).setSummary(captor.capture()); 522 assertThat(captor.getValue().toString()) 523 .isEqualTo("1 min total • background less than a minute\nfor past 24 hr"); 524 } 525 526 @Test testInitHeader_TotalAMinBackgroundZero_hasCorrectSummary()527 public void testInitHeader_TotalAMinBackgroundZero_hasCorrectSummary() { 528 final long backgroundTimeZero = 0; 529 final long foregroundTimeAMinutes = 60000; 530 Bundle bundle = new Bundle(2); 531 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero); 532 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes); 533 when(mFragment.getArguments()).thenReturn(bundle); 534 535 mFragment.initHeader(); 536 537 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 538 verify(mEntityHeaderController).setSummary(captor.capture()); 539 assertThat(captor.getValue().toString()) 540 .isEqualTo("1 min total for past 24 hr"); 541 } 542 543 @Test testInitHeader_foregroundTwoMinBackgroundFourMin_hasCorrectSummary()544 public void testInitHeader_foregroundTwoMinBackgroundFourMin_hasCorrectSummary() { 545 final long backgroundTimeFourMinute = 240000; 546 final long foregroundTimeTwoMinutes = 120000; 547 Bundle bundle = new Bundle(2); 548 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute); 549 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes); 550 when(mFragment.getArguments()).thenReturn(bundle); 551 mFragment.initHeader(); 552 553 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 554 verify(mEntityHeaderController).setSummary(captor.capture()); 555 assertThat(captor.getValue().toString()) 556 .isEqualTo("6 min total • 4 min background\nfor past 24 hr"); 557 } 558 559 @Test testInitHeader_totalUsageLessThanAMinWithSlotTime_hasCorrectSummary()560 public void testInitHeader_totalUsageLessThanAMinWithSlotTime_hasCorrectSummary() { 561 final long backgroundTimeLessThanHalfMinute = 20000; 562 final long foregroundTimeLessThanHalfMinute = 20000; 563 Bundle bundle = new Bundle(2); 564 bundle.putLong( 565 AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute); 566 bundle.putLong( 567 AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute); 568 bundle.putString(AdvancedPowerUsageDetail.EXTRA_SLOT_TIME, SLOT_TIME); 569 when(mFragment.getArguments()).thenReturn(bundle); 570 571 mFragment.initHeader(); 572 573 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 574 verify(mEntityHeaderController).setSummary(captor.capture()); 575 assertThat(captor.getValue().toString()) 576 .isEqualTo("Total less than a minute for 12 am-2 am"); 577 } 578 579 @Test testInitHeader_TotalAMinBackgroundLessThanAMinWithSlotTime_hasCorrectSummary()580 public void testInitHeader_TotalAMinBackgroundLessThanAMinWithSlotTime_hasCorrectSummary() { 581 final long backgroundTimeZero = 59999; 582 final long foregroundTimeTwoMinutes = 1; 583 Bundle bundle = new Bundle(2); 584 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero); 585 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes); 586 bundle.putString(AdvancedPowerUsageDetail.EXTRA_SLOT_TIME, SLOT_TIME); 587 when(mFragment.getArguments()).thenReturn(bundle); 588 589 mFragment.initHeader(); 590 591 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 592 verify(mEntityHeaderController).setSummary(captor.capture()); 593 assertThat(captor.getValue().toString()) 594 .isEqualTo("1 min total • background less than a minute\nfor 12 am-2 am"); 595 } 596 597 @Test testInitHeader_TotalAMinBackgroundZeroWithSlotTime_hasCorrectSummary()598 public void testInitHeader_TotalAMinBackgroundZeroWithSlotTime_hasCorrectSummary() { 599 final long backgroundTimeZero = 0; 600 final long foregroundTimeAMinutes = 60000; 601 Bundle bundle = new Bundle(2); 602 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero); 603 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes); 604 bundle.putString(AdvancedPowerUsageDetail.EXTRA_SLOT_TIME, SLOT_TIME); 605 when(mFragment.getArguments()).thenReturn(bundle); 606 607 mFragment.initHeader(); 608 609 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 610 verify(mEntityHeaderController).setSummary(captor.capture()); 611 assertThat(captor.getValue().toString()) 612 .isEqualTo("1 min total for 12 am-2 am"); 613 } 614 615 @Test testInitHeader_foregroundTwoMinBackgroundFourMinWithSlotTime_hasCorrectSummary()616 public void testInitHeader_foregroundTwoMinBackgroundFourMinWithSlotTime_hasCorrectSummary() { 617 final long backgroundTimeFourMinute = 240000; 618 final long foregroundTimeTwoMinutes = 120000; 619 Bundle bundle = new Bundle(2); 620 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute); 621 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes); 622 bundle.putString(AdvancedPowerUsageDetail.EXTRA_SLOT_TIME, SLOT_TIME); 623 when(mFragment.getArguments()).thenReturn(bundle); 624 mFragment.initHeader(); 625 626 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 627 verify(mEntityHeaderController).setSummary(captor.capture()); 628 assertThat(captor.getValue().toString()) 629 .isEqualTo("6 min total • 4 min background\nfor 12 am-2 am"); 630 } 631 632 @Test testStartBatteryDetailPage_hasBasicData()633 public void testStartBatteryDetailPage_hasBasicData() { 634 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, 635 mBatteryEntry, USAGE_PERCENT, /*isValidToShowSummary=*/ true); 636 637 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); 638 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME)) 639 .isEqualTo(BACKGROUND_TIME_MS); 640 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME)) 641 .isEqualTo(FOREGROUND_TIME_MS); 642 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)) 643 .isEqualTo(USAGE_PERCENT); 644 } 645 646 @Test testStartBatteryDetailPage_invalidToShowSummary_noFGBDData()647 public void testStartBatteryDetailPage_invalidToShowSummary_noFGBDData() { 648 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, 649 mBatteryEntry, USAGE_PERCENT, /*isValidToShowSummary=*/ false); 650 651 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); 652 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME)) 653 .isEqualTo(0); 654 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME)) 655 .isEqualTo(0); 656 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)) 657 .isEqualTo(USAGE_PERCENT); 658 } 659 660 @Test testStartBatteryDetailPage_NormalApp()661 public void testStartBatteryDetailPage_NormalApp() { 662 when(mBatteryEntry.getDefaultPackageName()).thenReturn(PACKAGE_NAME[0]); 663 664 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, 665 mBatteryEntry, USAGE_PERCENT, /*isValidToShowSummary=*/ true); 666 667 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo( 668 PACKAGE_NAME[0]); 669 } 670 671 @Test testStartBatteryDetailPage_SystemApp()672 public void testStartBatteryDetailPage_SystemApp() { 673 when(mBatteryEntry.getDefaultPackageName()).thenReturn(null); 674 675 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, 676 mBatteryEntry, USAGE_PERCENT, /*isValidToShowSummary=*/ true); 677 678 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_LABEL)).isEqualTo(APP_LABEL); 679 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_ICON_ID)).isEqualTo(ICON_ID); 680 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isNull(); 681 } 682 683 @Test testStartBatteryDetailPage_WorkApp()684 public void testStartBatteryDetailPage_WorkApp() { 685 final int appUid = 1010019; 686 doReturn(appUid).when(mBatteryEntry).getUid(); 687 688 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, 689 mBatteryEntry, USAGE_PERCENT, /*isValidToShowSummary=*/ true); 690 691 verify(mActivity).startActivityAsUser(any(Intent.class), eq(new UserHandle(10))); 692 } 693 694 @Test testStartBatteryDetailPage_typeUser_startByCurrentUser()695 public void testStartBatteryDetailPage_typeUser_startByCurrentUser() { 696 when(mBatteryEntry.isUserEntry()).thenReturn(true); 697 698 final int currentUser = 20; 699 ShadowActivityManager.setCurrentUser(currentUser); 700 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, 701 mBatteryEntry, USAGE_PERCENT, /*isValidToShowSummary=*/ true); 702 703 verify(mActivity).startActivityAsUser(any(Intent.class), eq(new UserHandle(currentUser))); 704 } 705 706 @Test testStartBatteryDetailPage_noBatteryUsage_hasBasicData()707 public void testStartBatteryDetailPage_noBatteryUsage_hasBasicData() { 708 final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 709 710 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, PACKAGE_NAME[0]); 711 712 verify(mActivity).startActivity(captor.capture()); 713 714 assertThat(captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS) 715 .getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)) 716 .isEqualTo(PACKAGE_NAME[0]); 717 718 assertThat(captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS) 719 .getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)) 720 .isEqualTo("0%"); 721 } 722 723 @Test testStartBatteryDetailPage_batteryEntryNotExisted_extractUidFromPackageName()724 public void testStartBatteryDetailPage_batteryEntryNotExisted_extractUidFromPackageName() throws 725 PackageManager.NameNotFoundException { 726 doReturn(UID).when(mPackageManager).getPackageUid(PACKAGE_NAME[0], 0 /* no flag */); 727 728 AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, mFragment, PACKAGE_NAME[0]); 729 730 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); 731 } 732 733 @Test testInitPreference_hasCorrectSummary()734 public void testInitPreference_hasCorrectSummary() { 735 Bundle bundle = new Bundle(4); 736 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, BACKGROUND_TIME_MS); 737 bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, FOREGROUND_TIME_MS); 738 bundle.putString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT, USAGE_PERCENT); 739 bundle.putInt(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_AMOUNT, POWER_MAH); 740 when(mFragment.getArguments()).thenReturn(bundle); 741 742 doReturn(mContext.getText(R.string.battery_used_for)).when(mFragment).getText( 743 R.string.battery_used_for); 744 doReturn(mContext.getText(R.string.battery_active_for)).when(mFragment).getText( 745 R.string.battery_active_for); 746 747 mFragment.initPreference(mContext); 748 749 assertThat(mForegroundPreference.getSummary().toString()).isEqualTo("Used for 0 min"); 750 assertThat(mBackgroundPreference.getSummary().toString()).isEqualTo("Active for 0 min"); 751 } 752 753 @Test testInitPreferenceForTriState_isValidPackageName_hasCorrectString()754 public void testInitPreferenceForTriState_isValidPackageName_hasCorrectString() { 755 when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(false); 756 757 mFragment.initPreferenceForTriState(mContext); 758 759 assertThat(mFooterPreference.getTitle().toString()) 760 .isEqualTo("This app requires optimized battery usage."); 761 } 762 763 @Test testInitPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString()764 public void testInitPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() { 765 when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); 766 when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); 767 768 mFragment.initPreferenceForTriState(mContext); 769 770 assertThat(mFooterPreference.getTitle() 771 .toString()).isEqualTo("This app requires unrestricted battery usage."); 772 } 773 774 @Test testInitPreferenceForTriState_hasCorrectString()775 public void testInitPreferenceForTriState_hasCorrectString() { 776 when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); 777 when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false); 778 779 mFragment.initPreferenceForTriState(mContext); 780 781 assertThat(mFooterPreference.getTitle().toString()) 782 .isEqualTo("Changing how an app uses your battery can affect its performance."); 783 } 784 785 @Test testOnRadioButtonClicked_clickOptimizePref_optimizePreferenceChecked()786 public void testOnRadioButtonClicked_clickOptimizePref_optimizePreferenceChecked() { 787 mOptimizePreference.setKey(KEY_PREF_OPTIMIZED); 788 mRestrictedPreference.setKey(KEY_PREF_RESTRICTED); 789 mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED); 790 mFragment.onRadioButtonClicked(mOptimizePreference); 791 792 assertThat(mOptimizePreference.isChecked()).isTrue(); 793 assertThat(mRestrictedPreference.isChecked()).isFalse(); 794 assertThat(mUnrestrictedPreference.isChecked()).isFalse(); 795 } 796 797 @Test testOnPause_optimizationModeChanged_logPreference()798 public void testOnPause_optimizationModeChanged_logPreference() { 799 final int mode = BatteryOptimizeUtils.MODE_RESTRICTED; 800 mFragment.mOptimizationMode = mode; 801 when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); 802 mOptimizePreference.setKey(KEY_PREF_OPTIMIZED); 803 804 mFragment.onRadioButtonClicked(mOptimizePreference); 805 mFragment.onPause(); 806 807 verify(mMetricsFeatureProvider) 808 .action( 809 SettingsEnums.OPEN_APP_BATTERY_USAGE, 810 SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED, 811 SettingsEnums.OPEN_APP_BATTERY_USAGE, 812 /* package name*/ "none", 813 /* consumed battery */ 0); 814 } 815 816 @Test testOnPause_optimizationModeIsNotChanged_notInvokeLogging()817 public void testOnPause_optimizationModeIsNotChanged_notInvokeLogging() { 818 final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED; 819 mFragment.mOptimizationMode = mode; 820 when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); 821 mOptimizePreference.setKey(KEY_PREF_OPTIMIZED); 822 823 mFragment.onRadioButtonClicked(mOptimizePreference); 824 mFragment.onPause(); 825 826 verifyZeroInteractions(mMetricsFeatureProvider); 827 } 828 829 @Test notifyBackupManager_optimizationModeIsNotChanged_notInvokeDataChanged()830 public void notifyBackupManager_optimizationModeIsNotChanged_notInvokeDataChanged() { 831 final int mode = BatteryOptimizeUtils.MODE_RESTRICTED; 832 mFragment.mOptimizationMode = mode; 833 when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); 834 835 mFragment.notifyBackupManager(); 836 837 verifyZeroInteractions(mBackupManager); 838 } 839 840 @Test notifyBackupManager_optimizationModeIsChanged_invokeDataChanged()841 public void notifyBackupManager_optimizationModeIsChanged_invokeDataChanged() { 842 mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED; 843 when(mBatteryOptimizeUtils.getAppOptimizationMode()) 844 .thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED); 845 846 mFragment.notifyBackupManager(); 847 848 verify(mBackupManager).dataChanged(); 849 } 850 851 @Test notifyBackupManager_triStateIsNotEnabled_notInvokeDataChanged()852 public void notifyBackupManager_triStateIsNotEnabled_notInvokeDataChanged() { 853 mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED; 854 when(mBatteryOptimizeUtils.getAppOptimizationMode()) 855 .thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED); 856 mFragment.mEnableTriState = false; 857 858 mFragment.onPause(); 859 860 verifyZeroInteractions(mBackupManager); 861 } 862 } 863