Loading core/java/android/app/usage/UsageStatsManagerInternal.java +17 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.ComponentName; import android.content.res.Configuration; import java.util.List; import java.util.Set; /** * UsageStatsManager local system service interface. Loading Loading @@ -158,6 +159,22 @@ public abstract class UsageStatsManagerInternal { */ public abstract void applyRestoredPayload(@UserIdInt int userId, String key, byte[] payload); /** * Called by DevicePolicyManagerService to inform that a new admin has been added. * * @param packageName the package in which the admin component is part of. * @param userId the userId in which the admin has been added. */ public abstract void onActiveAdminAdded(String packageName, int userId); /** * Called by DevicePolicyManagerService to inform about the active admins in an user. * * @param adminApps the set of active admins in {@param userId} or null if there are none. * @param userId the userId to which the admin apps belong. */ public abstract void setActiveAdminApps(Set<String> adminApps, int userId); /** * Return usage stats. * Loading services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,12 @@ import java.util.List; * should be added here to avoid build breakage in downstream branches. */ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when the service is started. * * @see {@link SystemService#onStart}. */ abstract void handleStart(); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} during the various boot phases. * Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +50 −2 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ import android.app.admin.SystemUpdateInfo; import android.app.admin.SystemUpdatePolicy; import android.app.backup.IBackupManager; import android.app.trust.TrustManager; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -401,6 +402,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final IPackageManager mIPackageManager; final UserManager mUserManager; final UserManagerInternal mUserManagerInternal; final UsageStatsManagerInternal mUsageStatsManagerInternal; final TelephonyManager mTelephonyManager; private final LockPatternUtils mLockPatternUtils; private final DevicePolicyConstants mConstants; Loading Loading @@ -504,6 +506,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void onStart() { publishBinderService(Context.DEVICE_POLICY_SERVICE, mService); mService.handleStart(); } @Override Loading Loading @@ -1560,6 +1563,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { removedAdmin = true; policy.mAdminList.remove(i); policy.mAdminMap.remove(aa.info.getComponent()); pushActiveAdminPackagesLocked(userHandle); } } } catch (RemoteException re) { Loading Loading @@ -1653,6 +1657,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return LocalServices.getService(PackageManagerInternal.class); } UsageStatsManagerInternal getUsageStatsManagerInternal() { return LocalServices.getService(UsageStatsManagerInternal.class); } NotificationManager getNotificationManager() { return mContext.getSystemService(NotificationManager.class); } Loading Loading @@ -1923,6 +1931,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mUserManager = Preconditions.checkNotNull(injector.getUserManager()); mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal()); mUsageStatsManagerInternal = Preconditions.checkNotNull( injector.getUsageStatsManagerInternal()); mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager()); mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager()); Loading Loading @@ -3189,6 +3199,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } @Override void handleStart() { pushActiveAdminPackages(); } @Override void handleStartUser(int userId) { updateScreenCaptureDisabledInWindowManager(userId, Loading Loading @@ -3357,6 +3372,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (replaceIndex == -1) { policy.mAdminList.add(newAdmin); enableIfNecessary(info.getPackageName(), userHandle); mUsageStatsManagerInternal.onActiveAdminAdded( adminReceiver.getPackageName(), userHandle); } else { policy.mAdminList.set(replaceIndex, newAdmin); } Loading @@ -3369,6 +3386,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private void pushActiveAdminPackages() { synchronized (this) { final List<UserInfo> users = mUserManager.getUsers(); for (int i = users.size() - 1; i >= 0; --i) { final int userId = users.get(i).id; mUsageStatsManagerInternal.setActiveAdminApps( getActiveAdminPackagesLocked(userId), userId); } } } private void pushActiveAdminPackagesLocked(int userId) { mUsageStatsManagerInternal.setActiveAdminApps( getActiveAdminPackagesLocked(userId), userId); } private Set<String> getActiveAdminPackagesLocked(int userId) { final DevicePolicyData policy = getUserData(userId); Set<String> adminPkgs = null; for (int i = policy.mAdminList.size() - 1; i >= 0; --i) { final String pkgName = policy.mAdminList.get(i).info.getPackageName(); if (adminPkgs == null) { adminPkgs = new ArraySet<>(); } adminPkgs.add(pkgName); } return adminPkgs; } private void transferActiveAdminUncheckedLocked(ComponentName incomingReceiver, ComponentName outgoingReceiver, int userHandle) { final DevicePolicyData policy = getUserData(userHandle); Loading Loading @@ -3487,6 +3533,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } @Override public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) { if (!mHasFeature) { return; Loading Loading @@ -3540,7 +3587,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private boolean isPackageTestOnly(String packageName, int userHandle) { final ApplicationInfo ai; try { ai = mIPackageManager.getApplicationInfo(packageName, ai = mInjector.getIPackageManager().getApplicationInfo(packageName, (PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE), userHandle); } catch (RemoteException e) { Loading @@ -3562,7 +3609,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void enforceShell(String method) { final int callingUid = Binder.getCallingUid(); final int callingUid = mInjector.binderGetCallingUid(); if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { throw new SecurityException("Non-shell user attempted to call " + method); } Loading Loading @@ -11163,6 +11210,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (doProxyCleanup) { resetGlobalProxyLocked(policy); } pushActiveAdminPackagesLocked(userHandle); saveSettingsLocked(userHandle); updateMaximumTimeToLockLocked(userHandle); policy.mRemovingAdmins.remove(adminReceiver); Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +6 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.IActivityManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.backup.IBackupManager; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; Loading Loading @@ -151,6 +152,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.userManagerInternal; } @Override UsageStatsManagerInternal getUsageStatsManagerInternal() { return services.usageStatsManagerInternal; } @Override PackageManagerInternal getPackageManagerInternal() { return services.packageManagerInternal; Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +135 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.mockito.hamcrest.MockitoHamcrest.argThat; Loading Loading @@ -90,6 +91,7 @@ import com.android.server.pm.UserRestrictionsUtils; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; Loading Loading @@ -182,6 +184,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { initializeDpms(); Mockito.reset(getServices().usageStatsManagerInternal); setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID); setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID); setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_UID); Loading @@ -207,6 +210,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); dpms.handleStart(); dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); Loading Loading @@ -278,6 +282,32 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertNull(LocalServices.getService(DevicePolicyManagerInternal.class)); } public void testHandleStart() throws Exception { // Device owner in SYSTEM_USER setDeviceOwner(); // Profile owner in CALLER_USER_HANDLE setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID); setAsProfileOwner(admin2); // Active admin in CALLER_USER_HANDLE final int ANOTHER_UID = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, 1306); setUpPackageManagerForFakeAdmin(adminAnotherPackage, ANOTHER_UID, admin2); dpm.setActiveAdmin(adminAnotherPackage, /* replace =*/ false, DpmMockContext.CALLER_USER_HANDLE); assertTrue(dpm.isAdminActiveAsUser(adminAnotherPackage, DpmMockContext.CALLER_USER_HANDLE)); initializeDpms(); // Verify verify(getServices().usageStatsManagerInternal).setActiveAdminApps( MockUtils.checkAdminApps(admin1.getPackageName()), eq(UserHandle.USER_SYSTEM)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( MockUtils.checkAdminApps(admin2.getPackageName(), adminAnotherPackage.getPackageName()), eq(DpmMockContext.CALLER_USER_HANDLE)); } /** * Caller doesn't have proper permissions. */ Loading Loading @@ -330,6 +360,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(DpmMockContext.CALLER_USER_HANDLE), anyString()); verify(getServices().usageStatsManagerInternal).onActiveAdminAdded( admin1.getPackageName(), DpmMockContext.CALLER_USER_HANDLE); // TODO Verify other calls too. // Make sure it's active admin1. Loading Loading @@ -369,6 +402,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(DpmMockContext.CALLER_USER_HANDLE), anyString()); // times(2) because it was previously called for admin1 which is in the same package // as admin2. verify(getServices().usageStatsManagerInternal, times(2)).onActiveAdminAdded( admin2.getPackageName(), DpmMockContext.CALLER_USER_HANDLE); // 4. Add the same admin1 again without replace, which should throw. assertExpectException(IllegalArgumentException.class, /* messageRegex= */ null, () -> dpm.setActiveAdmin(admin1, /* replace =*/ false)); Loading @@ -384,6 +422,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertEquals(admin1, admins.get(0)); assertEquals(admin2, admins.get(1)); // There shouldn't be any callback to UsageStatsManagerInternal when the admin is being // replaced verifyNoMoreInteractions(getServices().usageStatsManagerInternal); // Another user has no admins. mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL"); Loading Loading @@ -516,6 +558,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { () -> dpm.removeActiveAdmin(admin1)); assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal, times(0)).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); // 2. User unlocked. when(getServices().userManager.isUserUnlocked(eq(DpmMockContext.CALLER_USER_HANDLE))) Loading @@ -523,6 +567,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.removeActiveAdmin(admin1); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); } /** Loading @@ -547,6 +593,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); // TODO DO Still can't be removed in this case. } Loading Loading @@ -588,6 +636,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { isNull(Bundle.class)); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); // Again broadcast from saveSettingsLocked(). verify(mContext.spiedContext, times(2)).sendBroadcastAsUser( Loading @@ -598,6 +648,86 @@ public class DevicePolicyManagerTest extends DpmTestBase { // TODO Check other internal calls. } public void testRemoveActiveAdmin_multipleAdminsInUser() { // 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)); // Add admin2. dpm.setActiveAdmin(admin2, /* replace =*/ false); assertTrue(dpm.isAdminActive(admin2)); assertFalse(dpm.isRemovingAdmin(admin2, DpmMockContext.CALLER_USER_HANDLE)); // Broadcast from saveSettingsLocked(). verify(mContext.spiedContext, times(2)).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); verify(mContext.spiedContext).sendOrderedBroadcastAsUser( MockUtils.checkIntentAction( DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED), MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE), isNull(String.class), any(BroadcastReceiver.class), eq(dpms.mHandler), eq(Activity.RESULT_OK), isNull(String.class), isNull(Bundle.class)); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( MockUtils.checkAdminApps(admin2.getPackageName()), eq(DpmMockContext.CALLER_USER_HANDLE)); // Again broadcast from saveSettingsLocked(). verify(mContext.spiedContext, times(3)).sendBroadcastAsUser( MockUtils.checkIntentAction( DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE)); } /** * Test for: * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)} */ public void testForceRemoveActiveAdmin() throws Exception { mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS); // Add admin. setupPackageInPackageManager(admin1.getPackageName(), /* userId= */ DpmMockContext.CALLER_USER_HANDLE, /* appId= */ 10138, /* flags= */ ApplicationInfo.FLAG_TEST_ONLY); dpm.setActiveAdmin(admin1, /* replace =*/ false); assertTrue(dpm.isAdminActive(admin1)); // Calling from a non-shell uid should fail with a SecurityException mContext.binder.callingUid = 123456; assertExpectException(SecurityException.class, /* messageRegex =*/ "Non-shell user attempted to call", () -> dpms.forceRemoveActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE)); mContext.binder.callingUid = Process.SHELL_UID; dpms.forceRemoveActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE); mContext.callerPermissions.add(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); // Verify assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); } /** * Test for: @{link DevicePolicyManager#setActivePasswordState} * Loading Loading @@ -954,6 +1084,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(null), eq(true), eq(CAMERA_NOT_DISABLED)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, UserHandle.USER_SYSTEM); assertFalse(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)); // ACTION_DEVICE_OWNER_CHANGED should be sent twice, once for setting the device owner Loading Loading @@ -1044,6 +1177,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { // Check assertFalse(dpm.isProfileOwnerApp(admin1.getPackageName())); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); } public void testSetProfileOwner_failures() throws Exception { Loading Loading
core/java/android/app/usage/UsageStatsManagerInternal.java +17 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.ComponentName; import android.content.res.Configuration; import java.util.List; import java.util.Set; /** * UsageStatsManager local system service interface. Loading Loading @@ -158,6 +159,22 @@ public abstract class UsageStatsManagerInternal { */ public abstract void applyRestoredPayload(@UserIdInt int userId, String key, byte[] payload); /** * Called by DevicePolicyManagerService to inform that a new admin has been added. * * @param packageName the package in which the admin component is part of. * @param userId the userId in which the admin has been added. */ public abstract void onActiveAdminAdded(String packageName, int userId); /** * Called by DevicePolicyManagerService to inform about the active admins in an user. * * @param adminApps the set of active admins in {@param userId} or null if there are none. * @param userId the userId to which the admin apps belong. */ public abstract void setActiveAdminApps(Set<String> adminApps, int userId); /** * Return usage stats. * Loading
services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,12 @@ import java.util.List; * should be added here to avoid build breakage in downstream branches. */ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when the service is started. * * @see {@link SystemService#onStart}. */ abstract void handleStart(); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} during the various boot phases. * Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +50 −2 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ import android.app.admin.SystemUpdateInfo; import android.app.admin.SystemUpdatePolicy; import android.app.backup.IBackupManager; import android.app.trust.TrustManager; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -401,6 +402,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final IPackageManager mIPackageManager; final UserManager mUserManager; final UserManagerInternal mUserManagerInternal; final UsageStatsManagerInternal mUsageStatsManagerInternal; final TelephonyManager mTelephonyManager; private final LockPatternUtils mLockPatternUtils; private final DevicePolicyConstants mConstants; Loading Loading @@ -504,6 +506,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void onStart() { publishBinderService(Context.DEVICE_POLICY_SERVICE, mService); mService.handleStart(); } @Override Loading Loading @@ -1560,6 +1563,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { removedAdmin = true; policy.mAdminList.remove(i); policy.mAdminMap.remove(aa.info.getComponent()); pushActiveAdminPackagesLocked(userHandle); } } } catch (RemoteException re) { Loading Loading @@ -1653,6 +1657,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return LocalServices.getService(PackageManagerInternal.class); } UsageStatsManagerInternal getUsageStatsManagerInternal() { return LocalServices.getService(UsageStatsManagerInternal.class); } NotificationManager getNotificationManager() { return mContext.getSystemService(NotificationManager.class); } Loading Loading @@ -1923,6 +1931,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mUserManager = Preconditions.checkNotNull(injector.getUserManager()); mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal()); mUsageStatsManagerInternal = Preconditions.checkNotNull( injector.getUsageStatsManagerInternal()); mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager()); mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager()); Loading Loading @@ -3189,6 +3199,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } @Override void handleStart() { pushActiveAdminPackages(); } @Override void handleStartUser(int userId) { updateScreenCaptureDisabledInWindowManager(userId, Loading Loading @@ -3357,6 +3372,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (replaceIndex == -1) { policy.mAdminList.add(newAdmin); enableIfNecessary(info.getPackageName(), userHandle); mUsageStatsManagerInternal.onActiveAdminAdded( adminReceiver.getPackageName(), userHandle); } else { policy.mAdminList.set(replaceIndex, newAdmin); } Loading @@ -3369,6 +3386,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private void pushActiveAdminPackages() { synchronized (this) { final List<UserInfo> users = mUserManager.getUsers(); for (int i = users.size() - 1; i >= 0; --i) { final int userId = users.get(i).id; mUsageStatsManagerInternal.setActiveAdminApps( getActiveAdminPackagesLocked(userId), userId); } } } private void pushActiveAdminPackagesLocked(int userId) { mUsageStatsManagerInternal.setActiveAdminApps( getActiveAdminPackagesLocked(userId), userId); } private Set<String> getActiveAdminPackagesLocked(int userId) { final DevicePolicyData policy = getUserData(userId); Set<String> adminPkgs = null; for (int i = policy.mAdminList.size() - 1; i >= 0; --i) { final String pkgName = policy.mAdminList.get(i).info.getPackageName(); if (adminPkgs == null) { adminPkgs = new ArraySet<>(); } adminPkgs.add(pkgName); } return adminPkgs; } private void transferActiveAdminUncheckedLocked(ComponentName incomingReceiver, ComponentName outgoingReceiver, int userHandle) { final DevicePolicyData policy = getUserData(userHandle); Loading Loading @@ -3487,6 +3533,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } @Override public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) { if (!mHasFeature) { return; Loading Loading @@ -3540,7 +3587,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private boolean isPackageTestOnly(String packageName, int userHandle) { final ApplicationInfo ai; try { ai = mIPackageManager.getApplicationInfo(packageName, ai = mInjector.getIPackageManager().getApplicationInfo(packageName, (PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE), userHandle); } catch (RemoteException e) { Loading @@ -3562,7 +3609,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void enforceShell(String method) { final int callingUid = Binder.getCallingUid(); final int callingUid = mInjector.binderGetCallingUid(); if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { throw new SecurityException("Non-shell user attempted to call " + method); } Loading Loading @@ -11163,6 +11210,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (doProxyCleanup) { resetGlobalProxyLocked(policy); } pushActiveAdminPackagesLocked(userHandle); saveSettingsLocked(userHandle); updateMaximumTimeToLockLocked(userHandle); policy.mRemovingAdmins.remove(adminReceiver); Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +6 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.IActivityManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.backup.IBackupManager; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; Loading Loading @@ -151,6 +152,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.userManagerInternal; } @Override UsageStatsManagerInternal getUsageStatsManagerInternal() { return services.usageStatsManagerInternal; } @Override PackageManagerInternal getPackageManagerInternal() { return services.packageManagerInternal; Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +135 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.mockito.hamcrest.MockitoHamcrest.argThat; Loading Loading @@ -90,6 +91,7 @@ import com.android.server.pm.UserRestrictionsUtils; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; Loading Loading @@ -182,6 +184,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { initializeDpms(); Mockito.reset(getServices().usageStatsManagerInternal); setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID); setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID); setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_UID); Loading @@ -207,6 +210,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); dpms.handleStart(); dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); Loading Loading @@ -278,6 +282,32 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertNull(LocalServices.getService(DevicePolicyManagerInternal.class)); } public void testHandleStart() throws Exception { // Device owner in SYSTEM_USER setDeviceOwner(); // Profile owner in CALLER_USER_HANDLE setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID); setAsProfileOwner(admin2); // Active admin in CALLER_USER_HANDLE final int ANOTHER_UID = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, 1306); setUpPackageManagerForFakeAdmin(adminAnotherPackage, ANOTHER_UID, admin2); dpm.setActiveAdmin(adminAnotherPackage, /* replace =*/ false, DpmMockContext.CALLER_USER_HANDLE); assertTrue(dpm.isAdminActiveAsUser(adminAnotherPackage, DpmMockContext.CALLER_USER_HANDLE)); initializeDpms(); // Verify verify(getServices().usageStatsManagerInternal).setActiveAdminApps( MockUtils.checkAdminApps(admin1.getPackageName()), eq(UserHandle.USER_SYSTEM)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( MockUtils.checkAdminApps(admin2.getPackageName(), adminAnotherPackage.getPackageName()), eq(DpmMockContext.CALLER_USER_HANDLE)); } /** * Caller doesn't have proper permissions. */ Loading Loading @@ -330,6 +360,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(DpmMockContext.CALLER_USER_HANDLE), anyString()); verify(getServices().usageStatsManagerInternal).onActiveAdminAdded( admin1.getPackageName(), DpmMockContext.CALLER_USER_HANDLE); // TODO Verify other calls too. // Make sure it's active admin1. Loading Loading @@ -369,6 +402,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(DpmMockContext.CALLER_USER_HANDLE), anyString()); // times(2) because it was previously called for admin1 which is in the same package // as admin2. verify(getServices().usageStatsManagerInternal, times(2)).onActiveAdminAdded( admin2.getPackageName(), DpmMockContext.CALLER_USER_HANDLE); // 4. Add the same admin1 again without replace, which should throw. assertExpectException(IllegalArgumentException.class, /* messageRegex= */ null, () -> dpm.setActiveAdmin(admin1, /* replace =*/ false)); Loading @@ -384,6 +422,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertEquals(admin1, admins.get(0)); assertEquals(admin2, admins.get(1)); // There shouldn't be any callback to UsageStatsManagerInternal when the admin is being // replaced verifyNoMoreInteractions(getServices().usageStatsManagerInternal); // Another user has no admins. mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL"); Loading Loading @@ -516,6 +558,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { () -> dpm.removeActiveAdmin(admin1)); assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal, times(0)).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); // 2. User unlocked. when(getServices().userManager.isUserUnlocked(eq(DpmMockContext.CALLER_USER_HANDLE))) Loading @@ -523,6 +567,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.removeActiveAdmin(admin1); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); } /** Loading @@ -547,6 +593,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); // TODO DO Still can't be removed in this case. } Loading Loading @@ -588,6 +636,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { isNull(Bundle.class)); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); // Again broadcast from saveSettingsLocked(). verify(mContext.spiedContext, times(2)).sendBroadcastAsUser( Loading @@ -598,6 +648,86 @@ public class DevicePolicyManagerTest extends DpmTestBase { // TODO Check other internal calls. } public void testRemoveActiveAdmin_multipleAdminsInUser() { // 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)); // Add admin2. dpm.setActiveAdmin(admin2, /* replace =*/ false); assertTrue(dpm.isAdminActive(admin2)); assertFalse(dpm.isRemovingAdmin(admin2, DpmMockContext.CALLER_USER_HANDLE)); // Broadcast from saveSettingsLocked(). verify(mContext.spiedContext, times(2)).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); verify(mContext.spiedContext).sendOrderedBroadcastAsUser( MockUtils.checkIntentAction( DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED), MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE), isNull(String.class), any(BroadcastReceiver.class), eq(dpms.mHandler), eq(Activity.RESULT_OK), isNull(String.class), isNull(Bundle.class)); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( MockUtils.checkAdminApps(admin2.getPackageName()), eq(DpmMockContext.CALLER_USER_HANDLE)); // Again broadcast from saveSettingsLocked(). verify(mContext.spiedContext, times(3)).sendBroadcastAsUser( MockUtils.checkIntentAction( DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE)); } /** * Test for: * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)} */ public void testForceRemoveActiveAdmin() throws Exception { mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS); // Add admin. setupPackageInPackageManager(admin1.getPackageName(), /* userId= */ DpmMockContext.CALLER_USER_HANDLE, /* appId= */ 10138, /* flags= */ ApplicationInfo.FLAG_TEST_ONLY); dpm.setActiveAdmin(admin1, /* replace =*/ false); assertTrue(dpm.isAdminActive(admin1)); // Calling from a non-shell uid should fail with a SecurityException mContext.binder.callingUid = 123456; assertExpectException(SecurityException.class, /* messageRegex =*/ "Non-shell user attempted to call", () -> dpms.forceRemoveActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE)); mContext.binder.callingUid = Process.SHELL_UID; dpms.forceRemoveActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE); mContext.callerPermissions.add(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); // Verify assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); } /** * Test for: @{link DevicePolicyManager#setActivePasswordState} * Loading Loading @@ -954,6 +1084,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(null), eq(true), eq(CAMERA_NOT_DISABLED)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, UserHandle.USER_SYSTEM); assertFalse(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)); // ACTION_DEVICE_OWNER_CHANGED should be sent twice, once for setting the device owner Loading Loading @@ -1044,6 +1177,8 @@ public class DevicePolicyManagerTest extends DpmTestBase { // Check assertFalse(dpm.isProfileOwnerApp(admin1.getPackageName())); assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE)); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( null, DpmMockContext.CALLER_USER_HANDLE); } public void testSetProfileOwner_failures() throws Exception { Loading