From b70b11e02b38fce6d1bd0bc2c15f4596d4d82183 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 25 May 2018 14:59:40 -0700 Subject: [PATCH] Prevent disabling default phone/sms apps in battery setting - In handleDisableable(), call getKeepEnabledPackages() in the same way as AppActionButtonPreferenceController. - Update getKeepEnabledPackages() to dynamically query default phone/sms app packages. Change-Id: I8dc7d6248cf440dcc053f6acba9d5548d5670c41 Bug: 80328396 Bug: 80312809 Test: robotests --- .../ApplicationFeatureProviderImpl.java | 18 +++++++- .../AppButtonsPreferenceController.java | 27 ++++++----- .../ApplicationFeatureProviderImplTest.java | 21 ++++++++- .../shadow/ShadowDefaultDialerManager.java | 44 ++++++++++++++++++ .../shadow/ShadowSmsApplication.java | 46 +++++++++++++++++++ 5 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java index 545b510e8c0..d29fc950b1d 100644 --- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java +++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java @@ -17,6 +17,7 @@ package com.android.settings.applications; import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ComponentInfo; @@ -26,8 +27,12 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.RemoteException; import android.os.UserManager; +import android.telecom.DefaultDialerManager; +import android.text.TextUtils; import android.util.ArraySet; +import com.android.internal.telephony.SmsApplication; + import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -122,7 +127,18 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide @Override public Set getKeepEnabledPackages() { - return new ArraySet<>(); + // Find current default phone/sms app. We should keep them enabled. + final Set keepEnabledPackages = new ArraySet<>(); + final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext); + if (!TextUtils.isEmpty(defaultDialer)) { + keepEnabledPackages.add(defaultDialer); + } + final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication( + mContext, true /* updateIfNeeded */); + if (defaultSms != null) { + keepEnabledPackages.add(defaultSms.getPackageName()); + } + return keepEnabledPackages; } private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter diff --git a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java index add6023994f..a2ba9a96181 100644 --- a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java +++ b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java @@ -48,6 +48,7 @@ import com.android.settings.DeviceAdminAdd; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; +import com.android.settings.applications.ApplicationFeatureProvider; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.ActionButtonPreference; @@ -73,7 +74,7 @@ import java.util.List; * An easy way to handle them is to delegate them to {@link #handleDialogClick(int)} and * {@link #handleActivityResult(int, int, Intent)} in this controller. */ -//TODO(b/35810915): Make AppInfoDashboardFragment use this controller +//TODO(80312809): Merge this class into {@link AppActionButtonPreferenceController} public class AppButtonsPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnDestroy, ApplicationsState.Callbacks { @@ -100,17 +101,18 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController private final int mRequestUninstall; private final int mRequestRemoveDeviceAdmin; + private final DevicePolicyManager mDpm; + private final UserManager mUserManager; + private final PackageManager mPm; + private final SettingsActivity mActivity; + private final Fragment mFragment; + private final MetricsFeatureProvider mMetricsFeatureProvider; + private final ApplicationFeatureProvider mApplicationFeatureProvider; + private final int mUserId; private ApplicationsState.Session mSession; - private DevicePolicyManager mDpm; - private UserManager mUserManager; - private PackageManager mPm; - private SettingsActivity mActivity; - private Fragment mFragment; private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin; - private MetricsFeatureProvider mMetricsFeatureProvider; - private int mUserId; private boolean mUpdatedSysApp = false; private boolean mListeningToPackageRemove = false; private boolean mFinishing = false; @@ -127,8 +129,9 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController "Fragment should implement AppButtonsDialogListener"); } - mMetricsFeatureProvider = FeatureFactory.getFactory(activity).getMetricsFeatureProvider(); - + final FeatureFactory factory = FeatureFactory.getFactory(activity); + mMetricsFeatureProvider = factory.getMetricsFeatureProvider(); + mApplicationFeatureProvider = factory.getApplicationFeatureProvider(activity); mState = state; mDpm = dpm; mUserManager = userManager; @@ -538,11 +541,11 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController // Disable button for core system applications. mButtonsPref.setButton1Text(R.string.disable_text) .setButton1Positive(false); - } else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) { mButtonsPref.setButton1Text(R.string.disable_text) .setButton1Positive(false); - disableable = true; + disableable = !mApplicationFeatureProvider.getKeepEnabledPackages() + .contains(mAppEntry.info.packageName); } else { mButtonsPref.setButton1Text(R.string.enable_text) .setButton1Positive(true); diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java index 680dc076c04..1eb7fb81cac 100644 --- a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -34,17 +35,23 @@ import android.os.UserManager; import com.android.settings.testutils.ApplicationTestUtils; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowDefaultDialerManager; +import com.android.settings.testutils.shadow.ShadowSmsApplication; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; +import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; /** * Tests for {@link ApplicationFeatureProviderImpl}. @@ -246,8 +253,18 @@ public final class ApplicationFeatureProviderImplTest { } @Test - public void getKeepEnabledPackages_shouldContainNothing() { - assertThat(mProvider.getKeepEnabledPackages()).isEmpty(); + @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class}) + public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSms() { + final String testDialer = "com.android.test.defaultdialer"; + final String testSms = "com.android.test.defaultsms"; + ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver")); + ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer); + ReflectionHelpers.setField(mProvider, "mContext", RuntimeEnvironment.application); + + final Set keepEnabledPackages = mProvider.getKeepEnabledPackages(); + + final List expectedPackages = Arrays.asList(testDialer, testSms); + assertThat(keepEnabledPackages).containsExactlyElementsIn(expectedPackages); } private void setUpUsersAndInstalledApps() { diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java new file mode 100644 index 00000000000..ec4d788b9c1 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.testutils.shadow; + +import android.content.Context; +import android.telecom.DefaultDialerManager; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +@Implements(DefaultDialerManager.class) +public class ShadowDefaultDialerManager { + + private static String sDefaultDailer; + + @Resetter + public void reset() { + sDefaultDailer = null; + } + + @Implementation + public static String getDefaultDialerApplication(Context context) { + return sDefaultDailer; + } + + public static void setDefaultDialerApplication(String dialer) { + sDefaultDailer = dialer; + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java new file mode 100644 index 00000000000..8e0c013f674 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.testutils.shadow; + +import android.content.ComponentName; +import android.content.Context; + +import com.android.internal.telephony.SmsApplication; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +@Implements(SmsApplication.class) +public class ShadowSmsApplication { + + private static ComponentName sDefaultSmsApplication; + + @Resetter + public void reset() { + sDefaultSmsApplication = null; + } + + @Implementation + public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) { + return sDefaultSmsApplication; + } + + public static void setDefaultSmsApplication(ComponentName cn) { + sDefaultSmsApplication = cn; + } +}