Merge "Give PBAP permission only after user confirms" into pi-dev
diff --git a/src/com/android/settings/applications/AppStatePowerBridge.java b/src/com/android/settings/applications/AppStatePowerBridge.java
index ce03544..31412a7 100644
--- a/src/com/android/settings/applications/AppStatePowerBridge.java
+++ b/src/com/android/settings/applications/AppStatePowerBridge.java
@@ -15,6 +15,8 @@
  */
 package com.android.settings.applications;
 
+import android.content.Context;
+
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 import com.android.settingslib.applications.ApplicationsState.AppFilter;
@@ -28,10 +30,11 @@
  */
 public class AppStatePowerBridge extends AppStateBaseBridge {
 
-    private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance();
+    private final PowerWhitelistBackend mBackend;
 
-    public AppStatePowerBridge(ApplicationsState appState, Callback callback) {
+    public AppStatePowerBridge(Context context, ApplicationsState appState, Callback callback) {
         super(appState, callback);
+        mBackend = PowerWhitelistBackend.getInstance(context);
     }
 
     @Override
@@ -50,11 +53,6 @@
         app.extraInfo = mBackend.isWhitelisted(pkg) ? Boolean.TRUE : Boolean.FALSE;
     }
 
-    public static class HighPowerState {
-        public boolean isHighPower;
-        public boolean isSystemHighPower;
-    }
-
     public static final AppFilter FILTER_POWER_WHITELISTED = new CompoundFilter(
             ApplicationsState.FILTER_WITHOUT_DISABLED_UNTIL_USED, new AppFilter() {
         @Override
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index f592865..3a88337 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,11 @@
 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 @@
 
     @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
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index a00ea8e..51b24e1 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -884,7 +884,7 @@
             } else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                 mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
             } else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
-                mExtraInfoBridge = new AppStatePowerBridge(mState, this);
+                mExtraInfoBridge = new AppStatePowerBridge(mContext, mState, this);
             } else if (mManageApplications.mListType == LIST_TYPE_OVERLAY) {
                 mExtraInfoBridge = new AppStateOverlayBridge(mContext, mState, this);
             } else if (mManageApplications.mListType == LIST_TYPE_WRITE_SETTINGS) {
@@ -1276,7 +1276,8 @@
                 return true;
             }
             ApplicationsState.AppEntry entry = mEntries.get(position);
-            return !PowerWhitelistBackend.getInstance().isSysWhitelisted(entry.info.packageName);
+            return !PowerWhitelistBackend.getInstance(mContext)
+                    .isSysWhitelisted(entry.info.packageName);
         }
 
         @Override
diff --git a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
index 8c4b4d8..5c77373 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.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 @@
  * 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 @@
 
     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 @@
                     "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 @@
             // 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/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
index 69b5e9e..092f627 100644
--- a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
@@ -56,7 +56,7 @@
 
     public BackgroundActivityPreferenceController(Context context,
             InstrumentedPreferenceFragment fragment, int uid, String packageName) {
-        this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance());
+        this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance(context));
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java
index ab3ce8d..d526f4b 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceController.java
@@ -48,7 +48,7 @@
         mFragment = fragment;
         mSettingsActivity = settingsActivity;
         mPackageName = packageName;
-        mBackend = PowerWhitelistBackend.getInstance();
+        mBackend = PowerWhitelistBackend.getInstance(mSettingsActivity);
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/fuelgauge/HighPowerDetail.java b/src/com/android/settings/fuelgauge/HighPowerDetail.java
index 4f70700..7dfa0be 100644
--- a/src/com/android/settings/fuelgauge/HighPowerDetail.java
+++ b/src/com/android/settings/fuelgauge/HighPowerDetail.java
@@ -67,12 +67,13 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mBatteryUtils = BatteryUtils.getInstance(getContext());
-        mBackend = PowerWhitelistBackend.getInstance();
+        final Context context = getContext();
+        mBatteryUtils = BatteryUtils.getInstance(context);
+        mBackend = PowerWhitelistBackend.getInstance(context);
 
         mPackageName = getArguments().getString(AppInfoBase.ARG_PACKAGE_NAME);
         mPackageUid = getArguments().getInt(AppInfoBase.ARG_PACKAGE_UID);
-        PackageManager pm = getContext().getPackageManager();
+        final PackageManager pm = context.getPackageManager();
         try {
             mLabel = pm.getApplicationInfo(mPackageName, 0).loadLabel(pm);
         } catch (NameNotFoundException e) {
@@ -171,10 +172,10 @@
     }
 
     public static CharSequence getSummary(Context context, String pkg) {
-        PowerWhitelistBackend powerWhitelist = PowerWhitelistBackend.getInstance();
+        PowerWhitelistBackend powerWhitelist = PowerWhitelistBackend.getInstance(context);
         return context.getString(powerWhitelist.isSysWhitelisted(pkg) ? R.string.high_power_system
                 : powerWhitelist.isWhitelisted(pkg) ? R.string.high_power_on
-                : R.string.high_power_off);
+                        : R.string.high_power_off);
     }
 
     public static void show(Fragment caller, int uid, String packageName, int requestCode) {
diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java
index 84ef864..55081cd 100644
--- a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java
+++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java
@@ -30,12 +30,8 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
-import android.os.Process;
 import android.os.StatsDimensionsValue;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
 import android.support.annotation.GuardedBy;
@@ -44,7 +40,6 @@
 import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.util.ArrayUtils;
 import com.android.settings.R;
 import com.android.settings.fuelgauge.BatteryUtils;
@@ -101,7 +96,8 @@
             final BatteryUtils batteryUtils = BatteryUtils.getInstance(this);
             final ContentResolver contentResolver = getContentResolver();
             final UserManager userManager = getSystemService(UserManager.class);
-            final PowerWhitelistBackend powerWhitelistBackend = PowerWhitelistBackend.getInstance();
+            final PowerWhitelistBackend powerWhitelistBackend =
+                    PowerWhitelistBackend.getInstance(context);
             final PowerUsageFeatureProvider powerUsageFeatureProvider = FeatureFactory
                     .getFactory(this).getPowerUsageFeatureProvider(this);
             final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory
diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
index a457ba2..cd41c86 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 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 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.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 @@
     }
 
     @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/fuelgauge/BatteryOptimizationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java
index b454416..dec9c6a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizationPreferenceControllerTest.java
@@ -115,6 +115,10 @@
      */
     public static class TestPowerWhitelistBackend extends PowerWhitelistBackend {
 
+        public TestPowerWhitelistBackend(Context context) {
+            super(context);
+        }
+
         @Override
         public void refreshList() {
             // Do nothing so we could mock it without error
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 0000000..ec4d788
--- /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 0000000..8e0c013
--- /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;
+    }
+}