Home | History | Annotate | Download | only in fuelgauge
      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.google.common.truth.Truth.assertThat;
     20 
     21 import static org.mockito.Matchers.any;
     22 import static org.mockito.Matchers.anyInt;
     23 import static org.mockito.Matchers.anyString;
     24 import static org.mockito.Matchers.eq;
     25 import static org.mockito.Mockito.doAnswer;
     26 import static org.mockito.Mockito.doNothing;
     27 import static org.mockito.Mockito.doReturn;
     28 import static org.mockito.Mockito.doThrow;
     29 import static org.mockito.Mockito.mock;
     30 import static org.mockito.Mockito.spy;
     31 import static org.mockito.Mockito.verify;
     32 import static org.mockito.Mockito.when;
     33 
     34 import android.app.ActivityManager;
     35 import android.app.Application;
     36 import android.app.Fragment;
     37 import android.content.Context;
     38 import android.content.Intent;
     39 import android.content.pm.ApplicationInfo;
     40 import android.content.pm.PackageInfo;
     41 import android.content.pm.PackageManager;
     42 import android.os.UserManager;
     43 import android.widget.Button;
     44 
     45 import com.android.settings.R;
     46 import com.android.settings.SettingsActivity;
     47 import com.android.settings.TestConfig;
     48 import com.android.settings.enterprise.DevicePolicyManagerWrapper;
     49 import com.android.settings.testutils.FakeFeatureFactory;
     50 import com.android.settingslib.applications.AppUtils;
     51 import com.android.settingslib.applications.ApplicationsState;
     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.mockito.invocation.InvocationOnMock;
     63 import org.mockito.stubbing.Answer;
     64 import org.robolectric.RobolectricTestRunner;
     65 import org.robolectric.annotation.Config;
     66 import org.robolectric.util.ReflectionHelpers;
     67 
     68 @RunWith(RobolectricTestRunner.class)
     69 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
     70 public class AppButtonsPreferenceControllerTest {
     71     private static final String PACKAGE_NAME = "com.android.settings";
     72     private static final String RESOURCE_STRING = "string";
     73     private static final boolean ALL_USERS = false;
     74     private static final boolean DISABLE_AFTER_INSTALL = true;
     75     private static final int REQUEST_UNINSTALL = 0;
     76     private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
     77     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     78     private SettingsActivity mSettingsActivity;
     79     @Mock
     80     private TestFragment mFragment;
     81     @Mock
     82     private Lifecycle mLifecycle;
     83     @Mock
     84     private ApplicationsState mState;
     85     @Mock
     86     private ApplicationsState.AppEntry mAppEntry;
     87     @Mock
     88     private ApplicationInfo mAppInfo;
     89     @Mock
     90     private PackageManager mPackageManger;
     91     @Mock
     92     private DevicePolicyManagerWrapper mDpm;
     93     @Mock
     94     private ActivityManager mAm;
     95     @Mock
     96     private UserManager mUserManager;
     97     @Mock
     98     private Application mApplication;
     99     @Mock
    100     private PackageInfo mPackageInfo;
    101     @Mock
    102     private Button mUninstallButton;
    103     @Mock
    104     private Button mForceStopButton;
    105 
    106     private Intent mUninstallIntent;
    107     private AppButtonsPreferenceController mController;
    108 
    109     @Before
    110     public void setUp() throws Exception {
    111         MockitoAnnotations.initMocks(this);
    112 
    113         FakeFeatureFactory.setupForTest(mSettingsActivity);
    114         doReturn(mUserManager).when(mSettingsActivity).getSystemService(Context.USER_SERVICE);
    115         doReturn(mPackageManger).when(mSettingsActivity).getPackageManager();
    116         doReturn(mAm).when(mSettingsActivity).getSystemService(Context.ACTIVITY_SERVICE);
    117         doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt());
    118         doReturn(mApplication).when(mSettingsActivity).getApplication();
    119         when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(RESOURCE_STRING);
    120 
    121         mController = spy(new AppButtonsPreferenceController(mSettingsActivity, mFragment,
    122                 mLifecycle, PACKAGE_NAME, mState, mDpm, mUserManager, mPackageManger,
    123                 REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN));
    124         doReturn(false).when(mController).isFallbackPackage(anyString());
    125 
    126         mAppEntry.info = mAppInfo;
    127         mAppInfo.packageName = PACKAGE_NAME;
    128         mAppInfo.flags = 0;
    129         mPackageInfo.packageName = PACKAGE_NAME;
    130         mPackageInfo.applicationInfo = mAppInfo;
    131 
    132         mController.mUninstallButton = mUninstallButton;
    133         mController.mForceStopButton = mForceStopButton;
    134         mController.mPackageInfo = mPackageInfo;
    135 
    136         final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
    137         Answer<Void> callable = new Answer<Void>() {
    138             @Override
    139             public Void answer(InvocationOnMock invocation) throws Exception {
    140                 mUninstallIntent = captor.getValue();
    141                 return null;
    142             }
    143         };
    144         doAnswer(callable).when(mFragment).startActivityForResult(captor.capture(), anyInt());
    145     }
    146 
    147     @Test
    148     public void testRetrieveAppEntry_hasAppEntry_notNull()
    149             throws PackageManager.NameNotFoundException {
    150         doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
    151 
    152         mController.retrieveAppEntry();
    153 
    154         assertThat(mController.mAppEntry).isNotNull();
    155         assertThat(mController.mPackageInfo).isNotNull();
    156     }
    157 
    158 
    159     @Test
    160     public void testRetrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException {
    161         doReturn(null).when(mState).getEntry(eq(PACKAGE_NAME), anyInt());
    162         doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
    163 
    164         mController.retrieveAppEntry();
    165 
    166         assertThat(mController.mAppEntry).isNull();
    167         assertThat(mController.mPackageInfo).isNull();
    168     }
    169 
    170     @Test
    171     public void testRetrieveAppEntry_throwException_null() throws
    172             PackageManager.NameNotFoundException {
    173         doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt());
    174         doThrow(new PackageManager.NameNotFoundException()).when(mPackageManger).getPackageInfo(
    175                 anyString(), anyInt());
    176 
    177         mController.retrieveAppEntry();
    178 
    179         assertThat(mController.mAppEntry).isNotNull();
    180         assertThat(mController.mPackageInfo).isNull();
    181     }
    182 
    183     @Test
    184     public void testUpdateUninstallButton_isSystemApp_handleAsDisableableButton() {
    185         doReturn(false).when(mController).handleDisableable(any());
    186         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
    187 
    188         mController.updateUninstallButton();
    189 
    190         verify(mController).handleDisableable(any());
    191         verify(mUninstallButton).setEnabled(false);
    192     }
    193 
    194     @Test
    195     public void testIsAvailable_nonInstantApp() throws Exception {
    196         mController.mAppEntry = mAppEntry;
    197         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
    198                 new InstantAppDataProvider() {
    199                     @Override
    200                     public boolean isInstantApp(ApplicationInfo info) {
    201                         return false;
    202                     }
    203                 });
    204         assertThat(mController.isAvailable()).isTrue();
    205     }
    206 
    207     @Test
    208     public void testIsAvailable_instantApp() throws Exception {
    209         mController.mAppEntry = mAppEntry;
    210         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
    211                 new InstantAppDataProvider() {
    212                     @Override
    213                     public boolean isInstantApp(ApplicationInfo info) {
    214                         return true;
    215                     }
    216                 });
    217         assertThat(mController.isAvailable()).isFalse();
    218     }
    219 
    220     @Test
    221     public void testUpdateUninstallButton_isDeviceAdminApp_setButtonDisable() {
    222         doReturn(true).when(mController).handleDisableable(any());
    223         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
    224         doReturn(true).when(mDpm).packageHasActiveAdmins(anyString());
    225 
    226         mController.updateUninstallButton();
    227 
    228         verify(mController).handleDisableable(any());
    229         verify(mUninstallButton).setEnabled(false);
    230     }
    231 
    232     @Test
    233     public void testUpdateUninstallButton_isProfileOrDeviceOwner_setButtonDisable() {
    234         doReturn(true).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString());
    235 
    236         mController.updateUninstallButton();
    237 
    238         verify(mUninstallButton).setEnabled(false);
    239     }
    240 
    241     @Test
    242     public void testUpdateUninstallButton_isDeviceProvisioningApp_setButtonDisable() {
    243         doReturn(true).when(mDpm).isDeviceOwnerAppOnAnyUser(anyString());
    244         when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(PACKAGE_NAME);
    245 
    246         mController.updateUninstallButton();
    247 
    248         verify(mUninstallButton).setEnabled(false);
    249     }
    250 
    251     @Test
    252     public void testUpdateUninstallButton_isUninstallInQueue_setButtonDisable() {
    253         doReturn(true).when(mDpm).isUninstallInQueue(any());
    254 
    255         mController.updateUninstallButton();
    256 
    257         verify(mUninstallButton).setEnabled(false);
    258     }
    259 
    260     @Test
    261     public void testUpdateUninstallButton_isHomeAppAndBundled_setButtonDisable() {
    262         mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
    263         mController.mHomePackages.add(PACKAGE_NAME);
    264 
    265         mController.updateUninstallButton();
    266 
    267         verify(mUninstallButton).setEnabled(false);
    268     }
    269 
    270     @Test
    271     public void testUpdateForceStopButton_HasActiveAdmins_setButtonDisable() {
    272         doReturn(true).when(mDpm).packageHasActiveAdmins(anyString());
    273 
    274         mController.updateForceStopButton();
    275 
    276         verify(mController).updateForceStopButtonInner(false);
    277     }
    278 
    279     @Test
    280     public void testUpdateForceStopButton_AppNotStopped_setButtonEnable() {
    281         mController.updateForceStopButton();
    282 
    283         verify(mController).updateForceStopButtonInner(true);
    284     }
    285 
    286     @Test
    287     public void testUninstallPkg_intentSent() {
    288         mController.uninstallPkg(PACKAGE_NAME, ALL_USERS, DISABLE_AFTER_INSTALL);
    289 
    290         verify(mFragment).startActivityForResult(any(), eq(REQUEST_UNINSTALL));
    291         assertThat(
    292                 mUninstallIntent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true))
    293                 .isEqualTo(ALL_USERS);
    294         assertThat(mUninstallIntent.getAction()).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE);
    295         assertThat(mController.mDisableAfterUninstall).isEqualTo(DISABLE_AFTER_INSTALL);
    296     }
    297 
    298     @Test
    299     public void testForceStopPackage_methodInvokedAndUpdated() {
    300         final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
    301         doReturn(appEntry).when(mState).getEntry(anyString(), anyInt());
    302         doNothing().when(mController).updateForceStopButton();
    303 
    304         mController.forceStopPackage(PACKAGE_NAME);
    305 
    306         verify(mAm).forceStopPackage(PACKAGE_NAME);
    307         assertThat(mController.mAppEntry).isSameAs(appEntry);
    308         verify(mController).updateForceStopButton();
    309     }
    310 
    311     @Test
    312     public void testHandleDisableable_isHomeApp_notControllable() {
    313         mController.mHomePackages.add(PACKAGE_NAME);
    314 
    315         final boolean controllable = mController.handleDisableable(mUninstallButton);
    316 
    317         verify(mUninstallButton).setText(R.string.disable_text);
    318         assertThat(controllable).isFalse();
    319 
    320     }
    321 
    322     @Test
    323     public void testHandleDisableable_isAppEnabled_controllable() {
    324         mAppEntry.info.enabled = true;
    325         mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
    326         doReturn(false).when(mController).isSystemPackage(any(), any(), any());
    327 
    328         final boolean controllable = mController.handleDisableable(mUninstallButton);
    329 
    330         verify(mUninstallButton).setText(R.string.disable_text);
    331         assertThat(controllable).isTrue();
    332 
    333     }
    334 
    335     @Test
    336     public void testHandleDisableable_isAppDisabled_controllable() {
    337         mAppEntry.info.enabled = false;
    338         mAppEntry.info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
    339         doReturn(false).when(mController).isSystemPackage(any(), any(), any());
    340 
    341         final boolean controllable = mController.handleDisableable(mUninstallButton);
    342 
    343         verify(mUninstallButton).setText(R.string.enable_text);
    344         assertThat(controllable).isTrue();
    345     }
    346 
    347     @Test
    348     public void testRefreshUi_packageNull_shouldNotCrash() {
    349         mController.mPackageName = null;
    350 
    351         // Should not crash in this method
    352         assertThat(mController.refreshUi()).isFalse();
    353     }
    354 
    355     /**
    356      * The test fragment which implements
    357      * {@link ButtonActionDialogFragment.AppButtonsDialogListener}
    358      */
    359     private static class TestFragment extends Fragment implements
    360             ButtonActionDialogFragment.AppButtonsDialogListener {
    361 
    362         @Override
    363         public void handleDialogClick(int type) {
    364             // Do nothing
    365         }
    366     }
    367 }
    368