Merge "Add device/profile app check in background check" into oc-mr1-dev
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 2a57577..417ac0f 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -107,6 +107,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.UserIcons;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 import com.android.settings.password.FingerprintManagerWrapper;
 import com.android.settings.password.IFingerprintManager;
 
@@ -1280,6 +1281,28 @@
     }
 
     /**
+     * Return {@code true} if the supplied package is device owner or profile owner of at
+     * least one user.
+     * @param userManager used to get profile owner app for each user
+     * @param devicePolicyManager used to check whether it is device owner app
+     * @param packageName package to check about
+     */
+    public static boolean isProfileOrDeviceOwner(UserManager userManager,
+            DevicePolicyManagerWrapper devicePolicyManager, String packageName) {
+        List<UserInfo> userInfos = userManager.getUsers();
+        if (devicePolicyManager.isDeviceOwnerAppOnAnyUser(packageName)) {
+            return true;
+        }
+        for (int i = 0, size = userInfos.size(); i < size; i++) {
+            ComponentName cn = devicePolicyManager.getProfileOwnerAsUser(userInfos.get(i).id);
+            if (cn != null && cn.getPackageName().equals(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Return the resource id to represent the install status for an app
      */
     @StringRes
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 4af9bc6..a5daee2 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -43,6 +43,8 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.enterprise.DevicePolicyManagerWrapper;
+import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.applications.ApplicationsState;
@@ -73,7 +75,7 @@
     protected String mPackageName;
 
     protected IUsbManager mUsbManager;
-    protected DevicePolicyManager mDpm;
+    protected DevicePolicyManagerWrapper mDpm;
     protected UserManager mUserManager;
     protected PackageManager mPm;
 
@@ -92,7 +94,8 @@
                 .getApplicationFeatureProvider(activity);
         mState = ApplicationsState.getInstance(activity.getApplication());
         mSession = mState.newSession(this);
-        mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        mDpm = new DevicePolicyManagerWrapperImpl(
+                (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
         mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
         mPm = activity.getPackageManager();
         IBinder b = ServiceManager.getService(Context.USB_SERVICE);
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index e8a4d9d..5421586 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -274,7 +274,7 @@
         // We don't allow uninstalling DO/PO on *any* users, because if it's a system app,
         // "uninstall" is actually "downgrade to the system version + disable", and "downgrade"
         // will clear data on all users.
-        if (isProfileOrDeviceOwner(mPackageInfo.packageName)) {
+        if (Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mPackageInfo.packageName)) {
             enabled = false;
         }
 
@@ -349,23 +349,6 @@
         return enabled;
     }
 
-    /** Returns if the supplied package is device owner or profile owner of at least one user */
-    private boolean isProfileOrDeviceOwner(String packageName) {
-        List<UserInfo> userInfos = mUserManager.getUsers();
-        DevicePolicyManager dpm = (DevicePolicyManager)
-                getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
-        if (dpm.isDeviceOwnerAppOnAnyUser(packageName)) {
-            return true;
-        }
-        for (UserInfo userInfo : userInfos) {
-            ComponentName cn = dpm.getProfileOwnerAsUser(userInfo.id);
-            if (cn != null && cn.getPackageName().equals(packageName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle icicle) {
diff --git a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
index 1647aa5..b889cfd 100644
--- a/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/AppButtonsPreferenceController.java
@@ -381,7 +381,7 @@
         // We don't allow uninstalling DO/PO on *any* users, because if it's a system app,
         // "uninstall" is actually "downgrade to the system version + disable", and "downgrade"
         // will clear data on all users.
-        if (isProfileOrDeviceOwner(mPackageInfo.packageName)) {
+        if (Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mPackageInfo.packageName)) {
             enabled = false;
         }
 
@@ -581,21 +581,6 @@
                 || (mUserManager.isSplitSystemUser() && userCount == 2);
     }
 
-    /** Returns if the supplied package is device owner or profile owner of at least one user */
-    private boolean isProfileOrDeviceOwner(String packageName) {
-        List<UserInfo> userInfos = mUserManager.getUsers();
-        if (mDpm.isDeviceOwnerAppOnAnyUser(packageName)) {
-            return true;
-        }
-        for (int i = 0, size = userInfos.size(); i < size; i++) {
-            ComponentName cn = mDpm.getProfileOwnerAsUser(userInfos.get(i).id);
-            if (cn != null && cn.getPackageName().equals(packageName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
index 89089e5..4d1cf77 100644
--- a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
@@ -15,17 +15,22 @@
 package com.android.settings.fuelgauge;
 
 import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.os.UserManager;
 import android.support.annotation.VisibleForTesting;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.util.Log;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.enterprise.DevicePolicyManagerWrapper;
+import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 /**
@@ -39,14 +44,20 @@
 
     private final PackageManager mPackageManager;
     private final AppOpsManager mAppOpsManager;
+    private final UserManager mUserManager;
     private final String[] mPackages;
     private final int mUid;
+    @VisibleForTesting
+    DevicePolicyManagerWrapper mDpm;
 
     private String mTargetPackage;
 
     public BackgroundActivityPreferenceController(Context context, int uid) {
         super(context);
         mPackageManager = context.getPackageManager();
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mDpm = new DevicePolicyManagerWrapperImpl(
+                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         mUid = uid;
         mPackages = mPackageManager.getPackagesForUid(mUid);
@@ -56,12 +67,15 @@
     public void updateState(Preference preference) {
         final int mode = mAppOpsManager
                 .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
-        if (mode == AppOpsManager.MODE_ERRORED) {
-            preference.setEnabled(false);
-        } else {
+        // Set checked or not before we may set it disabled
+        if (mode != AppOpsManager.MODE_ERRORED) {
             final boolean checked = mode != AppOpsManager.MODE_IGNORED;
             ((SwitchPreference) preference).setChecked(checked);
         }
+        if (mode == AppOpsManager.MODE_ERRORED
+                || Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mTargetPackage)) {
+            preference.setEnabled(false);
+        }
 
         updateSummary(preference);
     }
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index d85464d..33ead1f 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -8,14 +8,17 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.UserInfo;
 import android.net.ConnectivityManager;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
+import android.os.UserManager;
 import android.os.storage.DiskInfo;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
@@ -23,6 +26,7 @@
 import android.text.format.DateUtils;
 import android.text.style.TtsSpan;
 
+import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -34,12 +38,15 @@
 import org.robolectric.annotation.Config;
 
 import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class UtilsTest {
 
     private static final String TIME_DESCRIPTION = "1 day 20 hours 30 minutes";
+    private static final String PACKAGE_NAME = "com.android.app";
     private Context mContext;
     @Mock
     private WifiManager wifiManager;
@@ -47,6 +54,10 @@
     private Network network;
     @Mock
     private ConnectivityManager connectivityManager;
+    @Mock
+    private DevicePolicyManagerWrapper mDevicePolicyManager;
+    @Mock
+    private UserManager mUserManager;
 
     @Before
     public void setUp() {
@@ -194,4 +205,25 @@
 
         assertThat(Utils.getInstallationStatus(info)).isEqualTo(R.string.disabled);
     }
+
+    @Test
+    public void testIsProfileOrDeviceOwner_deviceOwnerApp_returnTrue() {
+        when(mDevicePolicyManager.isDeviceOwnerAppOnAnyUser(PACKAGE_NAME)).thenReturn(true);
+
+        assertThat(Utils.isProfileOrDeviceOwner(mUserManager, mDevicePolicyManager,
+                PACKAGE_NAME)).isTrue();
+    }
+
+    @Test
+    public void testIsProfileOrDeviceOwner_profileOwnerApp_returnTrue() {
+        final List<UserInfo> userInfos = new ArrayList<>();
+        userInfos.add(new UserInfo());
+
+        when(mUserManager.getUsers()).thenReturn(userInfos);
+        when(mDevicePolicyManager.getProfileOwnerAsUser(userInfos.get(0).id)).thenReturn(
+                new ComponentName(PACKAGE_NAME, ""));
+
+        assertThat(Utils.isProfileOrDeviceOwner(mUserManager, mDevicePolicyManager,
+                PACKAGE_NAME)).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index 1de7c9f..deef5e0 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -45,6 +45,7 @@
 import com.android.settings.TestConfig;
 import com.android.settings.applications.instantapps.InstantAppButtonsController;
 import com.android.settings.applications.instantapps.InstantAppButtonsController.ShowDialogDelegate;
+import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.Utils;
@@ -103,7 +104,7 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private SettingsActivity mActivity;
     @Mock
-    private DevicePolicyManager mDevicePolicyManager;
+    private DevicePolicyManagerWrapper mDevicePolicyManager;
     @Mock
     private BatterySipper mBatterySipper;
     @Mock
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
index 4f48945..91f4a2b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
@@ -17,14 +17,17 @@
 package com.android.settings.fuelgauge;
 
 import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.os.UserManager;
 import android.support.v14.preference.SwitchPreference;
 
 import com.android.settings.R;
 import com.android.settings.TestConfig;
+import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -62,6 +65,12 @@
     private ApplicationInfo mHighApplicationInfo;
     @Mock
     private ApplicationInfo mLowApplicationInfo;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
     private BackgroundActivityPreferenceController mController;
     private SwitchPreference mPreference;
     private Context mShadowContext;
@@ -73,6 +82,9 @@
         mShadowContext = RuntimeEnvironment.application;
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
+                mDevicePolicyManager);
         when(mPackageManager.getPackagesForUid(UID_NORMAL)).thenReturn(PACKAGES_NORMAL);
         when(mPackageManager.getPackagesForUid(UID_SPECIAL)).thenReturn(PACKAGES_SPECIAL);
 
@@ -86,6 +98,7 @@
         mPreference = new SwitchPreference(mShadowContext);
         mController = spy(new BackgroundActivityPreferenceController(mContext, UID_NORMAL));
         mController.isAvailable();
+        mController.mDpm = mDevicePolicyManagerWrapper;
     }
 
     @Test
@@ -181,6 +194,7 @@
     @Test
     public void testMultiplePackages_ReturnStatusForTargetPackage() {
         mController = new BackgroundActivityPreferenceController(mContext, UID_SPECIAL);
+        mController.mDpm = mDevicePolicyManagerWrapper;
         when(mAppOpsManager
                 .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, LOW_SDK_PACKAGE))
                 .thenReturn(AppOpsManager.MODE_ALLOWED);