Test more DPM APIs.

Bug 24061108

Change-Id: Ia9da19f62c0f4edf53ca1f4c213f0368ec1983ba
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b0a04c7..3f70e0c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -271,7 +271,6 @@
     final Context mContext;
     final PackageManager mPackageManager;
     final UserManager mUserManager;
-    final PowerManager.WakeLock mWakeLock;
 
     final LocalService mLocalService;
 
@@ -995,7 +994,7 @@
         boolean removed = false;
         if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
         DevicePolicyData policy = getUserData(userHandle);
-        IPackageManager pm = AppGlobals.getPackageManager();
+        IPackageManager pm = getIPackageManager();
         synchronized (this) {
             for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
                 ActiveAdmin aa = policy.mAdminList.get(i);
@@ -1071,7 +1070,7 @@
 
     /** Unit test will override it to inject a mock. */
     @VisibleForTesting
-    IWindowManager newIWindowManager() {
+    IWindowManager getIWindowManager() {
         return IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
     }
 
@@ -1083,6 +1082,12 @@
 
     /** Unit test will override it to inject a mock. */
     @VisibleForTesting
+    IPackageManager getIPackageManager() {
+        return AppGlobals.getPackageManager();
+    }
+
+    /** Unit test will override it to inject a mock. */
+    @VisibleForTesting
     LockPatternUtils newLockPatternUtils(Context context) {
         return new LockPatternUtils(context);
     }
@@ -1129,13 +1134,33 @@
     }
 
     @VisibleForTesting
-    WakeLock powerManagerNewWakeLock(int levelAndFlags, String tag) {
-        return mContext.getSystemService(PowerManager.class).newWakeLock(levelAndFlags, tag);
+    void powerManagerGoToSleep(long time, int reason, int flags) {
+        mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
     }
 
     @VisibleForTesting
-    void powerManagerGoToSleep(long time, int reason, int flags) {
-        mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
+    boolean systemPropertiesGetBoolean(String key, boolean def) {
+        return SystemProperties.getBoolean(key, def);
+    }
+
+    @VisibleForTesting
+    long systemPropertiesGetLong(String key, long def) {
+        return SystemProperties.getLong(key, def);
+    }
+
+    @VisibleForTesting
+    String systemPropertiesGet(String key, String def) {
+        return SystemProperties.get(key, def);
+    }
+
+    @VisibleForTesting
+    String systemPropertiesGet(String key) {
+        return SystemProperties.get(key);
+    }
+
+    @VisibleForTesting
+    void systemPropertiesSet(String key, String value) {
+        SystemProperties.set(key, value);
     }
 
     /**
@@ -1145,14 +1170,16 @@
         mContext = context;
         mHandler = new Handler(getMyLooper());
         mOwners = newOwners();
-        mUserManager = getUserManager();
-        mPackageManager = getPackageManager();
-        mHasFeature = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
-        mPowerManagerInternal = getPowerManagerInternal();
-        mWakeLock = powerManagerNewWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
-        mIWindowManager = newIWindowManager();
-        mNotificationManager = getNotificationManager();
+
+        mUserManager = Preconditions.checkNotNull(getUserManager());
+        mPackageManager = Preconditions.checkNotNull(getPackageManager());
+        mPowerManagerInternal = Preconditions.checkNotNull(getPowerManagerInternal());
+        mIWindowManager = Preconditions.checkNotNull(getIWindowManager());
+        mNotificationManager = Preconditions.checkNotNull(getNotificationManager());
+
         mLocalService = new LocalService();
+
+        mHasFeature = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
         if (!mHasFeature) {
             // Skip the rest of the initialization
             return;
@@ -1862,7 +1889,7 @@
         // Ensure the status of the camera is synced down to the system. Interested native services
         // should monitor this value and act accordingly.
         String cameraPropertyForUser = SYSTEM_PROP_DISABLE_CAMERA_PREFIX + policy.mUserHandle;
-        boolean systemState = SystemProperties.getBoolean(cameraPropertyForUser, false);
+        boolean systemState = systemPropertiesGetBoolean(cameraPropertyForUser, false);
         boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
         if (cameraDisabled != systemState) {
             long token = binderClearCallingIdentity();
@@ -1870,7 +1897,7 @@
                 String value = cameraDisabled ? "1" : "0";
                 if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
                         + cameraPropertyForUser + "] = " + value);
-                SystemProperties.set(cameraPropertyForUser, value);
+                systemPropertiesSet(cameraPropertyForUser, value);
             } finally {
                 binderRestoreCallingIdentity(token);
             }
@@ -3231,7 +3258,7 @@
     }
 
     private boolean isExtStorageEncrypted() {
-        String state = SystemProperties.get("vold.decrypt");
+        String state = systemPropertiesGet("vold.decrypt");
         return !"".equals(state);
     }
 
@@ -3969,7 +3996,7 @@
      * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
      */
     private int getEncryptionStatus() {
-        String status = SystemProperties.get("ro.crypto.state", "unsupported");
+        String status = systemPropertiesGet("ro.crypto.state", "unsupported");
         if ("encrypted".equalsIgnoreCase(status)) {
             final long token = binderClearCallingIdentity();
             try {
@@ -4377,7 +4404,7 @@
         }
         boolean isInitializerSystemApp;
         try {
-            isInitializerSystemApp = isSystemApp(AppGlobals.getPackageManager(),
+            isInitializerSystemApp = isSystemApp(getIPackageManager(),
                     initializer.getPackageName(), binderGetCallingUserHandle().getIdentifier());
         } catch (RemoteException | IllegalArgumentException e) {
             isInitializerSystemApp = false;
@@ -4528,7 +4555,7 @@
         final long ident = binderClearCallingIdentity();
         try {
             clearUserRestrictions(userHandle);
-            AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
+            getIPackageManager().updatePermissionFlagsForAllApps(
                     PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                     0  /* flagValues */, userHandle.getIdentifier());
         } catch (RemoteException re) {
@@ -4596,7 +4623,7 @@
             long id = binderClearCallingIdentity();
             try {
                 if (!isDeviceOwner(activeAdmin.info.getPackageName())) {
-                    IPackageManager ipm = AppGlobals.getPackageManager();
+                    IPackageManager ipm = getIPackageManager();
                     ipm.setComponentEnabledSetting(who,
                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                             PackageManager.DONT_KILL_APP, userId);
@@ -4857,7 +4884,7 @@
 
     private void enableIfNecessary(String packageName, int userId) {
         try {
-            IPackageManager ipm = AppGlobals.getPackageManager();
+            IPackageManager ipm = getIPackageManager();
             ApplicationInfo ai = ipm.getApplicationInfo(packageName,
                     PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
                     userId);
@@ -4919,7 +4946,7 @@
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            IPackageManager pm = AppGlobals.getPackageManager();
+            IPackageManager pm = getIPackageManager();
             long id = binderClearCallingIdentity();
             try {
                 pm.addPersistentPreferredActivity(filter, activity, userHandle);
@@ -4938,7 +4965,7 @@
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            IPackageManager pm = AppGlobals.getPackageManager();
+            IPackageManager pm = getIPackageManager();
             long id = binderClearCallingIdentity();
             try {
                 pm.clearPackagePersistentPreferredActivities(packageName, userHandle);
@@ -5074,7 +5101,7 @@
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            IPackageManager pm = AppGlobals.getPackageManager();
+            IPackageManager pm = getIPackageManager();
             long id = binderClearCallingIdentity();
             try {
                 UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -5105,7 +5132,7 @@
         int callingUserId = UserHandle.getCallingUserId();
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            IPackageManager pm = AppGlobals.getPackageManager();
+            IPackageManager pm = getIPackageManager();
             long id = binderClearCallingIdentity();
             try {
                 UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -5144,7 +5171,7 @@
                 userIdToCheck = user.profileGroupId;
             }
 
-            IPackageManager pm = AppGlobals.getPackageManager();
+            IPackageManager pm = getIPackageManager();
             for (String enabledPackage : enabledPackages) {
                 boolean systemService = false;
                 try {
@@ -5276,7 +5303,7 @@
                     List<AccessibilityServiceInfo> installedServices =
                             accessibilityManager.getInstalledAccessibilityServiceList();
 
-                    IPackageManager pm = AppGlobals.getPackageManager();
+                    IPackageManager pm = getIPackageManager();
                     if (installedServices != null) {
                         for (AccessibilityServiceInfo service : installedServices) {
                             ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
@@ -5425,7 +5452,7 @@
                 List<InputMethodInfo> imes = inputMethodManager.getInputMethodList();
                 long id = binderClearCallingIdentity();
                 try {
-                    IPackageManager pm = AppGlobals.getPackageManager();
+                    IPackageManager pm = getIPackageManager();
                     if (imes != null) {
                         for (InputMethodInfo ime : imes) {
                             ServiceInfo serviceInfo = ime.getServiceInfo();
@@ -5472,7 +5499,7 @@
         long id = binderClearCallingIdentity();
         try {
             String profileOwnerPkg = profileOwnerComponent.getPackageName();
-            final IPackageManager ipm = AppGlobals.getPackageManager();
+            final IPackageManager ipm = getIPackageManager();
             IActivityManager activityManager = getIActivityManager();
 
             final int userHandle = user.getIdentifier();
@@ -5624,8 +5651,8 @@
                         // Send out notifications however as some clients may want to reread the
                         // value which actually changed due to a restriction having been applied.
                         final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
-                        long version = SystemProperties.getLong(property, 0) + 1;
-                        SystemProperties.set(property, Long.toString(version));
+                        long version = systemPropertiesGetLong(property, 0) + 1;
+                        systemPropertiesSet(property, Long.toString(version));
 
                         final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
                         Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
@@ -5660,7 +5687,7 @@
 
             long id = binderClearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
+                IPackageManager pm = getIPackageManager();
                 return pm.setApplicationHiddenSettingAsUser(packageName, hidden, callingUserId);
             } catch (RemoteException re) {
                 // shouldn't happen
@@ -5681,7 +5708,7 @@
 
             long id = binderClearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
+                IPackageManager pm = getIPackageManager();
                 return pm.getApplicationHiddenSettingAsUser(packageName, callingUserId);
             } catch (RemoteException re) {
                 // shouldn't happen
@@ -5718,7 +5745,7 @@
                     primaryUser = um.getUserInfo(userId);
                 }
 
-                IPackageManager pm = AppGlobals.getPackageManager();
+                IPackageManager pm = getIPackageManager();
                 if (!isSystemApp(pm, packageName, primaryUser.id)) {
                     throw new IllegalArgumentException("Only system apps can be enabled this way.");
                 }
@@ -5755,7 +5782,7 @@
                     primaryUser = um.getUserInfo(userId);
                 }
 
-                IPackageManager pm = AppGlobals.getPackageManager();
+                IPackageManager pm = getIPackageManager();
                 List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
                         intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                         0, // no flags
@@ -5851,7 +5878,7 @@
 
             long id = binderClearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
+                IPackageManager pm = getIPackageManager();
                 pm.setBlockUninstallForUser(packageName, uninstallBlocked, userId);
             } catch (RemoteException re) {
                 // Shouldn't happen.
@@ -5876,7 +5903,7 @@
 
             long id = binderClearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
+                IPackageManager pm = getIPackageManager();
                 return pm.getBlockUninstallForUser(packageName, userId);
             } catch (RemoteException re) {
                 // Shouldn't happen.
@@ -6560,7 +6587,7 @@
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             long ident = binderClearCallingIdentity();
             try {
-                final ApplicationInfo ai = AppGlobals.getPackageManager()
+                final ApplicationInfo ai = getIPackageManager()
                         .getApplicationInfo(packageName, 0, user.getIdentifier());
                 final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
                 if (targetSdkVersion < android.os.Build.VERSION_CODES.M) {
@@ -6607,7 +6634,7 @@
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             long ident = binderClearCallingIdentity();
             try {
-                int granted = AppGlobals.getPackageManager().checkPermission(permission,
+                int granted = getIPackageManager().checkPermission(permission,
                         packageName, user.getIdentifier());
                 int permFlags = packageManager.getPermissionFlags(permission, packageName, user);
                 if ((permFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED)
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index cb2c9b7..c147bcc 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -67,8 +67,26 @@
             </intent-filter>
         </receiver>
 
-        <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmin"
-                android:permission="android.permission.BIND_DEVICE_ADMIN">
+        <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_admin_sample" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin2"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_admin_sample" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin3"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
             <meta-data android:name="android.app.device_admin"
                 android:resource="@xml/device_admin_sample" />
             <intent-filter>
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index cb439eb..7e730f6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -20,6 +20,7 @@
 import android.app.IActivityManager;
 import android.app.NotificationManager;
 import android.content.Context;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.os.Looper;
 import android.os.PowerManager.WakeLock;
@@ -45,9 +46,9 @@
         public static final String DEVICE_OWNER_FILE = "device_owner2.xml";
         public static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
 
-        final private File mLegacyFile;
-        final private File mDeviceOwnerFile;
-        final private File mProfileOwnerBase;
+        private final File mLegacyFile;
+        private final File mDeviceOwnerFile;
+        private final File mProfileOwnerBase;
 
         public OwnersTestable(Context context, File dataDir) {
             super(context);
@@ -96,47 +97,52 @@
     }
 
     @Override
-    protected Owners newOwners() {
+    Owners newOwners() {
         return new OwnersTestable(getContext(), dataDir);
     }
 
     @Override
-    protected UserManager getUserManager() {
+    UserManager getUserManager() {
         return getContext().userManager;
     }
 
     @Override
-    protected PackageManager getPackageManager() {
+    PackageManager getPackageManager() {
         return getContext().packageManager;
     }
 
     @Override
-    protected PowerManagerInternal getPowerManagerInternal() {
+    PowerManagerInternal getPowerManagerInternal() {
         return getContext().powerManagerInternal;
     }
 
     @Override
-    protected NotificationManager getNotificationManager() {
+    NotificationManager getNotificationManager() {
         return getContext().notificationManager;
     }
 
     @Override
-    protected IWindowManager newIWindowManager() {
+    IWindowManager getIWindowManager() {
         return getContext().iwindowManager;
     }
 
     @Override
-    protected IActivityManager getIActivityManager() {
+    IActivityManager getIActivityManager() {
         return getContext().iactivityManager;
     }
 
     @Override
-    protected LockPatternUtils newLockPatternUtils(Context context) {
+    IPackageManager getIPackageManager() {
+        return getContext().ipackageManager;
+    }
+
+    @Override
+    LockPatternUtils newLockPatternUtils(Context context) {
         return getContext().lockPatternUtils;
     }
 
     @Override
-    protected Looper getMyLooper() {
+    Looper getMyLooper() {
         return Looper.getMainLooper();
     }
 
@@ -181,12 +187,32 @@
     }
 
     @Override
-    WakeLock powerManagerNewWakeLock(int levelAndFlags, String tag) {
-        return getContext().powerManager.newWakeLock(levelAndFlags, tag);
+    void powerManagerGoToSleep(long time, int reason, int flags) {
+        getContext().powerManager.goToSleep(time, reason, flags);
     }
 
     @Override
-    void powerManagerGoToSleep(long time, int reason, int flags) {
-        getContext().powerManager.goToSleep(time, reason, flags);
+    boolean systemPropertiesGetBoolean(String key, boolean def) {
+        return getContext().systemProperties.getBoolean(key, def);
+    }
+
+    @Override
+    long systemPropertiesGetLong(String key, long def) {
+        return getContext().systemProperties.getLong(key, def);
+    }
+
+    @Override
+    String systemPropertiesGet(String key, String def) {
+        return getContext().systemProperties.get(key, def);
+    }
+
+    @Override
+    String systemPropertiesGet(String key) {
+        return getContext().systemProperties.get(key);
+    }
+
+    @Override
+    void systemPropertiesSet(String key, String value) {
+        getContext().systemProperties.set(key, value);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 7cce56c..0da459d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -13,33 +13,39 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.android.server.devicepolicy;
 
 import com.android.server.LocalServices;
 
+import android.Manifest.permission;
+import android.app.Activity;
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.os.UserHandle;
+import android.os.Bundle;
 
 import org.mockito.ArgumentCaptor;
 
 import java.util.List;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 /**
- * Tests for {@link DevicePolicyManager} and {@link DevicePolicyManagerService}.
+ * Tests for DevicePolicyManager( and DevicePolicyManagerService).
  *
  m FrameworksServicesTests &&
  adb install \
@@ -51,9 +57,13 @@
  */
 public class DevicePolicyManagerTest extends DpmTestBase {
 
+
     private DpmMockContext mContext;
     public DevicePolicyManager dpm;
     public DevicePolicyManagerServiceTestable dpms;
+    public ComponentName admin1;
+    public ComponentName admin2;
+    public ComponentName admin3;
 
     @Override
     protected void setUp() throws Exception {
@@ -67,6 +77,59 @@
         LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
         dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
         dpm = new DevicePolicyManagerTestable(mContext, dpms);
+
+        admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
+        admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
+        admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
+
+        setUpPackageManagerForAdmin(admin1);
+        setUpPackageManagerForAdmin(admin2);
+        setUpPackageManagerForAdmin(admin3);
+
+        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+    }
+
+    /**
+     * Set up a mock result for {@link PackageManager#queryBroadcastReceivers}.  We'll return
+     * the actual ResolveInfo for the admin component, but we need to mock PM so it'll return
+     * it for user {@link DpmMockContext#CALLER_USER_HANDLE}.
+     */
+    private void setUpPackageManagerForAdmin(ComponentName admin) {
+        final Intent resolveIntent = new Intent();
+        resolveIntent.setComponent(admin);
+        final List<ResolveInfo> realResolveInfo =
+                mRealTestContext.getPackageManager().queryBroadcastReceivers(
+                        resolveIntent,
+                        PackageManager.GET_META_DATA);
+        assertNotNull(realResolveInfo);
+        assertEquals(1, realResolveInfo.size());
+
+        // We need to rewrite the UID in the activity info.
+        realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
+
+        doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
+                MockUtils.checkIntentComponent(admin),
+                eq(PackageManager.GET_META_DATA
+                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+                eq(DpmMockContext.CALLER_USER_HANDLE)
+        );
+    }
+
+    /**
+     * Set up a mock result for {@link IPackageManager#getApplicationInfo} for user
+     * {@link DpmMockContext#CALLER_USER_HANDLE}.
+     */
+    private void setUpApplicationInfo(int enabledSetting) throws Exception {
+        final ApplicationInfo ai = mRealTestContext.getPackageManager().getApplicationInfo(
+                admin1.getPackageName(),
+                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
+
+        ai.enabledSetting = enabledSetting;
+
+        doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
+                eq(admin1.getPackageName()),
+                eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+                eq(DpmMockContext.CALLER_USER_HANDLE));
     }
 
     public void testHasNoFeature() {
@@ -84,13 +147,11 @@
      * Caller doesn't have proper permissions.
      */
     public void testSetActiveAdmin_SecurityException() {
-        final ComponentName admin = new ComponentName(mRealTestContext, DummyDeviceAdmin.class);
-
         // 1. Failure cases.
 
         // Caller doesn't have MANAGE_DEVICE_ADMINS.
         try {
-            dpm.setActiveAdmin(admin, false);
+            dpm.setActiveAdmin(admin1, false);
             fail("Didn't throw SecurityException");
         } catch (SecurityException expected) {
         }
@@ -98,62 +159,246 @@
         // Caller has MANAGE_DEVICE_ADMINS, but for different user.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
         try {
-            dpm.setActiveAdmin(admin, false, DpmMockContext.CALLER_USER_HANDLE + 1);
+            dpm.setActiveAdmin(admin1, false, DpmMockContext.CALLER_USER_HANDLE + 1);
             fail("Didn't throw SecurityException");
         } catch (SecurityException expected) {
         }
     }
 
-    public void testSetActiveAdmin() {
-        final ComponentName admin = new ComponentName(mRealTestContext, DummyDeviceAdmin.class);
-
-        // 1. Prepare mock package manager (and other mocks)
-
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#setActiveAdmin}
+     *   with replace=false and replace=true
+     * {@link DevicePolicyManager#isAdminActive}
+     * {@link DevicePolicyManager#isAdminActiveAsUser}
+     * {@link DevicePolicyManager#getActiveAdmins}
+     * {@link DevicePolicyManager#getActiveAdminsAsUser}
+     */
+    public void testSetActiveAdmin() throws Exception {
+        // 1. Make sure the caller has proper permissions.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
-        // Create ResolveInfo for the admin.
-        final Intent resolveIntent = new Intent();
-        resolveIntent.setComponent(admin);
-        final List<ResolveInfo> realResolveInfo =
-                mRealTestContext.getPackageManager().queryBroadcastReceivers(
-                        resolveIntent,
-                        PackageManager.GET_META_DATA
-                            | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
-        assertNotNull(realResolveInfo);
-        assertEquals(1, realResolveInfo.size());
-
-        // We need to rewrite the UID in the activity info.
-        realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
-
-        doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
-                any(Intent.class), // TODO check the intent too.
-                eq(PackageManager.GET_META_DATA
-                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
-                eq(DpmMockContext.CALLER_USER_HANDLE)
-        );
-
-        // 2. Everything is ready; call the method.
-        dpm.setActiveAdmin(admin, false);
+        // 2. Call the API.
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
         // 3. Verify internal calls.
 
         // Check if the boradcast is sent.
-        final ArgumentCaptor<Intent> intentCap = ArgumentCaptor.forClass(Intent.class);
-        final ArgumentCaptor<UserHandle> uhCap = ArgumentCaptor.forClass(UserHandle.class);
-
-        verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
-                intentCap.capture(),
+        verify(mContext.spiedContext).sendBroadcastAsUser(
+                MockUtils.checkIntentAction(
+                        DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+        verify(mContext.spiedContext).sendBroadcastAsUser(
+                MockUtils.checkIntentAction(
+                        DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
                 MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
 
-        // First call from saveSettingsLocked().
-        assertEquals(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED,
-                intentCap.getAllValues().get(0).getAction());
-
-        // Second call from setActiveAdmin/sendAdminCommandLocked()
-        assertEquals(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
-                intentCap.getAllValues().get(1).getAction());
+        verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
+                eq(admin1.getPackageName()),
+                eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
+                eq(PackageManager.DONT_KILL_APP),
+                eq(DpmMockContext.CALLER_USER_HANDLE),
+                anyString());
 
         // TODO Verify other calls too.
+
+        // Make sure it's active admin1.
+        assertTrue(dpm.isAdminActive(admin1));
+        assertFalse(dpm.isAdminActive(admin2));
+        assertFalse(dpm.isAdminActive(admin3));
+
+        // But not admin1 for a different user.
+
+        // For this to work, caller needs android.permission.INTERACT_ACROSS_USERS_FULL.
+        // (Because we're checking a different user's status from CALLER_USER_HANDLE.)
+        mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+        assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE + 1));
+        assertFalse(dpm.isAdminActiveAsUser(admin2, DpmMockContext.CALLER_USER_HANDLE + 1));
+
+        mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+        // Next, add one more admin.
+        // Before doing so, update the application info, now it's enabled.
+        setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+        dpm.setActiveAdmin(admin2, /* replace =*/ false);
+
+        // Now we have two admins.
+        assertTrue(dpm.isAdminActive(admin1));
+        assertTrue(dpm.isAdminActive(admin2));
+        assertFalse(dpm.isAdminActive(admin3));
+
+        // Admin2 was already enabled, so setApplicationEnabledSetting() shouldn't have called
+        // again.  (times(1) because it was previously called for admin1)
+        verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
+                eq(admin1.getPackageName()),
+                eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
+                eq(PackageManager.DONT_KILL_APP),
+                eq(DpmMockContext.CALLER_USER_HANDLE),
+                anyString());
+
+        // 4. Add the same admin1 again without replace, which should throw.
+        try {
+            dpm.setActiveAdmin(admin1, /* replace =*/ false);
+            fail("Didn't throw");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        // 5. Add the same admin1 again with replace, which should succeed.
+        dpm.setActiveAdmin(admin1, /* replace =*/ true);
+
+        // TODO make sure it's replaced.
+
+        // 6. Test getActiveAdmins()
+        List<ComponentName> admins = dpm.getActiveAdmins();
+        assertEquals(2, admins.size());
+        assertEquals(admin1, admins.get(0));
+        assertEquals(admin2, admins.get(1));
+
+        // Another user has no admins.
+        mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+        assertEquals(0, DpmTestUtils.getListSizeAllowingNull(
+                dpm.getActiveAdminsAsUser(DpmMockContext.CALLER_USER_HANDLE + 1)));
+
+        mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
+    }
+
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#setActiveAdmin}
+     *   with replace=false
+     */
+    public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
+        // 1. Make sure the caller has proper permissions.
+        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
+        assertTrue(dpm.isAdminActive(admin1));
+
+        // Add the same admin1 again without replace, which should throw.
+        try {
+            dpm.setActiveAdmin(admin1, /* replace =*/ false);
+            fail("Didn't throw");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#removeActiveAdmin}
+     */
+    public void testRemoveActiveAdmin_SecurityException() {
+        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+        // Add admin.
+
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+        assertTrue(dpm.isAdminActive(admin1));
+
+        assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        // Directly call the DPMS method with a different userid, which should fail.
+        try {
+            dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE + 1);
+            fail("Didn't throw SecurityException");
+        } catch (SecurityException expected) {
+        }
+
+        // Try to remove active admin with a different caller userid should fail too, without
+        // having MANAGE_DEVICE_ADMINS.
+        mContext.callerPermissions.clear();
+
+        mContext.binder.callingUid = 1234567;
+        try {
+            dpm.removeActiveAdmin(admin1);
+            fail("Didn't throw SecurityException");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#removeActiveAdmin}
+     */
+    public void testRemoveActiveAdmin_fromDifferentUserWithMINTERACT_ACROSS_USERS_FULL() {
+        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+        // Add admin1.
+
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+        assertTrue(dpm.isAdminActive(admin1));
+        assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        // Different user, but should work, because caller has proper permissions.
+        mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
+        mContext.binder.callingUid = 1234567;
+        dpm.removeActiveAdmin(admin1);
+
+        assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        // TODO DO Still can't be removed in this case.
+    }
+
+    /**
+     * Test for:
+     * {@link DevicePolicyManager#removeActiveAdmin}
+     */
+    public void testRemoveActiveAdmin_sameUserNoMANAGE_DEVICE_ADMINS() {
+        // Need MANAGE_DEVICE_ADMINS for setActiveAdmin.  We'll remove it later.
+        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+        // Add admin1.
+
+        dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+        assertTrue(dpm.isAdminActive(admin1));
+        assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        // Broadcast from saveSettingsLocked().
+        verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
+                MockUtils.checkIntentAction(
+                        DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+        // Remove.  No permissions, but same user, so it'll work.
+        mContext.callerPermissions.clear();
+        dpm.removeActiveAdmin(admin1);
+
+        final ArgumentCaptor<BroadcastReceiver> brCap =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+        // Is removing now, but not removed yet.
+        assertTrue(dpm.isAdminActive(admin1));
+        assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        verify(mContext.spiedContext).sendOrderedBroadcastAsUser(
+                MockUtils.checkIntentAction(
+                        DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED),
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+                isNull(String.class),
+                brCap.capture(),
+                eq(dpms.mHandler),
+                eq(Activity.RESULT_OK),
+                isNull(String.class),
+                isNull(Bundle.class));
+
+        brCap.getValue().onReceive(mContext, null);
+
+        assertFalse(dpm.isAdminActive(admin1));
+        assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        // Again broadcast from saveSettingsLocked().
+        verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
+                MockUtils.checkIntentAction(
+                        DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+        // TODO Check other internal calls.
     }
 }
 
+
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 8644311..6bb9833 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -16,6 +16,7 @@
 
 package com.android.server.devicepolicy;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.LockPatternUtils;
 
 import android.app.IActivityManager;
@@ -24,11 +25,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.PowerManager.WakeLock;
 import android.os.PowerManagerInternal;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.test.mock.MockContext;
@@ -71,27 +74,27 @@
     public static final int SYSTEM_PID = 11111;
 
     public static class MockBinder {
-        int mCallingUid = CALLER_UID;
-        int mCallingPid = CALLER_PID;
+        public int callingUid = CALLER_UID;
+        public int callingPid = CALLER_PID;
 
         public long clearCallingIdentity() {
-            final long token = (((long) mCallingUid) << 32) | (mCallingPid);
-            mCallingUid = SYSTEM_UID;
-            mCallingPid = SYSTEM_PID;
+            final long token = (((long) callingUid) << 32) | (callingPid);
+            callingUid = SYSTEM_UID;
+            callingPid = SYSTEM_PID;
             return token;
         }
 
         public void restoreCallingIdentity(long token) {
-            mCallingUid = (int) (token >> 32);
-            mCallingPid = (int) token;
+            callingUid = (int) (token >> 32);
+            callingPid = (int) token;
         }
 
         public int getCallingUid() {
-            return mCallingUid;
+            return callingUid;
         }
 
         public int getCallingPid() {
-            return mCallingPid;
+            return callingPid;
         }
 
         public UserHandle getCallingUserHandle() {
@@ -99,7 +102,7 @@
         }
 
         public boolean isCallerUidMyUid() {
-            return mCallingUid == SYSTEM_UID;
+            return callingUid == SYSTEM_UID;
         }
     }
 
@@ -118,6 +121,27 @@
         }
     }
 
+    public static class SystemPropertiesForMock {
+        public boolean getBoolean(String key, boolean def) {
+            return false;
+        }
+
+        public long getLong(String key, long def) {
+            return 0;
+        }
+
+        public String get(String key, String def) {
+            return null;
+        }
+
+        public String get(String key) {
+            return null;
+        }
+
+        public void set(String key, String value) {
+        }
+    }
+
     public final Context realTestContext;
 
     /**
@@ -129,12 +153,14 @@
 
     public final MockBinder binder;
     public final EnvironmentForMock environment;
+    public final SystemPropertiesForMock systemProperties;
     public final UserManager userManager;
     public final PowerManagerForMock powerManager;
     public final PowerManagerInternal powerManagerInternal;
     public final NotificationManager notificationManager;
     public final IWindowManager iwindowManager;
     public final IActivityManager iactivityManager;
+    public final IPackageManager ipackageManager;
     public final LockPatternUtils lockPatternUtils;
 
     /** Note this is a partial mock, not a real mock. */
@@ -146,12 +172,14 @@
         realTestContext = context;
         binder = new MockBinder();
         environment = mock(EnvironmentForMock.class);
+        systemProperties= mock(SystemPropertiesForMock.class);
         userManager = mock(UserManager.class);
         powerManager = mock(PowerManagerForMock.class);
         powerManagerInternal = mock(PowerManagerInternal.class);
         notificationManager = mock(NotificationManager.class);
         iwindowManager = mock(IWindowManager.class);
         iactivityManager = mock(IActivityManager.class);
+        ipackageManager = mock(IPackageManager.class);
         lockPatternUtils = mock(LockPatternUtils.class);
 
         // Package manager is huge, so we use a partial mock instead.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
index a8e2c3c..44a851a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
@@ -23,6 +23,7 @@
 import org.junit.Assert;
 
 import java.io.File;
+import java.util.List;
 
 public class DpmTestUtils {
     private DpmTestUtils() {
@@ -33,6 +34,11 @@
             Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
         }
         dir.mkdirs();
+        Log.i(DpmTestBase.TAG, "Created " + dir);
+    }
+
+    public static int getListSizeAllowingNull(List<?> list) {
+        return list == null ? 0 : list.size();
     }
 
     public static Printer LOG_PRINTER = new Printer() {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
similarity index 75%
rename from services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
rename to services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
index c47d194..5cd1555 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
@@ -17,5 +17,11 @@
 
 import android.app.admin.DeviceAdminReceiver;
 
-public class DummyDeviceAdmin extends DeviceAdminReceiver {
-}
+public class DummyDeviceAdmins {
+    public static class Admin1 extends DeviceAdminReceiver {
+    }
+    public static class Admin2 extends DeviceAdminReceiver {
+    }
+    public static class Admin3 extends DeviceAdminReceiver {
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index f2a2bf7..5008fbf 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -17,6 +17,8 @@
 
 import com.google.common.base.Objects;
 
+import android.content.ComponentName;
+import android.content.Intent;
 import android.os.UserHandle;
 
 import org.hamcrest.BaseMatcher;
@@ -44,4 +46,35 @@
         return Mockito.argThat(m);
     }
 
+    public static Intent checkIntentComponent(final ComponentName component) {
+        final Matcher<Intent> m = new BaseMatcher<Intent>() {
+            @Override
+            public boolean matches(Object item) {
+                if (item == null) return false;
+                return Objects.equal(((Intent) item).getComponent(), component);
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Intent: component=\"" + component + "\"");
+            }
+        };
+        return Mockito.argThat(m);
+    }
+
+    public static Intent checkIntentAction(final String action) {
+        final Matcher<Intent> m = new BaseMatcher<Intent>() {
+            @Override
+            public boolean matches(Object item) {
+                if (item == null) return false;
+                return Objects.equal(((Intent) item).getAction(), action);
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Intent: action=\"" + action + "\"");
+            }
+        };
+        return Mockito.argThat(m);
+    }
 }