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);
+ }
}