Home | History | Annotate | Download | only in appinfo
      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.AppInfoDashboardFragment.ARG_PACKAGE_NAME;
     20 import static com.android.settings.applications.appinfo.AppInfoDashboardFragment
     21         .UNINSTALL_ALL_USERS_MENU;
     22 import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.UNINSTALL_UPDATES;
     23 import static com.google.common.truth.Truth.assertThat;
     24 import static org.mockito.ArgumentMatchers.any;
     25 import static org.mockito.ArgumentMatchers.nullable;
     26 import static org.mockito.Mockito.doNothing;
     27 import static org.mockito.Mockito.doReturn;
     28 import static org.mockito.Mockito.mock;
     29 import static org.mockito.Mockito.never;
     30 import static org.mockito.Mockito.spy;
     31 import static org.mockito.Mockito.times;
     32 import static org.mockito.Mockito.verify;
     33 import static org.mockito.Mockito.when;
     34 
     35 import android.app.admin.DevicePolicyManager;
     36 import android.content.Context;
     37 import android.content.Intent;
     38 import android.content.pm.ApplicationInfo;
     39 import android.content.pm.PackageInfo;
     40 import android.content.pm.PackageManager;
     41 import android.content.pm.UserInfo;
     42 import android.os.Bundle;
     43 import android.os.UserManager;
     44 import android.view.Menu;
     45 import android.view.MenuItem;
     46 
     47 import com.android.settings.SettingsActivity;
     48 import com.android.settings.SettingsPreferenceFragment;
     49 import com.android.settings.testutils.SettingsRobolectricTestRunner;
     50 import com.android.settingslib.applications.AppUtils;
     51 import com.android.settingslib.applications.ApplicationsState.AppEntry;
     52 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
     53 import com.android.settingslib.core.lifecycle.Lifecycle;
     54 
     55 import org.junit.Before;
     56 import org.junit.Test;
     57 import org.junit.runner.RunWith;
     58 import org.mockito.Answers;
     59 import org.mockito.ArgumentCaptor;
     60 import org.mockito.Mock;
     61 import org.mockito.MockitoAnnotations;
     62 import org.robolectric.RuntimeEnvironment;
     63 import org.robolectric.annotation.Config;
     64 import org.robolectric.util.ReflectionHelpers;
     65 
     66 import java.util.ArrayList;
     67 import java.util.List;
     68 
     69 @RunWith(SettingsRobolectricTestRunner.class)
     70 public final class AppInfoDashboardFragmentTest {
     71 
     72     private static final String PACKAGE_NAME = "test_package_name";
     73 
     74     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     75     private UserManager mUserManager;
     76     @Mock
     77     private SettingsActivity mActivity;
     78     @Mock
     79     private DevicePolicyManager mDevicePolicyManager;
     80     @Mock
     81     private PackageManager mPackageManager;
     82 
     83     private AppInfoDashboardFragment mFragment;
     84     private Context mShadowContext;
     85 
     86     @Before
     87     public void setUp() {
     88         MockitoAnnotations.initMocks(this);
     89         mShadowContext = RuntimeEnvironment.application;
     90         mFragment = spy(new AppInfoDashboardFragment());
     91         doReturn(mActivity).when(mFragment).getActivity();
     92         doReturn(mShadowContext).when(mFragment).getContext();
     93         doReturn(mPackageManager).when(mActivity).getPackageManager();
     94 
     95         // Default to not considering any apps to be instant (individual tests can override this).
     96         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
     97                 (InstantAppDataProvider) (i -> false));
     98     }
     99 
    100     @Test
    101     public void shouldShowUninstallForAll_installForOneOtherUserOnly_shouldReturnTrue() {
    102         when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
    103         when(mUserManager.getUsers().size()).thenReturn(2);
    104         ReflectionHelpers.setField(mFragment, "mDpm", mDevicePolicyManager);
    105         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
    106         final ApplicationInfo info = new ApplicationInfo();
    107         info.enabled = true;
    108         final AppEntry appEntry = mock(AppEntry.class);
    109         appEntry.info = info;
    110         final PackageInfo packageInfo = mock(PackageInfo.class);
    111         ReflectionHelpers.setField(mFragment, "mPackageInfo", packageInfo);
    112 
    113         assertThat(mFragment.shouldShowUninstallForAll(appEntry)).isTrue();
    114     }
    115 
    116     @Test
    117     public void shouldShowUninstallForAll_installForSelfOnly_shouldReturnFalse() {
    118         when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
    119         when(mUserManager.getUsers().size()).thenReturn(2);
    120         ReflectionHelpers.setField(mFragment, "mDpm", mDevicePolicyManager);
    121         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
    122         final ApplicationInfo info = new ApplicationInfo();
    123         info.flags = ApplicationInfo.FLAG_INSTALLED;
    124         info.enabled = true;
    125         final AppEntry appEntry = mock(AppEntry.class);
    126         appEntry.info = info;
    127         final PackageInfo packageInfo = mock(PackageInfo.class);
    128         ReflectionHelpers.setField(mFragment, "mPackageInfo", packageInfo);
    129 
    130         assertThat(mFragment.shouldShowUninstallForAll(appEntry)).isFalse();
    131     }
    132 
    133     @Test
    134     public void onPrepareOptionsMenu_setUpdateMenuVisible_byDefaultForSystemApps_shouldBeTrue() {
    135         Menu menu = onPrepareOptionsMenuTestsSetup();
    136         mFragment.onPrepareOptionsMenu(menu);
    137 
    138         verify(menu.findItem(UNINSTALL_UPDATES), times(1)).setVisible(true);
    139     }
    140 
    141     @Test
    142     @Config(qualifiers = "mcc999")
    143     public void onPrepareOptionsMenu_setUpdateMenuVisible_ifDisabledByDevice_shouldBeFalse() {
    144         Menu menu = onPrepareOptionsMenuTestsSetup();
    145         mFragment.onPrepareOptionsMenu(menu);
    146 
    147         verify(menu.findItem(UNINSTALL_UPDATES), times(1)).setVisible(false);
    148     }
    149 
    150     private Menu onPrepareOptionsMenuTestsSetup() {
    151         // Menu mocking
    152         Menu menu = mock(Menu.class);
    153         final MenuItem uninstallUpdatesMenuItem = mock(MenuItem.class);
    154         final MenuItem uninstallForAllMenuItem = mock(MenuItem.class);
    155         when(menu.findItem(UNINSTALL_UPDATES)).thenReturn(uninstallUpdatesMenuItem);
    156         when(menu.findItem(UNINSTALL_ALL_USERS_MENU)).thenReturn(uninstallForAllMenuItem);
    157 
    158         // Setup work to prevent NPE
    159         final ApplicationInfo info = new ApplicationInfo();
    160         info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
    161         info.enabled = true;
    162         final AppEntry appEntry = mock(AppEntry.class);
    163         appEntry.info = info;
    164         mFragment.setAppEntry(appEntry);
    165 
    166         return menu;
    167     }
    168 
    169     @Test
    170     public void launchFragment_hasNoPackageInfo_shouldFinish() {
    171         ReflectionHelpers.setField(mFragment, "mPackageInfo", null);
    172 
    173         assertThat(mFragment.ensurePackageInfoAvailable(mActivity)).isFalse();
    174         verify(mActivity).finishAndRemoveTask();
    175     }
    176 
    177     @Test
    178     public void launchFragment_hasPackageInfo_shouldReturnTrue() {
    179         final PackageInfo packageInfo = mock(PackageInfo.class);
    180         ReflectionHelpers.setField(mFragment, "mPackageInfo", packageInfo);
    181 
    182         assertThat(mFragment.ensurePackageInfoAvailable(mActivity)).isTrue();
    183         verify(mActivity, never()).finishAndRemoveTask();
    184     }
    185 
    186     @Test
    187     public void packageSizeChange_isOtherPackage_shouldNotRefreshUi() {
    188         ReflectionHelpers.setField(mFragment, "mPackageName", PACKAGE_NAME);
    189         mFragment.onPackageSizeChanged("Not_" + PACKAGE_NAME);
    190 
    191         verify(mFragment, never()).refreshUi();
    192     }
    193 
    194     @Test
    195     public void packageSizeChange_isOwnPackage_shouldRefreshUi() {
    196         doReturn(Boolean.TRUE).when(mFragment).refreshUi();
    197         ReflectionHelpers.setField(mFragment, "mPackageName", PACKAGE_NAME);
    198 
    199         mFragment.onPackageSizeChanged(PACKAGE_NAME);
    200 
    201         verify(mFragment).refreshUi();
    202     }
    203 
    204     // Tests that we don't show the "uninstall for all users" button for instant apps.
    205     @Test
    206     public void instantApps_noUninstallForAllButton() {
    207         // Make this app appear to be instant.
    208         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
    209                 (InstantAppDataProvider) (i -> true));
    210         when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
    211         when(mUserManager.getUsers().size()).thenReturn(2);
    212 
    213         final ApplicationInfo info = new ApplicationInfo();
    214         info.enabled = true;
    215         final AppEntry appEntry = mock(AppEntry.class);
    216         appEntry.info = info;
    217         final PackageInfo packageInfo = mock(PackageInfo.class);
    218 
    219         ReflectionHelpers.setField(mFragment, "mDpm", mDevicePolicyManager);
    220         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
    221         ReflectionHelpers.setField(mFragment, "mPackageInfo", packageInfo);
    222 
    223         assertThat(mFragment.shouldShowUninstallForAll(appEntry)).isFalse();
    224     }
    225 
    226     @Test
    227     public void onActivityResult_uninstalledUpdates_shouldInvalidateOptionsMenu() {
    228         doReturn(true).when(mFragment).refreshUi();
    229 
    230         mFragment.onActivityResult(mFragment.REQUEST_UNINSTALL, 0, mock(Intent.class));
    231 
    232         verify(mActivity).invalidateOptionsMenu();
    233     }
    234 
    235     @Test
    236     public void onActivityResult_packageUninstalled_shouldFinishAndRemoveTask() {
    237         doReturn(false).when(mFragment).refreshUi();
    238 
    239         mFragment.onActivityResult(mFragment.REQUEST_UNINSTALL, 0, mock(Intent.class));
    240 
    241         verify(mActivity).finishAndRemoveTask();
    242     }
    243 
    244     @Test
    245     public void getPreferenceControllers_noPackageInfo_shouldReturnNull() {
    246         doNothing().when(mFragment).retrieveAppEntry();
    247 
    248         assertThat(mFragment.createPreferenceControllers(mShadowContext)).isNull();
    249     }
    250 
    251     @Test
    252     public void getNumberOfUserWithPackageInstalled_twoUsersInstalled_shouldReturnTwo()
    253             throws PackageManager.NameNotFoundException {
    254         final String packageName = "Package1";
    255         final int userID1 = 1;
    256         final int userID2 = 2;
    257         final List<UserInfo> userInfos = new ArrayList<>();
    258         userInfos.add(new UserInfo(userID1, "User1", UserInfo.FLAG_PRIMARY));
    259         userInfos.add(new UserInfo(userID2, "yue", UserInfo.FLAG_GUEST));
    260         when(mUserManager.getUsers(true)).thenReturn(userInfos);
    261         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
    262         final ApplicationInfo appInfo = new ApplicationInfo();
    263         appInfo.flags = ApplicationInfo.FLAG_INSTALLED;
    264         when(mPackageManager.getApplicationInfoAsUser(
    265                 packageName, PackageManager.GET_META_DATA, userID1))
    266                 .thenReturn(appInfo);
    267         when(mPackageManager.getApplicationInfoAsUser(
    268                 packageName, PackageManager.GET_META_DATA, userID2))
    269                 .thenReturn(appInfo);
    270         ReflectionHelpers.setField(mFragment, "mPm", mPackageManager);
    271 
    272         assertThat(mFragment.getNumberOfUserWithPackageInstalled(packageName)).isEqualTo(2);
    273     }
    274 
    275     @Test
    276     public void getNumberOfUserWithPackageInstalled_oneUserInstalled_shouldReturnOne()
    277             throws PackageManager.NameNotFoundException {
    278         final String packageName = "Package1";
    279         final int userID1 = 1;
    280         final int userID2 = 2;
    281         final List<UserInfo> userInfos = new ArrayList<>();
    282         userInfos.add(new UserInfo(userID1, "User1", UserInfo.FLAG_PRIMARY));
    283         userInfos.add(new UserInfo(userID2, "yue", UserInfo.FLAG_GUEST));
    284         when(mUserManager.getUsers(true)).thenReturn(userInfos);
    285         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
    286         final ApplicationInfo appInfo = new ApplicationInfo();
    287         appInfo.flags = ApplicationInfo.FLAG_INSTALLED;
    288         when(mPackageManager.getApplicationInfoAsUser(
    289                 packageName, PackageManager.GET_META_DATA, userID1))
    290                 .thenReturn(appInfo);
    291         when(mPackageManager.getApplicationInfoAsUser(
    292                 packageName, PackageManager.GET_META_DATA, userID2))
    293                 .thenThrow(new PackageManager.NameNotFoundException());
    294         ReflectionHelpers.setField(mFragment, "mPm", mPackageManager);
    295 
    296         assertThat(mFragment.getNumberOfUserWithPackageInstalled(packageName)).isEqualTo(1);
    297     }
    298 
    299     @Test
    300     public void onDestroy_shouldUnregisterReceiver() {
    301         final Context context = mock(Context.class);
    302         doReturn(context).when(mFragment).getContext();
    303         ReflectionHelpers.setField(mFragment, "mLifecycle", mock(Lifecycle.class));
    304         ReflectionHelpers.setField(mFragment, "mCheckedForLoaderManager", true);
    305         mFragment.startListeningToPackageRemove();
    306 
    307         mFragment.onDestroy();
    308 
    309         verify(context).unregisterReceiver(mFragment.mPackageRemovedReceiver);
    310     }
    311 
    312     @Test
    313     public void startAppInfoFragment_noCrashOnNullArgs() {
    314         final SettingsPreferenceFragment caller = mock(SettingsPreferenceFragment.class);
    315         final SettingsActivity sa = mock(SettingsActivity.class);
    316         when(caller.getActivity()).thenReturn(sa);
    317         when(caller.getContext()).thenReturn(sa);
    318         final AppEntry appEntry = mock(AppEntry.class);
    319         appEntry.info = mock(ApplicationInfo.class);
    320 
    321         AppInfoDashboardFragment.startAppInfoFragment(AppInfoDashboardFragment.class, 0, null,
    322                 caller, appEntry);
    323     }
    324 
    325     @Test
    326     public void startAppInfoFragment_includesNewAndOldArgs() {
    327         final SettingsPreferenceFragment caller = mock(SettingsPreferenceFragment.class);
    328         final SettingsActivity sa = mock(SettingsActivity.class);
    329         when(caller.getContext()).thenReturn(sa);
    330         final AppEntry appEntry = mock(AppEntry.class);
    331         appEntry.info = mock(ApplicationInfo.class);
    332 
    333         final Bundle bundle = new Bundle();
    334         bundle.putString("test", "test");
    335 
    336         AppInfoDashboardFragment.startAppInfoFragment(AppInfoDashboardFragment.class, 0, bundle,
    337                 caller, appEntry);
    338 
    339         final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
    340 
    341         verify(caller).startActivityForResult(intent.capture(), any(Integer.class));
    342         assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
    343                 .containsKey("test"))
    344                 .isTrue();
    345         assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
    346                 .containsKey(ARG_PACKAGE_NAME))
    347                 .isTrue();
    348     }
    349 }
    350