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.applications.appinfo; 18 19 import static com.android.settings.applications.appinfo.AppButtonsPreferenceController.KEY_REMOVE_TASK_WHEN_FINISHING; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyBoolean; 25 import static org.mockito.ArgumentMatchers.anyInt; 26 import static org.mockito.ArgumentMatchers.anyString; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.doAnswer; 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.ActivityManager; 39 import android.app.admin.DevicePolicyManager; 40 import android.app.settings.SettingsEnums; 41 import android.content.Context; 42 import android.content.Intent; 43 import android.content.om.OverlayInfo; 44 import android.content.om.OverlayManager; 45 import android.content.pm.ApplicationInfo; 46 import android.content.pm.PackageInfo; 47 import android.content.pm.PackageManager; 48 import android.os.RemoteException; 49 import android.os.UserManager; 50 import android.util.ArraySet; 51 import android.view.View; 52 53 import androidx.preference.PreferenceScreen; 54 55 import com.android.settings.R; 56 import com.android.settings.SettingsActivity; 57 import com.android.settings.core.InstrumentedPreferenceFragment; 58 import com.android.settings.testutils.FakeFeatureFactory; 59 import com.android.settingslib.applications.AppUtils; 60 import com.android.settingslib.applications.ApplicationsState; 61 import com.android.settingslib.applications.instantapps.InstantAppDataProvider; 62 import com.android.settingslib.core.lifecycle.Lifecycle; 63 import com.android.settingslib.widget.ActionButtonsPreference; 64 65 import org.junit.After; 66 import org.junit.Before; 67 import org.junit.Test; 68 import org.junit.runner.RunWith; 69 import org.mockito.Answers; 70 import org.mockito.ArgumentCaptor; 71 import org.mockito.Mock; 72 import org.mockito.MockitoAnnotations; 73 import org.mockito.stubbing.Answer; 74 import org.robolectric.RobolectricTestRunner; 75 import org.robolectric.RuntimeEnvironment; 76 import org.robolectric.annotation.Config; 77 import org.robolectric.annotation.Implementation; 78 import org.robolectric.annotation.Implements; 79 import org.robolectric.annotation.Resetter; 80 import org.robolectric.util.ReflectionHelpers; 81 82 import java.util.Set; 83 84 @RunWith(RobolectricTestRunner.class) 85 public class AppButtonsPreferenceControllerTest { 86 87 private static final String PACKAGE_NAME = "com.android.settings"; 88 private static final String RRO_PACKAGE_NAME = "com.android.settings.overlay"; 89 private static final String RESOURCE_STRING = "string"; 90 private static final boolean ALL_USERS = false; 91 private static final boolean DISABLE_AFTER_INSTALL = true; 92 private static final int REQUEST_UNINSTALL = 0; 93 private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1; 94 private static final OverlayInfo OVERLAY_DISABLED = createFakeOverlay("overlay", false, 1); 95 private static final OverlayInfo OVERLAY_ENABLED = createFakeOverlay("overlay", true, 1); 96 97 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 98 private SettingsActivity mSettingsActivity; 99 @Mock 100 private TestFragment mFragment; 101 @Mock 102 private Lifecycle mLifecycle; 103 @Mock 104 private ApplicationsState mState; 105 @Mock 106 private ApplicationsState.AppEntry mAppEntry; 107 @Mock 108 private ApplicationInfo mAppInfo; 109 @Mock 110 private OverlayManager mOverlayManager; 111 @Mock 112 private PackageManager mPackageManger; 113 @Mock 114 private DevicePolicyManager mDpm; 115 @Mock 116 private ActivityManager mAm; 117 @Mock 118 private UserManager mUserManager; 119 @Mock 120 private PackageInfo mPackageInfo; 121 @Mock 122 private PreferenceScreen mScreen; 123 124 private Context mContext; 125 private Intent mUninstallIntent; 126 private ActionButtonsPreference mButtonPrefs; 127 private AppButtonsPreferenceController mController; 128 129 @Before setUp()130 public void setUp() { 131 MockitoAnnotations.initMocks(this); 132 133 FakeFeatureFactory.setupForTest(); 134 mContext = RuntimeEnvironment.application; 135 doReturn(mDpm).when(mSettingsActivity).getSystemService(Context.DEVICE_POLICY_SERVICE); 136 doReturn(mUserManager).when(mSettingsActivity).getSystemService(Context.USER_SERVICE); 137 doReturn(mPackageManger).when(mSettingsActivity).getPackageManager(); 138 doReturn(mAm).when(mSettingsActivity).getSystemService(Context.ACTIVITY_SERVICE); 139 doReturn(mOverlayManager).when(mSettingsActivity). 140 getSystemService(OverlayManager.class); 141 doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt()); 142 doReturn(mContext).when(mSettingsActivity).getApplicationContext(); 143 when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(RESOURCE_STRING); 144 145 mController = spy(new AppButtonsPreferenceController(mSettingsActivity, mFragment, 146 mLifecycle, PACKAGE_NAME, mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN)); 147 148 mAppEntry.info = mAppInfo; 149 mAppInfo.packageName = PACKAGE_NAME; 150 mAppInfo.flags = 0; 151 mPackageInfo.packageName = PACKAGE_NAME; 152 mPackageInfo.applicationInfo = mAppInfo; 153 154 mButtonPrefs = createMock(); 155 mController.mButtonsPref = mButtonPrefs; 156 mController.mPackageInfo = mPackageInfo; 157 158 final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 159 Answer<Void> callable = invocation -> { 160 mUninstallIntent = captor.getValue(); 161 return null; 162 }; 163 doAnswer(callable).when(mFragment).startActivityForResult(captor.capture(), anyInt()); 164 } 165 166 @After tearDown()167 public void tearDown() { 168 ShadowAppUtils.reset(); 169 } 170 171 @Test 172 @Config(shadows = ShadowAppUtils.class) isAvailable_validPackageName_isTrue()173 public void isAvailable_validPackageName_isTrue() { 174 assertThat(mController.isAvailable()).isTrue(); 175 } 176 177 @Test isAvailable_nullPackageName_isFalse()178 public void isAvailable_nullPackageName_isFalse() { 179 final AppButtonsPreferenceController controller = spy( 180 new AppButtonsPreferenceController(mSettingsActivity, mFragment, 181 mLifecycle, null, mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN)); 182 183 assertThat(controller.isAvailable()).isFalse(); 184 } 185 186 @Test retrieveAppEntry_hasAppEntry_notNull()187 public void retrieveAppEntry_hasAppEntry_notNull() 188 throws PackageManager.NameNotFoundException { 189 doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt()); 190 191 mController.retrieveAppEntry(); 192 193 assertThat(mController.mAppEntry).isNotNull(); 194 assertThat(mController.mPackageInfo).isNotNull(); 195 } 196 197 @Test retrieveAppEntry_noAppEntry_null()198 public void retrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException { 199 doReturn(null).when(mState).getEntry(eq(PACKAGE_NAME), anyInt()); 200 doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt()); 201 202 mController.retrieveAppEntry(); 203 204 assertThat(mController.mAppEntry).isNull(); 205 assertThat(mController.mPackageInfo).isNull(); 206 } 207 208 @Test retrieveAppEntry_throwException_null()209 public void retrieveAppEntry_throwException_null() throws 210 PackageManager.NameNotFoundException { 211 doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt()); 212 doThrow(new PackageManager.NameNotFoundException()).when(mPackageManger).getPackageInfo( 213 anyString(), anyInt()); 214 215 mController.retrieveAppEntry(); 216 217 assertThat(mController.mAppEntry).isNotNull(); 218 assertThat(mController.mPackageInfo).isNull(); 219 } 220 221 @Test updateOpenButton_noLaunchIntent_buttonShouldBeDisable()222 public void updateOpenButton_noLaunchIntent_buttonShouldBeDisable() { 223 mController.updateOpenButton(); 224 225 verify(mButtonPrefs).setButton1Visible(false); 226 } 227 228 @Test updateOpenButton_haveLaunchIntent_buttonShouldBeEnable()229 public void updateOpenButton_haveLaunchIntent_buttonShouldBeEnable() { 230 doReturn(new Intent()).when(mPackageManger).getLaunchIntentForPackage(anyString()); 231 232 mController.updateOpenButton(); 233 234 verify(mButtonPrefs).setButton1Visible(true); 235 } 236 237 @Test updateUninstallButton_isSystemApp_handleAsDisableableButton()238 public void updateUninstallButton_isSystemApp_handleAsDisableableButton() { 239 doReturn(false).when(mController).handleDisableable(); 240 mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 241 242 mController.updateUninstallButton(); 243 244 verify(mController).handleDisableable(); 245 verify(mButtonPrefs).setButton2Enabled(false); 246 } 247 248 @Test 249 @Config(shadows = ShadowAppUtils.class) isAvailable_nonInstantApp()250 public void isAvailable_nonInstantApp() { 251 mController.mAppEntry = mAppEntry; 252 assertThat(mController.isAvailable()).isTrue(); 253 } 254 255 @Test isAvailable_instantApp()256 public void isAvailable_instantApp() { 257 mController.mAppEntry = mAppEntry; 258 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 259 new InstantAppDataProvider() { 260 @Override 261 public boolean isInstantApp(ApplicationInfo info) { 262 return true; 263 } 264 }); 265 assertThat(mController.isAvailable()).isFalse(); 266 } 267 268 @Test updateUninstallButton_isDeviceAdminApp_setButtonDisable()269 public void updateUninstallButton_isDeviceAdminApp_setButtonDisable() { 270 doReturn(true).when(mController).handleDisableable(); 271 mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 272 doReturn(true).when(mDpm).packageHasActiveAdmins(anyString()); 273 274 mController.updateUninstallButton(); 275 276 verify(mController).handleDisableable(); 277 verify(mButtonPrefs).setButton2Enabled(false); 278 } 279 280 @Test updateUninstallButton_isSystemAndIsProfileOrDeviceOwner_setButtonDisable()281 public void updateUninstallButton_isSystemAndIsProfileOrDeviceOwner_setButtonDisable() { 282 doReturn(true).when(mController).isSystemPackage(any(), any(), any()); 283 doReturn(true).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString()); 284 285 mController.updateUninstallButton(); 286 287 verify(mButtonPrefs).setButton2Enabled(false); 288 } 289 290 @Test updateUninstallButton_isSystemAndIsNotProfileOrDeviceOwner_setButtonEnabled()291 public void updateUninstallButton_isSystemAndIsNotProfileOrDeviceOwner_setButtonEnabled() { 292 doReturn(true).when(mController).isSystemPackage(any(), any(), any()); 293 doReturn(false).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString()); 294 295 mController.updateUninstallButton(); 296 297 verify(mButtonPrefs).setButton2Enabled(true); 298 } 299 300 @Test updateUninstallButton_isNotSystemAndIsProfileOrDeviceOwner_setButtonDisable()301 public void updateUninstallButton_isNotSystemAndIsProfileOrDeviceOwner_setButtonDisable() { 302 doReturn(false).when(mController).isSystemPackage(any(), any(), any()); 303 doReturn(0).when(mDpm).getDeviceOwnerUserId(); 304 doReturn(true).when(mDpm).isDeviceOwnerApp(anyString()); 305 306 mController.updateUninstallButton(); 307 308 verify(mButtonPrefs).setButton2Enabled(false); 309 } 310 311 @Test updateUninstallButton_isNotSystemAndIsNotProfileOrDeviceOwner_setButtonEnabled()312 public void updateUninstallButton_isNotSystemAndIsNotProfileOrDeviceOwner_setButtonEnabled() { 313 doReturn(false).when(mController).isSystemPackage(any(), any(), any()); 314 doReturn(10).when(mDpm).getDeviceOwnerUserId(); 315 doReturn(false).when(mDpm).isDeviceOwnerApp(anyString()); 316 317 mController.updateUninstallButton(); 318 319 verify(mButtonPrefs).setButton2Enabled(true); 320 } 321 322 @Test updateUninstallButton_isDeviceProvisioningApp_setButtonDisable()323 public void updateUninstallButton_isDeviceProvisioningApp_setButtonDisable() { 324 doReturn(true).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString()); 325 when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(PACKAGE_NAME); 326 327 mController.updateUninstallButton(); 328 329 verify(mButtonPrefs).setButton2Enabled(false); 330 } 331 332 @Test updateUninstallButton_isUninstallInQueue_setButtonDisable()333 public void updateUninstallButton_isUninstallInQueue_setButtonDisable() { 334 doReturn(true).when(mDpm).isUninstallInQueue(any()); 335 336 mController.updateUninstallButton(); 337 338 verify(mButtonPrefs).setButton2Enabled(false); 339 } 340 341 @Test updateUninstallButton_isHomeAppAndBundled_setButtonDisable()342 public void updateUninstallButton_isHomeAppAndBundled_setButtonDisable() { 343 mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 344 mController.mHomePackages.add(PACKAGE_NAME); 345 346 mController.updateUninstallButton(); 347 348 verify(mButtonPrefs).setButton2Enabled(false); 349 } 350 351 @Test updateUninstallButton_isSystemRro_setButtonDisable()352 public void updateUninstallButton_isSystemRro_setButtonDisable() { 353 mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 354 355 when(mAppInfo.isResourceOverlay()).thenReturn(true); 356 357 mController.updateUninstallButton(); 358 359 verify(mButtonPrefs).setButton2Enabled(false); 360 } 361 362 @Test updateUninstallButton_isNonSystemRro_setButtonDisable()363 public void updateUninstallButton_isNonSystemRro_setButtonDisable() 364 throws RemoteException { 365 when(mAppInfo.isResourceOverlay()).thenReturn(true); 366 when(mOverlayManager.getOverlayInfo(anyString(), any())) 367 .thenReturn(OVERLAY_ENABLED); 368 369 mController.updateUninstallButton(); 370 371 verify(mButtonPrefs).setButton2Enabled(false); 372 } 373 374 @Test updateUninstallButton_isNonSystemRro_setButtonEnable()375 public void updateUninstallButton_isNonSystemRro_setButtonEnable() 376 throws RemoteException { 377 when(mAppInfo.isResourceOverlay()).thenReturn(true); 378 when(mOverlayManager.getOverlayInfo(anyString(), any())) 379 .thenReturn(OVERLAY_DISABLED); 380 381 mController.updateUninstallButton(); 382 383 verify(mButtonPrefs).setButton2Enabled(true); 384 } 385 386 @Test updateForceStopButton_HasActiveAdmins_setButtonDisable()387 public void updateForceStopButton_HasActiveAdmins_setButtonDisable() { 388 doReturn(true).when(mDpm).packageHasActiveAdmins(anyString()); 389 390 mController.updateForceStopButton(); 391 392 verify(mController).updateForceStopButtonInner(false); 393 } 394 395 @Test updateForceStopButton_AppNotStopped_setButtonEnable()396 public void updateForceStopButton_AppNotStopped_setButtonEnable() { 397 mController.updateForceStopButton(); 398 399 verify(mController).updateForceStopButtonInner(true); 400 } 401 402 @Test uninstallPkg_intentSent()403 public void uninstallPkg_intentSent() { 404 mController.uninstallPkg(PACKAGE_NAME, ALL_USERS, DISABLE_AFTER_INSTALL); 405 406 verify(mFragment).startActivityForResult(any(), eq(REQUEST_UNINSTALL)); 407 assertThat( 408 mUninstallIntent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true)) 409 .isEqualTo(ALL_USERS); 410 assertThat(mUninstallIntent.getAction()).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE); 411 assertThat(mController.mDisableAfterUninstall).isEqualTo(DISABLE_AFTER_INSTALL); 412 } 413 414 @Test forceStopPackage_methodInvokedAndUpdated()415 public void forceStopPackage_methodInvokedAndUpdated() { 416 final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class); 417 doReturn(appEntry).when(mState).getEntry(anyString(), anyInt()); 418 doNothing().when(mController).updateForceStopButton(); 419 420 mController.forceStopPackage(PACKAGE_NAME); 421 422 verify(mAm).forceStopPackage(PACKAGE_NAME); 423 assertThat(mController.mAppEntry).isSameInstanceAs(appEntry); 424 verify(mController).updateForceStopButton(); 425 } 426 427 @Test handleDisableable_isHomeApp_notControllable()428 public void handleDisableable_isHomeApp_notControllable() { 429 mController.mHomePackages.add(PACKAGE_NAME); 430 431 final boolean controllable = mController.handleDisableable(); 432 433 verify(mButtonPrefs).setButton2Text(R.string.disable_text); 434 assertThat(controllable).isFalse(); 435 } 436 437 @Test handleDisableable_isAppEnabled_controllable()438 public void handleDisableable_isAppEnabled_controllable() { 439 mAppEntry.info.enabled = true; 440 mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 441 doReturn(false).when(mController).isSystemPackage(any(), any(), any()); 442 443 final boolean controllable = mController.handleDisableable(); 444 445 verify(mButtonPrefs).setButton2Text(R.string.disable_text); 446 assertThat(controllable).isTrue(); 447 } 448 449 @Test handleDisableable_isAppDisabled_controllable()450 public void handleDisableable_isAppDisabled_controllable() { 451 mAppEntry.info.enabled = false; 452 mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 453 doReturn(false).when(mController).isSystemPackage(any(), any(), any()); 454 455 final boolean controllable = mController.handleDisableable(); 456 457 verify(mButtonPrefs).setButton2Text(R.string.enable_text); 458 assertThat(controllable).isTrue(); 459 } 460 461 @Test handleActivityResult_packageUninstalled_shouldFinishPrefernecePanel()462 public void handleActivityResult_packageUninstalled_shouldFinishPrefernecePanel() { 463 doReturn(false).when(mController).refreshUi(); 464 465 mController.handleActivityResult(REQUEST_UNINSTALL, 0, mock(Intent.class)); 466 467 verify(mSettingsActivity).finishPreferencePanel(anyInt(), any(Intent.class)); 468 } 469 470 @Test refreshUi_packageNull_shouldNotCrash()471 public void refreshUi_packageNull_shouldNotCrash() { 472 mController.mPackageName = null; 473 474 // Should not crash in this method 475 assertThat(mController.refreshUi()).isFalse(); 476 } 477 478 @Test refreshUi_buttonPreferenceNull_shouldNotCrash()479 public void refreshUi_buttonPreferenceNull_shouldNotCrash() 480 throws PackageManager.NameNotFoundException { 481 doReturn(AppButtonsPreferenceController.AVAILABLE) 482 .when(mController).getAvailabilityStatus(); 483 doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt()); 484 doReturn(mButtonPrefs).when(mScreen).findPreference(anyString()); 485 mController.displayPreference(mScreen); 486 mController.mButtonsPref = null; 487 488 // Should not crash in this method 489 assertThat(mController.refreshUi()).isTrue(); 490 } 491 492 @Test onPackageListChanged_available_shouldRefreshUi()493 public void onPackageListChanged_available_shouldRefreshUi() { 494 doReturn(AppButtonsPreferenceController.AVAILABLE) 495 .when(mController).getAvailabilityStatus(); 496 doReturn(true).when(mController).refreshUi(); 497 498 mController.onPackageListChanged(); 499 500 verify(mController).refreshUi(); 501 } 502 503 @Test onPackageListChanged_notAvailable_shouldNotRefreshUiAndNoCrash()504 public void onPackageListChanged_notAvailable_shouldNotRefreshUiAndNoCrash() { 505 doReturn(AppButtonsPreferenceController.DISABLED_FOR_USER) 506 .when(mController).getAvailabilityStatus(); 507 508 mController.onPackageListChanged(); 509 510 verify(mController, never()).refreshUi(); 511 // Should not crash in this method 512 } 513 514 @Test 515 @Config(shadows = ShadowAppUtils.class) getAvailabilityStatus_systemModule()516 public void getAvailabilityStatus_systemModule() { 517 ShadowAppUtils.addHiddenModule(mController.mPackageName); 518 assertThat(mController.getAvailabilityStatus()).isEqualTo( 519 AppButtonsPreferenceController.DISABLED_FOR_USER); 520 } 521 522 @Test handleActivityResult_onAppUninstall_removeTask()523 public void handleActivityResult_onAppUninstall_removeTask() { 524 mController.handleActivityResult(REQUEST_UNINSTALL, 0, new Intent()); 525 526 ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class); 527 verify(mSettingsActivity).finishPreferencePanel(anyInt(), argumentCaptor.capture()); 528 529 final Intent i = argumentCaptor.getValue(); 530 assertThat(i).isNotNull(); 531 assertThat(i.getBooleanExtra(KEY_REMOVE_TASK_WHEN_FINISHING, false)).isTrue(); 532 } 533 534 @Test handleActivityResult_onAppNotUninstall_persistTask()535 public void handleActivityResult_onAppNotUninstall_persistTask() { 536 mController.handleActivityResult(REQUEST_UNINSTALL + 1, 0, new Intent()); 537 538 ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class); 539 verify(mSettingsActivity).finishPreferencePanel(anyInt(), argumentCaptor.capture()); 540 541 final Intent i = argumentCaptor.getValue(); 542 assertThat(i).isNotNull(); 543 assertThat(i.getBooleanExtra(KEY_REMOVE_TASK_WHEN_FINISHING, false)).isFalse(); 544 } 545 546 @Test 547 @Config(shadows = ShadowAppUtils.class) isAvailable_nonMainlineModule_isTrue()548 public void isAvailable_nonMainlineModule_isTrue() { 549 assertThat(mController.isAvailable()).isTrue(); 550 } 551 552 @Test 553 @Config(shadows = ShadowAppUtils.class) isAvailable_mainlineModule_isFalse()554 public void isAvailable_mainlineModule_isFalse() { 555 ShadowAppUtils.addMainlineModule(mController.mPackageName); 556 assertThat(mController.isAvailable()).isFalse(); 557 } 558 559 /** 560 * The test fragment which implements 561 * {@link ButtonActionDialogFragment.AppButtonsDialogListener} 562 */ 563 public static class TestFragment extends InstrumentedPreferenceFragment 564 implements ButtonActionDialogFragment.AppButtonsDialogListener { 565 566 @Override handleDialogClick(int type)567 public void handleDialogClick(int type) { 568 // Do nothing 569 } 570 571 @Override getMetricsCategory()572 public int getMetricsCategory() { 573 return SettingsEnums.PAGE_UNKNOWN; 574 } 575 } 576 createMock()577 private ActionButtonsPreference createMock() { 578 final ActionButtonsPreference pref = mock(ActionButtonsPreference.class); 579 when(pref.setButton1Text(anyInt())).thenReturn(pref); 580 when(pref.setButton1Icon(anyInt())).thenReturn(pref); 581 when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref); 582 when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref); 583 when(pref.setButton2Text(anyInt())).thenReturn(pref); 584 when(pref.setButton2Icon(anyInt())).thenReturn(pref); 585 when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref); 586 when(pref.setButton2Visible(anyBoolean())).thenReturn(pref); 587 when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref); 588 when(pref.setButton3Text(anyInt())).thenReturn(pref); 589 when(pref.setButton3Icon(anyInt())).thenReturn(pref); 590 when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref); 591 when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref); 592 593 return pref; 594 } 595 createFakeOverlay(String pkg, boolean enabled, int priority)596 private static OverlayInfo createFakeOverlay(String pkg, boolean enabled, int priority) { 597 final int state = (enabled) ? OverlayInfo.STATE_ENABLED : OverlayInfo.STATE_DISABLED; 598 return new OverlayInfo(pkg /* packageName */, 599 "target.package" /* targetPackageName */, 600 "theme" /* targetOverlayableName */, 601 "category", /* category */ 602 "package", /* baseCodePath */ 603 state, 604 0 /* userId */, 605 priority, 606 false /* isStatic */); 607 } 608 609 @Implements(AppUtils.class) 610 public static class ShadowAppUtils { 611 612 public static Set<String> sSystemModules = new ArraySet<>(); 613 public static Set<String> sMainlineModules = new ArraySet<>(); 614 615 @Resetter reset()616 public static void reset() { 617 sSystemModules.clear(); 618 sMainlineModules.clear(); 619 } 620 addHiddenModule(String pkg)621 public static void addHiddenModule(String pkg) { 622 sSystemModules.add(pkg); 623 } 624 addMainlineModule(String pkg)625 public static void addMainlineModule(String pkg) { 626 sMainlineModules.add(pkg); 627 } 628 629 @Implementation isInstant(ApplicationInfo info)630 protected static boolean isInstant(ApplicationInfo info) { 631 return false; 632 } 633 634 @Implementation isSystemModule(Context context, String packageName)635 protected static boolean isSystemModule(Context context, String packageName) { 636 return sSystemModules.contains(packageName); 637 } 638 639 @Implementation isMainlineModule(PackageManager pm, String packageName)640 protected static boolean isMainlineModule(PackageManager pm, String packageName) { 641 return sMainlineModules.contains(packageName); 642 } 643 } 644 } 645