Make DPM/DPMS unit-testable
- Now all services that DPMS uses are injectable. - Introduce some wrappers to make static methods and final class mockable. (e.g. for Binder.getCallingUid()) - In unit tests we replace those with Mockito mocks, except we use a partial mock for PackageManager, because we use way too many methods of this and most of them are okay to use directly. - To install a partial mock to PackageManager, I needed to make ApplicationPackageManager @hide public non-final. - For a starter, added tests for DPM.setAmin(). Bug 24061108 Change-Id: I2afd51d8bc0038992d5f9be38c686260be775b75
This commit is contained in:
@@ -93,8 +93,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/*package*/
|
||||
final class ApplicationPackageManager extends PackageManager {
|
||||
/** @hide */
|
||||
public class ApplicationPackageManager extends PackageManager {
|
||||
private static final String TAG = "ApplicationPackageManager";
|
||||
private final static boolean DEBUG_ICONS = false;
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ final class SystemServiceRegistry {
|
||||
new CachedServiceFetcher<DevicePolicyManager>() {
|
||||
@Override
|
||||
public DevicePolicyManager createService(ContextImpl ctx) {
|
||||
return DevicePolicyManager.create(ctx, ctx.mMainThread.getHandler());
|
||||
return DevicePolicyManager.create(ctx);
|
||||
}});
|
||||
|
||||
registerService(Context.DOWNLOAD_SERVICE, DownloadManager.class,
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.ProxyInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallback;
|
||||
@@ -45,6 +44,7 @@ import android.security.Credentials;
|
||||
import android.service.restrictions.RestrictionsReceiver;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.org.conscrypt.TrustedCertificateStore;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -87,18 +87,30 @@ public class DevicePolicyManager {
|
||||
private final Context mContext;
|
||||
private final IDevicePolicyManager mService;
|
||||
|
||||
private DevicePolicyManager(Context context, Handler handler) {
|
||||
mContext = context;
|
||||
mService = IDevicePolicyManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
|
||||
private DevicePolicyManager(Context context) {
|
||||
this(context, IDevicePolicyManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static DevicePolicyManager create(Context context, Handler handler) {
|
||||
DevicePolicyManager me = new DevicePolicyManager(context, handler);
|
||||
@VisibleForTesting
|
||||
protected DevicePolicyManager(Context context, IDevicePolicyManager service) {
|
||||
mContext = context;
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static DevicePolicyManager create(Context context) {
|
||||
DevicePolicyManager me = new DevicePolicyManager(context);
|
||||
return me.mService != null ? me : null;
|
||||
}
|
||||
|
||||
/** @hide test will override it. */
|
||||
@VisibleForTesting
|
||||
protected int myUserId() {
|
||||
return UserHandle.myUserId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Activity action: Starts the provisioning flow which sets up a managed profile.
|
||||
*
|
||||
@@ -823,7 +835,7 @@ public class DevicePolicyManager {
|
||||
* active (enabled) in the system.
|
||||
*/
|
||||
public boolean isAdminActive(@NonNull ComponentName admin) {
|
||||
return isAdminActiveAsUser(admin, UserHandle.myUserId());
|
||||
return isAdminActiveAsUser(admin, myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -863,7 +875,7 @@ public class DevicePolicyManager {
|
||||
* returned.
|
||||
*/
|
||||
public List<ComponentName> getActiveAdmins() {
|
||||
return getActiveAdminsAsUser(UserHandle.myUserId());
|
||||
return getActiveAdminsAsUser(myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -889,7 +901,7 @@ public class DevicePolicyManager {
|
||||
public boolean packageHasActiveAdmins(String packageName) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.packageHasActiveAdmins(packageName, UserHandle.myUserId());
|
||||
return mService.packageHasActiveAdmins(packageName, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -906,7 +918,7 @@ public class DevicePolicyManager {
|
||||
public void removeActiveAdmin(@NonNull ComponentName admin) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.removeActiveAdmin(admin, UserHandle.myUserId());
|
||||
mService.removeActiveAdmin(admin, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -925,7 +937,7 @@ public class DevicePolicyManager {
|
||||
public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId());
|
||||
return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -1040,7 +1052,7 @@ public class DevicePolicyManager {
|
||||
* all admins.
|
||||
*/
|
||||
public int getPasswordQuality(@Nullable ComponentName admin) {
|
||||
return getPasswordQuality(admin, UserHandle.myUserId());
|
||||
return getPasswordQuality(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1093,7 +1105,7 @@ public class DevicePolicyManager {
|
||||
* all admins.
|
||||
*/
|
||||
public int getPasswordMinimumLength(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumLength(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumLength(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1154,7 +1166,7 @@ public class DevicePolicyManager {
|
||||
* password.
|
||||
*/
|
||||
public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumUpperCase(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumUpperCase(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1215,7 +1227,7 @@ public class DevicePolicyManager {
|
||||
* password.
|
||||
*/
|
||||
public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumLowerCase(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumLowerCase(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1273,7 +1285,7 @@ public class DevicePolicyManager {
|
||||
* @return The minimum number of letters required in the password.
|
||||
*/
|
||||
public int getPasswordMinimumLetters(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumLetters(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumLetters(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1332,7 +1344,7 @@ public class DevicePolicyManager {
|
||||
* @return The minimum number of numerical digits required in the password.
|
||||
*/
|
||||
public int getPasswordMinimumNumeric(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumNumeric(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumNumeric(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1390,7 +1402,7 @@ public class DevicePolicyManager {
|
||||
* @return The minimum number of symbols required in the password.
|
||||
*/
|
||||
public int getPasswordMinimumSymbols(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumSymbols(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumSymbols(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1449,7 +1461,7 @@ public class DevicePolicyManager {
|
||||
* @return The minimum number of letters required in the password.
|
||||
*/
|
||||
public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) {
|
||||
return getPasswordMinimumNonLetter(admin, UserHandle.myUserId());
|
||||
return getPasswordMinimumNonLetter(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1540,7 +1552,7 @@ public class DevicePolicyManager {
|
||||
public long getPasswordExpirationTimeout(@Nullable ComponentName admin) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId());
|
||||
return mService.getPasswordExpirationTimeout(admin, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -1561,7 +1573,7 @@ public class DevicePolicyManager {
|
||||
public long getPasswordExpiration(@Nullable ComponentName admin) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getPasswordExpiration(admin, UserHandle.myUserId());
|
||||
return mService.getPasswordExpiration(admin, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -1577,7 +1589,7 @@ public class DevicePolicyManager {
|
||||
* @return The length of the password history
|
||||
*/
|
||||
public int getPasswordHistoryLength(@Nullable ComponentName admin) {
|
||||
return getPasswordHistoryLength(admin, UserHandle.myUserId());
|
||||
return getPasswordHistoryLength(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1617,7 +1629,7 @@ public class DevicePolicyManager {
|
||||
public boolean isActivePasswordSufficient() {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.isActivePasswordSufficient(UserHandle.myUserId());
|
||||
return mService.isActivePasswordSufficient(myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -1636,7 +1648,7 @@ public class DevicePolicyManager {
|
||||
public int getCurrentFailedPasswordAttempts() {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getCurrentFailedPasswordAttempts(UserHandle.myUserId());
|
||||
return mService.getCurrentFailedPasswordAttempts(myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -1698,7 +1710,7 @@ public class DevicePolicyManager {
|
||||
* all admins.
|
||||
*/
|
||||
public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin) {
|
||||
return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId());
|
||||
return getMaximumFailedPasswordsForWipe(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1818,7 +1830,7 @@ public class DevicePolicyManager {
|
||||
* all admins if admin is null. Returns 0 if there are no restrictions.
|
||||
*/
|
||||
public long getMaximumTimeToLock(@Nullable ComponentName admin) {
|
||||
return getMaximumTimeToLock(admin, UserHandle.myUserId());
|
||||
return getMaximumTimeToLock(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -1881,7 +1893,7 @@ public class DevicePolicyManager {
|
||||
public void wipeData(int flags) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.wipeData(flags, UserHandle.myUserId());
|
||||
mService.wipeData(flags, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -1995,7 +2007,7 @@ public class DevicePolicyManager {
|
||||
public ComponentName getGlobalProxyAdmin() {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getGlobalProxyAdmin(UserHandle.myUserId());
|
||||
return mService.getGlobalProxyAdmin(myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -2145,7 +2157,7 @@ public class DevicePolicyManager {
|
||||
public boolean getStorageEncryption(@Nullable ComponentName admin) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getStorageEncryption(admin, UserHandle.myUserId());
|
||||
return mService.getStorageEncryption(admin, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -2173,7 +2185,7 @@ public class DevicePolicyManager {
|
||||
* or {@link #ENCRYPTION_STATUS_ACTIVE}.
|
||||
*/
|
||||
public int getStorageEncryptionStatus() {
|
||||
return getStorageEncryptionStatus(UserHandle.myUserId());
|
||||
return getStorageEncryptionStatus(myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -2410,7 +2422,7 @@ public class DevicePolicyManager {
|
||||
* have disabled the camera
|
||||
*/
|
||||
public boolean getCameraDisabled(@Nullable ComponentName admin) {
|
||||
return getCameraDisabled(admin, UserHandle.myUserId());
|
||||
return getCameraDisabled(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -2457,7 +2469,7 @@ public class DevicePolicyManager {
|
||||
* have disabled screen capture.
|
||||
*/
|
||||
public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
|
||||
return getScreenCaptureDisabled(admin, UserHandle.myUserId());
|
||||
return getScreenCaptureDisabled(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -2557,7 +2569,7 @@ public class DevicePolicyManager {
|
||||
* for a list.
|
||||
*/
|
||||
public int getKeyguardDisabledFeatures(@Nullable ComponentName admin) {
|
||||
return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
|
||||
return getKeyguardDisabledFeatures(admin, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -2590,7 +2602,7 @@ public class DevicePolicyManager {
|
||||
* @hide
|
||||
*/
|
||||
public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) {
|
||||
setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
|
||||
setActiveAdmin(policyReceiver, refreshing, myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2627,7 +2639,7 @@ public class DevicePolicyManager {
|
||||
public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.getRemoveWarning(admin, result, UserHandle.myUserId());
|
||||
mService.getRemoveWarning(admin, result, myUserId());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
@@ -2956,7 +2968,7 @@ public class DevicePolicyManager {
|
||||
throws IllegalArgumentException {
|
||||
if (mService != null) {
|
||||
try {
|
||||
final int myUserId = UserHandle.myUserId();
|
||||
final int myUserId = myUserId();
|
||||
mService.setActiveAdmin(admin, false, myUserId);
|
||||
return mService.setProfileOwner(admin, ownerName, myUserId);
|
||||
} catch (RemoteException re) {
|
||||
@@ -3301,7 +3313,7 @@ public class DevicePolicyManager {
|
||||
*/
|
||||
public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
|
||||
@NonNull ComponentName agent) {
|
||||
return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
|
||||
return getTrustAgentConfiguration(admin, agent, myUserId());
|
||||
}
|
||||
|
||||
/** @hide per-user version */
|
||||
@@ -3927,7 +3939,7 @@ public class DevicePolicyManager {
|
||||
* @see #setAccountManagementDisabled
|
||||
*/
|
||||
public String[] getAccountTypesWithManagementDisabled() {
|
||||
return getAccountTypesWithManagementDisabledAsUser(UserHandle.myUserId());
|
||||
return getAccountTypesWithManagementDisabledAsUser(myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
|
||||
/**
|
||||
@@ -57,4 +59,14 @@ public final class LocalServices {
|
||||
sLocalServiceObjects.put(type, service);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a service instance, must be only used in tests.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static <T> void removeServiceForTest(Class<T> type) {
|
||||
synchronized (sLocalServiceObjects) {
|
||||
sLocalServiceObjects.remove(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,15 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmin"
|
||||
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>
|
||||
|
||||
</application>
|
||||
|
||||
<instrumentation
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
import android.app.IActivityManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.os.PowerManagerInternal;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.view.IWindowManager;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Overrides {@link #DevicePolicyManagerService} for dependency injection.
|
||||
*/
|
||||
public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerService {
|
||||
/**
|
||||
* Overrides {@link #Owners} for dependency injection.
|
||||
*/
|
||||
public static class OwnersTestable extends Owners {
|
||||
public static final String LEGACY_FILE = "legacy.xml";
|
||||
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;
|
||||
|
||||
public OwnersTestable(Context context, File dataDir) {
|
||||
super(context);
|
||||
mLegacyFile = new File(dataDir, LEGACY_FILE);
|
||||
mDeviceOwnerFile = new File(dataDir, DEVICE_OWNER_FILE);
|
||||
mProfileOwnerBase = new File(dataDir, PROFILE_OWNER_FILE_BASE);
|
||||
}
|
||||
|
||||
@Override
|
||||
File getLegacyConfigFileWithTestOverride() {
|
||||
return mLegacyFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
File getDeviceOwnerFileWithTestOverride() {
|
||||
return mDeviceOwnerFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
File getProfileOwnerFileWithTestOverride(int userId) {
|
||||
return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
|
||||
}
|
||||
}
|
||||
|
||||
public final File dataDir;
|
||||
public final File systemUserDataDir;
|
||||
public final File secondUserDataDir;
|
||||
|
||||
public DevicePolicyManagerServiceTestable(DpmMockContext context, File dataDir) {
|
||||
super(context);
|
||||
this.dataDir = dataDir;
|
||||
|
||||
systemUserDataDir = new File(dataDir, "user0");
|
||||
DpmTestUtils.clearDir(dataDir);
|
||||
|
||||
secondUserDataDir = new File(dataDir, "user" + DpmMockContext.CALLER_USER_HANDLE);
|
||||
DpmTestUtils.clearDir(secondUserDataDir);
|
||||
|
||||
when(getContext().environment.getUserSystemDirectory(
|
||||
eq(DpmMockContext.CALLER_USER_HANDLE))).thenReturn(secondUserDataDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
DpmMockContext getContext() {
|
||||
return (DpmMockContext) super.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Owners newOwners() {
|
||||
return new OwnersTestable(getContext(), dataDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserManager getUserManager() {
|
||||
return getContext().userManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PackageManager getPackageManager() {
|
||||
return getContext().packageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowerManagerInternal getPowerManagerInternal() {
|
||||
return getContext().powerManagerInternal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NotificationManager getNotificationManager() {
|
||||
return getContext().notificationManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IWindowManager newIWindowManager() {
|
||||
return getContext().iwindowManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IActivityManager getIActivityManager() {
|
||||
return getContext().iactivityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LockPatternUtils newLockPatternUtils(Context context) {
|
||||
return getContext().lockPatternUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Looper getMyLooper() {
|
||||
return Looper.getMainLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getDevicePolicyFilePathForSystemUser() {
|
||||
return systemUserDataDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
long binderClearCallingIdentity() {
|
||||
return getContext().binder.clearCallingIdentity();
|
||||
}
|
||||
|
||||
@Override
|
||||
void binderRestoreCallingIdentity(long token) {
|
||||
getContext().binder.restoreCallingIdentity(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
int binderGetCallingUid() {
|
||||
return getContext().binder.getCallingUid();
|
||||
}
|
||||
|
||||
@Override
|
||||
int binderGetCallingPid() {
|
||||
return getContext().binder.getCallingPid();
|
||||
}
|
||||
|
||||
@Override
|
||||
UserHandle binderGetCallingUserHandle() {
|
||||
return getContext().binder.getCallingUserHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean binderIsCallingUidMyUid() {
|
||||
return getContext().binder.isCallerUidMyUid();
|
||||
}
|
||||
|
||||
@Override
|
||||
File environmentGetUserSystemDirectory(int userId) {
|
||||
return getContext().environment.getUserSystemDirectory(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
WakeLock powerManagerNewWakeLock(int levelAndFlags, String tag) {
|
||||
return getContext().powerManager.newWakeLock(levelAndFlags, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
void powerManagerGoToSleep(long time, int reason, int flags) {
|
||||
getContext().powerManager.goToSleep(time, reason, flags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import android.app.admin.DeviceAdminReceiver;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
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}.
|
||||
*
|
||||
m FrameworksServicesTests &&
|
||||
adb install \
|
||||
-r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
|
||||
adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
|
||||
-w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
|
||||
|
||||
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
|
||||
*/
|
||||
public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
|
||||
private DpmMockContext mContext;
|
||||
public DevicePolicyManager dpm;
|
||||
public DevicePolicyManagerServiceTestable dpms;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mContext = getContext();
|
||||
|
||||
when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
|
||||
.thenReturn(true);
|
||||
|
||||
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
|
||||
dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
|
||||
dpm = new DevicePolicyManagerTestable(mContext, dpms);
|
||||
}
|
||||
|
||||
public void testHasNoFeature() {
|
||||
when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
|
||||
.thenReturn(false);
|
||||
|
||||
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
|
||||
new DevicePolicyManagerServiceTestable(mContext, dataDir);
|
||||
|
||||
// If the device has no DPMS feature, it shouldn't register the local service.
|
||||
assertNull(LocalServices.getService(DevicePolicyManagerInternal.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
fail("Didn't throw SecurityException");
|
||||
} catch (SecurityException expected) {
|
||||
}
|
||||
|
||||
// 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);
|
||||
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)
|
||||
|
||||
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);
|
||||
|
||||
// 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(),
|
||||
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());
|
||||
|
||||
// TODO Verify other calls too.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
|
||||
/**
|
||||
* Overrides {@link #DevicePolicyManager} for dependency injection.
|
||||
*/
|
||||
public class DevicePolicyManagerTestable extends DevicePolicyManager {
|
||||
public final DevicePolicyManagerServiceTestable dpms;
|
||||
|
||||
public DevicePolicyManagerTestable(DpmMockContext context,
|
||||
DevicePolicyManagerServiceTestable dpms) {
|
||||
super(context, dpms);
|
||||
this.dpms = dpms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int myUserId() {
|
||||
return DpmMockContext.CALLER_USER_HANDLE;
|
||||
}
|
||||
}
|
||||
@@ -16,31 +16,328 @@
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
import android.app.IActivityManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
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.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.test.mock.MockContext;
|
||||
import android.view.IWindowManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
public class DpmMockContext extends ContextWrapper {
|
||||
private final UserManager mMockUserManager;
|
||||
/**
|
||||
* Context used throughout DPMS tests.
|
||||
*/
|
||||
public class DpmMockContext extends MockContext {
|
||||
/**
|
||||
* User-id of a non-system user we use throughout unit tests.
|
||||
*/
|
||||
public static final int CALLER_USER_HANDLE = 20;
|
||||
|
||||
/**
|
||||
* UID of the caller.
|
||||
*/
|
||||
public static final int CALLER_UID = UserHandle.PER_USER_RANGE * CALLER_USER_HANDLE + 123;
|
||||
|
||||
public DpmMockContext(Context context) {
|
||||
super(context);
|
||||
mMockUserManager = mock(UserManager.class);
|
||||
/**
|
||||
* PID of the caller.
|
||||
*/
|
||||
public static final int CALLER_PID = 22222;
|
||||
|
||||
/**
|
||||
* UID of the system server.
|
||||
*/
|
||||
public static final int SYSTEM_UID = android.os.Process.SYSTEM_UID;
|
||||
|
||||
/**
|
||||
* PID of the system server.
|
||||
*/
|
||||
public static final int SYSTEM_PID = 11111;
|
||||
|
||||
public static class MockBinder {
|
||||
int mCallingUid = CALLER_UID;
|
||||
int mCallingPid = CALLER_PID;
|
||||
|
||||
public long clearCallingIdentity() {
|
||||
final long token = (((long) mCallingUid) << 32) | (mCallingPid);
|
||||
mCallingUid = SYSTEM_UID;
|
||||
mCallingPid = SYSTEM_PID;
|
||||
return token;
|
||||
}
|
||||
|
||||
public void restoreCallingIdentity(long token) {
|
||||
mCallingUid = (int) (token >> 32);
|
||||
mCallingPid = (int) token;
|
||||
}
|
||||
|
||||
public int getCallingUid() {
|
||||
return mCallingUid;
|
||||
}
|
||||
|
||||
public int getCallingPid() {
|
||||
return mCallingPid;
|
||||
}
|
||||
|
||||
public UserHandle getCallingUserHandle() {
|
||||
return new UserHandle(UserHandle.getUserId(getCallingUid()));
|
||||
}
|
||||
|
||||
public boolean isCallerUidMyUid() {
|
||||
return mCallingUid == SYSTEM_UID;
|
||||
}
|
||||
}
|
||||
|
||||
public UserManager getMockUserManager() {
|
||||
return mMockUserManager;
|
||||
public static class EnvironmentForMock {
|
||||
public File getUserSystemDirectory(int userId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PowerManagerForMock {
|
||||
public WakeLock newWakeLock(int levelAndFlags, String tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void goToSleep(long time, int reason, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
public final Context realTestContext;
|
||||
|
||||
/**
|
||||
* Use this instance to verify unimplemented methods such as {@link #sendBroadcast}.
|
||||
* (Spying on {@code this} instance will confuse mockito somehow and I got weired "wrong number
|
||||
* of arguments" exceptions.)
|
||||
*/
|
||||
public final Context spiedContext;
|
||||
|
||||
public final MockBinder binder;
|
||||
public final EnvironmentForMock environment;
|
||||
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 LockPatternUtils lockPatternUtils;
|
||||
|
||||
/** Note this is a partial mock, not a real mock. */
|
||||
public final PackageManager packageManager;
|
||||
|
||||
public final List<String> callerPermissions = new ArrayList<>();
|
||||
|
||||
public DpmMockContext(Context context) {
|
||||
realTestContext = context;
|
||||
binder = new MockBinder();
|
||||
environment = mock(EnvironmentForMock.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);
|
||||
lockPatternUtils = mock(LockPatternUtils.class);
|
||||
|
||||
// Package manager is huge, so we use a partial mock instead.
|
||||
packageManager = spy(context.getPackageManager());
|
||||
|
||||
spiedContext = mock(Context.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
switch (name) {
|
||||
case Context.USER_SERVICE:
|
||||
return mMockUserManager;
|
||||
return userManager;
|
||||
case Context.POWER_SERVICE:
|
||||
return powerManager;
|
||||
}
|
||||
return super.getSystemService(name);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return packageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enforceCallingOrSelfPermission(String permission, String message) {
|
||||
if (binder.getCallingUid() == SYSTEM_UID) {
|
||||
return; // Assume system has all permissions.
|
||||
}
|
||||
if (!callerPermissions.contains(permission)) {
|
||||
throw new SecurityException("Caller doesn't have " + permission + " : " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent) {
|
||||
spiedContext.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission) {
|
||||
spiedContext.sendBroadcast(intent, receiverPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
|
||||
spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
|
||||
spiedContext.sendBroadcast(intent, receiverPermission, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
|
||||
spiedContext.sendBroadcast(intent, receiverPermission, appOp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
|
||||
spiedContext.sendOrderedBroadcast(intent, receiverPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcast(Intent intent, String receiverPermission,
|
||||
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
|
||||
String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
|
||||
initialCode, initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options,
|
||||
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
|
||||
String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendOrderedBroadcast(intent, receiverPermission, options, resultReceiver,
|
||||
scheduler,
|
||||
initialCode, initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
|
||||
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
|
||||
String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver,
|
||||
scheduler,
|
||||
initialCode, initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
|
||||
spiedContext.sendBroadcastAsUser(intent, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) {
|
||||
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
|
||||
int appOp) {
|
||||
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
|
||||
int initialCode, String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
|
||||
scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
|
||||
resultReceiver,
|
||||
scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
|
||||
resultReceiver, scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStickyBroadcast(Intent intent) {
|
||||
spiedContext.sendStickyBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode,
|
||||
initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStickyBroadcast(Intent intent) {
|
||||
spiedContext.removeStickyBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
|
||||
spiedContext.sendStickyBroadcastAsUser(intent, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
|
||||
String initialData, Bundle initialExtras) {
|
||||
spiedContext.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver, scheduler, initialCode,
|
||||
initialData, initialExtras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
|
||||
spiedContext.removeStickyBroadcastAsUser(intent, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
|
||||
return spiedContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
|
||||
String broadcastPermission, Handler scheduler) {
|
||||
return spiedContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
|
||||
IntentFilter filter, String broadcastPermission, Handler scheduler) {
|
||||
return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
|
||||
scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterReceiver(BroadcastReceiver receiver) {
|
||||
spiedContext.unregisterReceiver(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,14 +19,25 @@ package com.android.server.devicepolicy;
|
||||
import android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class DpmTestBase extends AndroidTestCase {
|
||||
private DpmMockContext mMockContext;
|
||||
public static final String TAG = "DpmTest";
|
||||
|
||||
protected Context mRealTestContext;
|
||||
protected DpmMockContext mMockContext;
|
||||
|
||||
public File dataDir;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mRealTestContext = super.getContext();
|
||||
mMockContext = new DpmMockContext(super.getContext());
|
||||
|
||||
dataDir = new File(mRealTestContext.getCacheDir(), "test-data");
|
||||
DpmTestUtils.clearDir(dataDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import android.os.FileUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Printer;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class DpmTestUtils {
|
||||
private DpmTestUtils() {
|
||||
}
|
||||
|
||||
public static void clearDir(File dir) {
|
||||
if (dir.exists()) {
|
||||
Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
|
||||
}
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
public static Printer LOG_PRINTER = new Printer() {
|
||||
@Override
|
||||
public void println(String x) {
|
||||
Log.i(DpmTestBase.TAG, x);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import android.app.admin.DeviceAdminReceiver;
|
||||
|
||||
public class DummyDeviceAdmin extends DeviceAdminReceiver {
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import android.os.UserHandle;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class MockUtils {
|
||||
private MockUtils() {
|
||||
}
|
||||
|
||||
public static UserHandle checkUserHandle(final int userId) {
|
||||
final Matcher<UserHandle> m = new BaseMatcher<UserHandle>() {
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
if (item == null) return false;
|
||||
return Objects.equal(((UserHandle) item).getIdentifier(), userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("UserHandle: user-id= \"" + userId + "\"");
|
||||
}
|
||||
};
|
||||
return Mockito.argThat(m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.FileUtils;
|
||||
import android.os.UserHandle;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -31,8 +30,6 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
@@ -47,58 +44,11 @@ import static org.mockito.Mockito.when;
|
||||
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
|
||||
*/
|
||||
public class OwnersTest extends DpmTestBase {
|
||||
private static final String TAG = "DeviceOwnerTest";
|
||||
|
||||
private static final String LEGACY_FILE = "legacy.xml";
|
||||
private static final String DEVICE_OWNER_FILE = "device_owner2.xml";
|
||||
private static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
|
||||
|
||||
private File mDataDir;
|
||||
|
||||
private class OwnersSub extends Owners {
|
||||
final File mLegacyFile;
|
||||
final File mDeviceOwnerFile;
|
||||
final File mProfileOwnerBase;
|
||||
|
||||
public OwnersSub() {
|
||||
super(getContext());
|
||||
mLegacyFile = new File(mDataDir, LEGACY_FILE);
|
||||
mDeviceOwnerFile = new File(mDataDir, DEVICE_OWNER_FILE);
|
||||
mProfileOwnerBase = new File(mDataDir, PROFILE_OWNER_FILE_BASE);
|
||||
}
|
||||
|
||||
@Override
|
||||
File getLegacyConfigFileWithTestOverride() {
|
||||
return mLegacyFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
File getDeviceOwnerFileWithTestOverride() {
|
||||
return mDeviceOwnerFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
File getProfileOwnerFileWithTestOverride(int userId) {
|
||||
return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mDataDir = new File(getContext().getCacheDir(), "OwnersTest");
|
||||
if (mDataDir.exists()) {
|
||||
assertTrue("failed to delete dir", FileUtils.deleteContents(mDataDir));
|
||||
}
|
||||
mDataDir.mkdirs();
|
||||
Log.i(TAG, "Created " + mDataDir);
|
||||
}
|
||||
|
||||
private String readAsset(String assetPath) throws IOException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader((getContext().getResources().getAssets().open(assetPath))))) {
|
||||
new InputStreamReader(
|
||||
mRealTestContext.getResources().getAssets().open(assetPath)))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
@@ -126,7 +76,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
ui.id = userId;
|
||||
userInfos.add(ui);
|
||||
}
|
||||
when(getContext().getMockUserManager().getUsers()).thenReturn(userInfos);
|
||||
when(getContext().userManager.getUsers()).thenReturn(userInfos);
|
||||
}
|
||||
|
||||
public void testUpgrade01() throws Exception {
|
||||
@@ -134,9 +84,10 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// First, migrate.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test01/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test01/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -160,7 +111,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// Then re-read and check.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
owners.load();
|
||||
|
||||
assertFalse(owners.hasDeviceOwner());
|
||||
@@ -176,9 +127,10 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// First, migrate.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test02/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test02/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -204,7 +156,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// Then re-read and check.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
owners.load();
|
||||
|
||||
assertTrue(owners.hasDeviceOwner());
|
||||
@@ -223,9 +175,10 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// First, migrate.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test03/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test03/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -259,7 +212,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// Then re-read and check.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
owners.load();
|
||||
|
||||
assertFalse(owners.hasDeviceOwner());
|
||||
@@ -286,9 +239,10 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// First, migrate.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test04/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test04/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -327,7 +281,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// Then re-read and check.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
owners.load();
|
||||
|
||||
assertTrue(owners.hasDeviceOwner());
|
||||
@@ -359,9 +313,10 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// First, migrate.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test05/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test05/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -386,7 +341,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// Then re-read and check.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
owners.load();
|
||||
|
||||
assertFalse(owners.hasDeviceOwner());
|
||||
@@ -405,9 +360,10 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// First, migrate.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test06/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test06/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -431,7 +387,7 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
// Then re-read and check.
|
||||
{
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
owners.load();
|
||||
|
||||
assertFalse(owners.hasDeviceOwner());
|
||||
@@ -447,10 +403,11 @@ public class OwnersTest extends DpmTestBase {
|
||||
public void testRemoveExistingFiles() throws Exception {
|
||||
addUsersToUserManager(10, 11, 20, 21);
|
||||
|
||||
final OwnersSub owners = new OwnersSub();
|
||||
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
|
||||
|
||||
// First, migrate to create new-style config files.
|
||||
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test04/input.xml"));
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test04/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user