Loading services/core/java/com/android/server/pm/UserManagerService.java +49 −21 Original line number Diff line number Diff line Loading @@ -1926,8 +1926,17 @@ public class UserManagerService extends IUserManager.Stub { availabilityIntent.putExtra(Intent.EXTRA_USER_HANDLE, profileInfo.getUserHandle().getIdentifier()); if (profileInfo.isManagedProfile()) { getDevicePolicyManagerInternal().broadcastIntentToManifestReceivers( availabilityIntent, parentHandle, /* requiresPermission= */ true); var dpmi = getDevicePolicyManagerInternal(); if (dpmi == null) { // This should never happen because the profile is a managed profile, but it doesn't // hurt to check... Slogf.wtf(LOG_TAG, "broadcastProfileAvailabilityChanges(profile=%s, parent=%s): " + "not calling dmpi.broadcastIntentToManifestReceivers() because dpmi is " + "null", profileInfo, parentHandle); } else { dpmi.broadcastIntentToManifestReceivers(availabilityIntent, parentHandle, /* requiresPermission= */ true); } } availabilityIntent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); Loading Loading @@ -3229,7 +3238,8 @@ public class UserManagerService extends IUserManager.Stub { return false; } } return !getDevicePolicyManagerInternal().isUserOrganizationManaged(userId); var dpmi = getDevicePolicyManagerInternal(); return dpmi == null || !dpmi.isUserOrganizationManaged(userId); } @Override Loading Loading @@ -7314,13 +7324,22 @@ public class UserManagerService extends IUserManager.Stub { mContext.sendBroadcastAsUser(intent, parentHandle, /* receiverPermission= */null); } private void sendManagedProfileRemovedBroadcast(int parentUserId, int removedUserId) { private void sendManagedProfileRemovedBroadcast(@UserIdInt int parentUserId, @UserIdInt int removedUserId) { var dpmi = getDevicePolicyManagerInternal(); if (dpmi == null) { // This should never happen (because current caller checks if removed used is of type // UserManager.USER_TYPE_PROFILE_MANAGED), but it doesn't hurt to check... Slogf.wtf(LOG_TAG, "sendManagedProfileRemovedBroadcast(parent=%d, removed=%d): ignoring" + " as device doesn't have DPMI", parentUserId, removedUserId); return; } Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED); managedProfileIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(removedUserId)); managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId); final UserHandle parentHandle = UserHandle.of(parentUserId); getDevicePolicyManagerInternal().broadcastIntentToManifestReceivers( managedProfileIntent, parentHandle, /* requiresPermission= */ false); dpmi.broadcastIntentToManifestReceivers(managedProfileIntent, parentHandle, /* requiresPermission= */ false); managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(managedProfileIntent, parentHandle, Loading @@ -7338,25 +7357,29 @@ public class UserManagerService extends IUserManager.Stub { || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) { checkSystemOrRoot("get application restrictions for other user/app " + packageName); } if (android.app.admin.flags.Flags.appRestrictionsCoexistence()) { List<Bundle> restrictions = getDevicePolicyManagerInternal().getApplicationRestrictionsPerAdminForUser( packageName, userId); if (restrictions.isEmpty()) { List<Bundle> restrictions = null; var dpmi = getDevicePolicyManagerInternal(); if (dpmi != null) { restrictions = dpmi.getApplicationRestrictionsPerAdminForUser(packageName, userId); } if (restrictions == null || restrictions.isEmpty()) { return Bundle.EMPTY; } else { if (restrictions.size() > 1) { Slog.w(LOG_TAG, "Application restriction list contains more than one element."); } int size = restrictions.size(); if (size > 1) { Slogf.w(LOG_TAG, "Application restriction list contains more than one (%d) element;" + " returning first", size); } return restrictions.getFirst(); } } else { synchronized (mAppRestrictionsLock) { // Read the restrictions from XML return readApplicationRestrictionsLAr(packageName, userId); } } } @Override public void setApplicationRestrictions(String packageName, Bundle restrictions, Loading Loading @@ -8961,8 +8984,13 @@ public class UserManagerService extends IUserManager.Stub { return mPmInternal; } /** Returns the internal device policy manager interface. */ private DevicePolicyManagerInternal getDevicePolicyManagerInternal() { /** * Returns the internal device policy manager interface. * * <p>NOTE: it's {@code null} when the device doesn't have the * {@code android.software.device_admin} feature. */ private @Nullable DevicePolicyManagerInternal getDevicePolicyManagerInternal() { if (mDevicePolicyManagerInternal == null) { mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class); Loading services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceMockedTest.java +72 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.server.pm; import static android.app.admin.flags.Flags.FLAG_APP_RESTRICTIONS_COEXISTENCE; import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; import static android.content.pm.PackageManager.FEATURE_EMBEDDED; import static android.content.pm.PackageManager.FEATURE_LEANBACK; Loading Loading @@ -71,10 +72,12 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.KeyguardManager; import android.app.PropertyInvalidatedCache; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManagerInternal; import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.Bundle; import android.os.PowerManager; import android.os.ServiceSpecificException; import android.os.SystemProperties; Loading Loading @@ -206,6 +209,7 @@ public final class UserManagerServiceMockedTest { private @Mock StorageManager mStorageManager; private @Mock LockSettingsInternal mLockSettingsInternal; private @Mock PackageManagerInternal mPackageManagerInternal; private @Mock DevicePolicyManagerInternal mDevicePolicyManagerInternal; private @Mock KeyguardManager mKeyguardManager; private @Mock PowerManager mPowerManager; private @Mock TelecomManager mTelecomManager; Loading Loading @@ -1580,7 +1584,7 @@ public final class UserManagerServiceMockedTest { @EnableFlags(FLAG_DEMOTE_MAIN_USER) public void testSetMainUser_userNotFound() { assumeDoesntHaveMainUser(); int userId = 666; int userId = OTHER_USER_ID; expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isFalse(); Loading Loading @@ -1870,6 +1874,62 @@ public final class UserManagerServiceMockedTest { assertThat(mUsers.get(USER_ID).info.isAdmin()).isTrue(); } // NOTE: tests for getApplicationRestrictionsForUser were added to check when DPMI is null, so // they don't encompass all scenarios (like when FLAG_APP_RESTRICTIONS_COEXISTENCE is not set) @Test public void testGetApplicationRestrictionsForUser_invalidUser() { mockCallingUserId(USER_ID); assertThrows(SecurityException.class, () -> mUms .getApplicationRestrictionsForUser(mRealContext.getPackageName(), OTHER_USER_ID)); } @Test public void testGetApplicationRestrictionsForUser_differentPackage() { // Should throw because it's not the same as the calling uid package assertThrows(SecurityException.class, () -> mUms.getApplicationRestrictions("Age, the name is Pack Age")); } @Test @RequiresFlagsEnabled(FLAG_APP_RESTRICTIONS_COEXISTENCE) public void testGetApplicationRestrictionsForUser_flagEnabled_noDPMI() { mockGetLocalService(DevicePolicyManagerInternal.class, null); var result = mUms.getApplicationRestrictions(mRealContext.getPackageName()); assertThat(result).isSameInstanceAs(Bundle.EMPTY); } @Test @RequiresFlagsEnabled(FLAG_APP_RESTRICTIONS_COEXISTENCE) public void testGetApplicationRestrictionsForUser_flagEnabled_noRestrictions() { String pkg = mRealContext.getPackageName(); mockCallingUserId(USER_ID); mockDpmiGetApplicationRestrictionsPerAdminForUser(pkg, USER_ID); mockGetLocalService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); var result = mUms.getApplicationRestrictions(pkg); assertThat(result).isSameInstanceAs(Bundle.EMPTY); } @Test @RequiresFlagsEnabled(FLAG_APP_RESTRICTIONS_COEXISTENCE) public void testGetApplicationRestrictionsForUser_flagEnabled_multipleRestrictions() { String pkg = mRealContext.getPackageName(); Bundle bundle1 = new Bundle(); Bundle bundle2 = new Bundle(); mockCallingUserId(USER_ID); mockDpmiGetApplicationRestrictionsPerAdminForUser(pkg, USER_ID, bundle1, bundle2); mockGetLocalService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); var result = mUms.getApplicationRestrictions(pkg); assertThat(result).isSameInstanceAs(bundle1); } /** * Returns true if the user's XML file has Default restrictions * @param userId Id of the user. Loading Loading @@ -2024,6 +2084,17 @@ public final class UserManagerServiceMockedTest { doReturn(userId).when(UserHandle::getCallingUserId); } private void mockDpmiGetApplicationRestrictionsPerAdminForUser(String pkgName, @UserIdInt int userId, Bundle...bundles) { List<Bundle> list = Arrays.asList(bundles); Log.d(TAG, "mockDpmiGetApplicationRestrictionsPerAdminForAnyUser(" + pkgName + ", " + userId + "): will return " + list); when(mDevicePolicyManagerInternal .getApplicationRestrictionsPerAdminForUser(pkgName, userId)) .thenReturn(list); } private void expectUserJourneyLogged(@UserIdInt int userId, @UserJourney int journey) { verify(mUserJourneyLogger).logUserJourneyBegin(userId, journey); } Loading Loading
services/core/java/com/android/server/pm/UserManagerService.java +49 −21 Original line number Diff line number Diff line Loading @@ -1926,8 +1926,17 @@ public class UserManagerService extends IUserManager.Stub { availabilityIntent.putExtra(Intent.EXTRA_USER_HANDLE, profileInfo.getUserHandle().getIdentifier()); if (profileInfo.isManagedProfile()) { getDevicePolicyManagerInternal().broadcastIntentToManifestReceivers( availabilityIntent, parentHandle, /* requiresPermission= */ true); var dpmi = getDevicePolicyManagerInternal(); if (dpmi == null) { // This should never happen because the profile is a managed profile, but it doesn't // hurt to check... Slogf.wtf(LOG_TAG, "broadcastProfileAvailabilityChanges(profile=%s, parent=%s): " + "not calling dmpi.broadcastIntentToManifestReceivers() because dpmi is " + "null", profileInfo, parentHandle); } else { dpmi.broadcastIntentToManifestReceivers(availabilityIntent, parentHandle, /* requiresPermission= */ true); } } availabilityIntent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); Loading Loading @@ -3229,7 +3238,8 @@ public class UserManagerService extends IUserManager.Stub { return false; } } return !getDevicePolicyManagerInternal().isUserOrganizationManaged(userId); var dpmi = getDevicePolicyManagerInternal(); return dpmi == null || !dpmi.isUserOrganizationManaged(userId); } @Override Loading Loading @@ -7314,13 +7324,22 @@ public class UserManagerService extends IUserManager.Stub { mContext.sendBroadcastAsUser(intent, parentHandle, /* receiverPermission= */null); } private void sendManagedProfileRemovedBroadcast(int parentUserId, int removedUserId) { private void sendManagedProfileRemovedBroadcast(@UserIdInt int parentUserId, @UserIdInt int removedUserId) { var dpmi = getDevicePolicyManagerInternal(); if (dpmi == null) { // This should never happen (because current caller checks if removed used is of type // UserManager.USER_TYPE_PROFILE_MANAGED), but it doesn't hurt to check... Slogf.wtf(LOG_TAG, "sendManagedProfileRemovedBroadcast(parent=%d, removed=%d): ignoring" + " as device doesn't have DPMI", parentUserId, removedUserId); return; } Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED); managedProfileIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(removedUserId)); managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId); final UserHandle parentHandle = UserHandle.of(parentUserId); getDevicePolicyManagerInternal().broadcastIntentToManifestReceivers( managedProfileIntent, parentHandle, /* requiresPermission= */ false); dpmi.broadcastIntentToManifestReceivers(managedProfileIntent, parentHandle, /* requiresPermission= */ false); managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(managedProfileIntent, parentHandle, Loading @@ -7338,25 +7357,29 @@ public class UserManagerService extends IUserManager.Stub { || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) { checkSystemOrRoot("get application restrictions for other user/app " + packageName); } if (android.app.admin.flags.Flags.appRestrictionsCoexistence()) { List<Bundle> restrictions = getDevicePolicyManagerInternal().getApplicationRestrictionsPerAdminForUser( packageName, userId); if (restrictions.isEmpty()) { List<Bundle> restrictions = null; var dpmi = getDevicePolicyManagerInternal(); if (dpmi != null) { restrictions = dpmi.getApplicationRestrictionsPerAdminForUser(packageName, userId); } if (restrictions == null || restrictions.isEmpty()) { return Bundle.EMPTY; } else { if (restrictions.size() > 1) { Slog.w(LOG_TAG, "Application restriction list contains more than one element."); } int size = restrictions.size(); if (size > 1) { Slogf.w(LOG_TAG, "Application restriction list contains more than one (%d) element;" + " returning first", size); } return restrictions.getFirst(); } } else { synchronized (mAppRestrictionsLock) { // Read the restrictions from XML return readApplicationRestrictionsLAr(packageName, userId); } } } @Override public void setApplicationRestrictions(String packageName, Bundle restrictions, Loading Loading @@ -8961,8 +8984,13 @@ public class UserManagerService extends IUserManager.Stub { return mPmInternal; } /** Returns the internal device policy manager interface. */ private DevicePolicyManagerInternal getDevicePolicyManagerInternal() { /** * Returns the internal device policy manager interface. * * <p>NOTE: it's {@code null} when the device doesn't have the * {@code android.software.device_admin} feature. */ private @Nullable DevicePolicyManagerInternal getDevicePolicyManagerInternal() { if (mDevicePolicyManagerInternal == null) { mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class); Loading
services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceMockedTest.java +72 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.server.pm; import static android.app.admin.flags.Flags.FLAG_APP_RESTRICTIONS_COEXISTENCE; import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; import static android.content.pm.PackageManager.FEATURE_EMBEDDED; import static android.content.pm.PackageManager.FEATURE_LEANBACK; Loading Loading @@ -71,10 +72,12 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.KeyguardManager; import android.app.PropertyInvalidatedCache; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManagerInternal; import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.Bundle; import android.os.PowerManager; import android.os.ServiceSpecificException; import android.os.SystemProperties; Loading Loading @@ -206,6 +209,7 @@ public final class UserManagerServiceMockedTest { private @Mock StorageManager mStorageManager; private @Mock LockSettingsInternal mLockSettingsInternal; private @Mock PackageManagerInternal mPackageManagerInternal; private @Mock DevicePolicyManagerInternal mDevicePolicyManagerInternal; private @Mock KeyguardManager mKeyguardManager; private @Mock PowerManager mPowerManager; private @Mock TelecomManager mTelecomManager; Loading Loading @@ -1580,7 +1584,7 @@ public final class UserManagerServiceMockedTest { @EnableFlags(FLAG_DEMOTE_MAIN_USER) public void testSetMainUser_userNotFound() { assumeDoesntHaveMainUser(); int userId = 666; int userId = OTHER_USER_ID; expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isFalse(); Loading Loading @@ -1870,6 +1874,62 @@ public final class UserManagerServiceMockedTest { assertThat(mUsers.get(USER_ID).info.isAdmin()).isTrue(); } // NOTE: tests for getApplicationRestrictionsForUser were added to check when DPMI is null, so // they don't encompass all scenarios (like when FLAG_APP_RESTRICTIONS_COEXISTENCE is not set) @Test public void testGetApplicationRestrictionsForUser_invalidUser() { mockCallingUserId(USER_ID); assertThrows(SecurityException.class, () -> mUms .getApplicationRestrictionsForUser(mRealContext.getPackageName(), OTHER_USER_ID)); } @Test public void testGetApplicationRestrictionsForUser_differentPackage() { // Should throw because it's not the same as the calling uid package assertThrows(SecurityException.class, () -> mUms.getApplicationRestrictions("Age, the name is Pack Age")); } @Test @RequiresFlagsEnabled(FLAG_APP_RESTRICTIONS_COEXISTENCE) public void testGetApplicationRestrictionsForUser_flagEnabled_noDPMI() { mockGetLocalService(DevicePolicyManagerInternal.class, null); var result = mUms.getApplicationRestrictions(mRealContext.getPackageName()); assertThat(result).isSameInstanceAs(Bundle.EMPTY); } @Test @RequiresFlagsEnabled(FLAG_APP_RESTRICTIONS_COEXISTENCE) public void testGetApplicationRestrictionsForUser_flagEnabled_noRestrictions() { String pkg = mRealContext.getPackageName(); mockCallingUserId(USER_ID); mockDpmiGetApplicationRestrictionsPerAdminForUser(pkg, USER_ID); mockGetLocalService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); var result = mUms.getApplicationRestrictions(pkg); assertThat(result).isSameInstanceAs(Bundle.EMPTY); } @Test @RequiresFlagsEnabled(FLAG_APP_RESTRICTIONS_COEXISTENCE) public void testGetApplicationRestrictionsForUser_flagEnabled_multipleRestrictions() { String pkg = mRealContext.getPackageName(); Bundle bundle1 = new Bundle(); Bundle bundle2 = new Bundle(); mockCallingUserId(USER_ID); mockDpmiGetApplicationRestrictionsPerAdminForUser(pkg, USER_ID, bundle1, bundle2); mockGetLocalService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); var result = mUms.getApplicationRestrictions(pkg); assertThat(result).isSameInstanceAs(bundle1); } /** * Returns true if the user's XML file has Default restrictions * @param userId Id of the user. Loading Loading @@ -2024,6 +2084,17 @@ public final class UserManagerServiceMockedTest { doReturn(userId).when(UserHandle::getCallingUserId); } private void mockDpmiGetApplicationRestrictionsPerAdminForUser(String pkgName, @UserIdInt int userId, Bundle...bundles) { List<Bundle> list = Arrays.asList(bundles); Log.d(TAG, "mockDpmiGetApplicationRestrictionsPerAdminForAnyUser(" + pkgName + ", " + userId + "): will return " + list); when(mDevicePolicyManagerInternal .getApplicationRestrictionsPerAdminForUser(pkgName, userId)) .thenReturn(list); } private void expectUserJourneyLogged(@UserIdInt int userId, @UserJourney int journey) { verify(mUserJourneyLogger).logUserJourneyBegin(userId, journey); } Loading