OSDN Git Service

Prevent disabling default phone/sms apps in battery setting
authorFan Zhang <zhfan@google.com>
Fri, 25 May 2018 21:59:40 +0000 (14:59 -0700)
committerFan Zhang <zhfan@google.com>
Tue, 29 May 2018 22:25:56 +0000 (22:25 +0000)
- In handleDisableable(), call getKeepEnabledPackages() in the same way
  as AppActionButtonPreferenceController.
- Update getKeepEnabledPackages() to dynamically query default phone/sms
  app packages.

Change-Id: I8dc7d6248cf440dcc053f6acba9d5548d5670c41
Merged-In: I8dc7d6248cf440dcc053f6acba9d5548d5670c41
Fixes: 80328396
Bug: 80312809
Test: robotests

src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
tests/robotests/src/com/android/settings/testutils/shadow/ShadowDefaultDialerManager.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/testutils/shadow/ShadowSmsApplication.java [new file with mode: 0644]

index f592865..3a88337 100644 (file)
@@ -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,11 @@ 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 com.android.settingslib.wrapper.PackageManagerWrapper;
 
 import java.util.ArrayList;
@@ -124,7 +128,18 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
 
     @Override
     public Set<String> getKeepEnabledPackages() {
-        return new ArraySet<>();
+        // Find current default phone/sms app. We should keep them enabled.
+        final Set<String> 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
index 8c4b4d8..5c77373 100644 (file)
@@ -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);
index a457ba2..cd41c86 100644 (file)
@@ -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,6 +35,8 @@ 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 com.android.settingslib.wrapper.PackageManagerWrapper;
 
 import org.junit.Before;
@@ -41,11 +44,15 @@ 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}.
@@ -247,8 +254,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<String> keepEnabledPackages = mProvider.getKeepEnabledPackages();
+
+        final List<String> 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 (file)
index 0000000..ec4d788
--- /dev/null
@@ -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 (file)
index 0000000..8e0c013
--- /dev/null
@@ -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;
+    }
+}