• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
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