Add method to disable "disable" button in installed app UI

OEMs can now force grey out the "disable" button for important apps on
device.

Change-Id: Ic075a07ad12592bd60238c7b1c9ab84932c8db3c
Fix: 38250742
Test: make RunSettingsRoboTests
This commit is contained in:
Fan Zhang
2017-05-31 10:42:19 -07:00
parent 63b013ea60
commit a45f3d2f33
6 changed files with 129 additions and 33 deletions

View File

@@ -17,19 +17,6 @@
package com.android.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
@@ -38,6 +25,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.BatteryStats;
import android.os.UserManager;
import android.support.v7.preference.Preference;
@@ -56,6 +44,7 @@ import com.android.settings.applications.instantapps.InstantAppButtonsController
import com.android.settings.applications.instantapps.InstantAppButtonsController.ShowDialogDelegate;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.Utils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
@@ -69,11 +58,26 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -87,8 +91,6 @@ public final class InstalledAppDetailsTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
ApplicationFeatureProvider mApplicationFeatureProvider;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private UserManager mUserManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -107,15 +109,17 @@ public final class InstalledAppDetailsTest {
private PackageManager mPackageManager;
@Mock
private BatteryUtils mBatteryUtils;
private FakeFeatureFactory mFeatureFactory;
private InstalledAppDetails mAppDetail;
private Context mShadowContext;
private Preference mBatteryPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFeatureFactory = FakeFeatureFactory.setupForTest(mContext);
mShadowContext = RuntimeEnvironment.application;
mAppDetail = spy(new InstalledAppDetails());
mAppDetail.mBatteryUtils = mBatteryUtils;
@@ -347,16 +351,14 @@ public final class InstalledAppDetailsTest {
final InstalledAppDetailsWithMockInstantButtons
fragment = new InstalledAppDetailsWithMockInstantButtons();
ReflectionHelpers.setField(fragment, "mPackageInfo", packageInfo);
ReflectionHelpers.setField(fragment, "mApplicationFeatureProvider",
mFeatureFactory.applicationFeatureProvider);
final InstantAppButtonsController buttonsController =
mock(InstantAppButtonsController.class);
when(buttonsController.setPackageName(nullable(String.class)))
.thenReturn(buttonsController);
FakeFeatureFactory.setupForTest(mContext);
FakeFeatureFactory factory =
(FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
when(factory.applicationFeatureProvider.newInstantAppButtonsController(
when(mFeatureFactory.applicationFeatureProvider.newInstantAppButtonsController(
nullable(Fragment.class), nullable(View.class), nullable(ShowDialogDelegate.class)))
.thenReturn(buttonsController);
@@ -461,4 +463,79 @@ public final class InstalledAppDetailsTest {
public void isBatteryStatsAvailable_parametersNull_returnFalse() {
assertThat(mAppDetail.isBatteryStatsAvailable()).isFalse();
}
@Test
public void handleDisableable_appIsHomeApp_buttonShouldNotWork() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = true;
final AppEntry appEntry = mock(AppEntry.class);
appEntry.info = info;
final HashSet<String> homePackages = new HashSet<>();
homePackages.add(info.packageName);
ReflectionHelpers.setField(mAppDetail, "mHomePackages", homePackages);
ReflectionHelpers.setField(mAppDetail, "mAppEntry", appEntry);
final Button button = mock(Button.class);
assertThat(mAppDetail.handleDisableable(button)).isFalse();
verify(button).setText(R.string.disable_text);
}
@Test
@Config(shadows = ShadowUtils.class)
public void handleDisableable_appIsEnabled_buttonShouldWork() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = true;
info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
final AppEntry appEntry = mock(AppEntry.class);
appEntry.info = info;
when(mFeatureFactory.applicationFeatureProvider.getKeepEnabledPackages()).thenReturn(
new HashSet<>());
ReflectionHelpers.setField(mAppDetail, "mApplicationFeatureProvider",
mFeatureFactory.applicationFeatureProvider);
ReflectionHelpers.setField(mAppDetail, "mAppEntry", appEntry);
final Button button = mock(Button.class);
assertThat(mAppDetail.handleDisableable(button)).isTrue();
verify(button).setText(R.string.disable_text);
}
@Test
@Config(shadows = ShadowUtils.class)
public void handleDisableable_appIsEnabledAndInKeepEnabledWhitelist_buttonShouldNotWork() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = true;
info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
final AppEntry appEntry = mock(AppEntry.class);
appEntry.info = info;
final HashSet<String> packages = new HashSet<>();
packages.add(info.packageName);
when(mFeatureFactory.applicationFeatureProvider.getKeepEnabledPackages()).thenReturn(
packages);
ReflectionHelpers.setField(mAppDetail, "mApplicationFeatureProvider",
mFeatureFactory.applicationFeatureProvider);
ReflectionHelpers.setField(mAppDetail, "mAppEntry", appEntry);
final Button button = mock(Button.class);
assertThat(mAppDetail.handleDisableable(button)).isFalse();
verify(button).setText(R.string.disable_text);
}
@Implements(Utils.class)
public static class ShadowUtils {
@Implementation
public static boolean isSystemPackage(Resources resources, PackageManager pm,
PackageInfo pkg) {
return false;
}
}
}