Loading core/java/android/app/admin/DevicePolicyManager.java +28 −6 Original line number Diff line number Diff line Loading @@ -8497,6 +8497,11 @@ public class DevicePolicyManager { * From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use * {@link android.accounts.AccountManager} APIs to add or remove accounts when account * management for a specific type is disabled. * <p> * This method may be called on the {@code DevicePolicyManager} instance returned from * {@link #getParentProfileInstance(ComponentName)} by the profile owner on an * organization-owned device, to restrict accounts that may not be managed on the primary * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param accountType For which account management is disabled or enabled. Loading @@ -8506,10 +8511,10 @@ public class DevicePolicyManager { */ public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType, boolean disabled) { throwIfParentInstance("setAccountManagementDisabled"); if (mService != null) { try { mService.setAccountManagementDisabled(admin, accountType, disabled); mService.setAccountManagementDisabled(admin, accountType, disabled, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8517,28 +8522,43 @@ public class DevicePolicyManager { } /** * Gets the array of accounts for which account management is disabled by the profile owner. * Gets the array of accounts for which account management is disabled by the profile owner * or device owner. * * <p> Account management can be disabled/enabled by calling * {@link #setAccountManagementDisabled}. * <p> * This method may be called on the {@code DevicePolicyManager} instance returned from * {@link #getParentProfileInstance(ComponentName)}. Note that only a profile owner on * an organization-deviced can affect account types on the parent profile instance. * * @return a list of account types for which account management has been disabled. * * @see #setAccountManagementDisabled */ public @Nullable String[] getAccountTypesWithManagementDisabled() { throwIfParentInstance("getAccountTypesWithManagementDisabled"); return getAccountTypesWithManagementDisabledAsUser(myUserId()); return getAccountTypesWithManagementDisabledAsUser(myUserId(), mParentInstance); } /** * @see #getAccountTypesWithManagementDisabled() * Note that calling this method on the parent profile instance will return the same * value as calling it on the main {@code DevicePolicyManager} instance. * @hide */ public @Nullable String[] getAccountTypesWithManagementDisabledAsUser(int userId) { return getAccountTypesWithManagementDisabledAsUser(userId, false); } /** * @see #getAccountTypesWithManagementDisabled() * @hide */ public @Nullable String[] getAccountTypesWithManagementDisabledAsUser( int userId, boolean parentInstance) { if (mService != null) { try { return mService.getAccountTypesWithManagementDisabledAsUser(userId); return mService.getAccountTypesWithManagementDisabledAsUser(userId, parentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -9876,6 +9896,7 @@ public class DevicePolicyManager { * <li>{@link #setTrustAgentConfiguration}</li> * <li>{@link #getRequiredStrongAuthTimeout}</li> * <li>{@link #setRequiredStrongAuthTimeout}</li> * <li>{@link #getAccountTypesWithManagementDisabled}</li> * </ul> * <p> * The following methods are supported for the parent instance but can only be called by the Loading @@ -9884,6 +9905,7 @@ public class DevicePolicyManager { * <li>{@link #getPasswordComplexity}</li> * <li>{@link #setCameraDisabled}</li> * <li>{@link #getCameraDisabled}</li> * <li>{@link #setAccountManagementDisabled(ComponentName, String, boolean)}</li> * </ul> * * <p>The following methods can be called by the profile owner of a managed profile Loading core/java/android/app/admin/IDevicePolicyManager.aidl +2 −2 Original line number Diff line number Diff line Loading @@ -248,9 +248,9 @@ interface IDevicePolicyManager { int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled, in boolean parent); String[] getAccountTypesWithManagementDisabled(); String[] getAccountTypesWithManagementDisabledAsUser(int userId); String[] getAccountTypesWithManagementDisabledAsUser(int userId, in boolean parent); void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled); boolean isSecondaryLockscreenEnabled(int userId); Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +29 −10 Original line number Diff line number Diff line Loading @@ -11055,14 +11055,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setAccountManagementDisabled(ComponentName who, String accountType, boolean disabled) { boolean disabled, boolean parent) { if (!mHasFeature) { return; } Objects.requireNonNull(who, "ComponentName is null"); synchronized (getLockObject()) { /* * When called on the parent DPM instance (parent == true), affects active admin * selection in two ways: * * The ActiveAdmin must be of an org-owned profile owner. * * The parent ActiveAdmin instance should be used for managing the restriction. */ ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); parent ? DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER : DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent); if (disabled) { ap.accountTypesWithManagementDisabled.add(accountType); } else { Loading @@ -11074,23 +11081,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public String[] getAccountTypesWithManagementDisabled() { return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId()); return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId(), false); } @Override public String[] getAccountTypesWithManagementDisabledAsUser(int userId) { public String[] getAccountTypesWithManagementDisabledAsUser(int userId, boolean parent) { enforceFullCrossUsersPermission(userId); if (!mHasFeature) { return null; } synchronized (getLockObject()) { DevicePolicyData policy = getUserData(userId); final int N = policy.mAdminList.size(); ArraySet<String> resultSet = new ArraySet<>(); for (int i = 0; i < N; i++) { ActiveAdmin admin = policy.mAdminList.get(i); final ArraySet<String> resultSet = new ArraySet<>(); if (!parent) { final DevicePolicyData policy = getUserData(userId); for (ActiveAdmin admin : policy.mAdminList) { resultSet.addAll(admin.accountTypesWithManagementDisabled); } } // Check if there's a profile owner of an org-owned device and the method is called for // the parent user of this profile owner. final ActiveAdmin orgOwnedAdmin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); final boolean shouldGetParentAccounts = orgOwnedAdmin != null && (parent || UserHandle.getUserId(orgOwnedAdmin.getUid()) != userId); if (shouldGetParentAccounts) { resultSet.addAll( orgOwnedAdmin.getParentActiveAdmin().accountTypesWithManagementDisabled); } return resultSet.toArray(new String[resultSet.size()]); } } Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +49 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,6 @@ import android.test.MoreAsserts; import android.util.ArraySet; import android.util.Pair; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.internal.R; Loading Loading @@ -6058,6 +6057,55 @@ public class DevicePolicyManagerTest extends DpmTestBase { .thenReturn(packages); } public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception { setupProfileOwner(); final String accountType = "com.example.account.type"; int originalUid = mContext.binder.callingUid; dpm.setAccountManagementDisabled(admin1, accountType, true); assertThat(dpm.getAccountTypesWithManagementDisabled()).asList().containsExactly( accountType); mContext.binder.callingUid = DpmMockContext.ANOTHER_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = originalUid; dpm.setAccountManagementDisabled(admin1, accountType, false); assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); } public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile() throws Exception { final int managedProfileUserId = 15; final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); addManagedProfile(admin1, managedProfileAdminUid, admin1); mContext.binder.callingUid = managedProfileAdminUid; configureProfileOwnerOfOrgOwnedDevice(admin1, managedProfileUserId); int originalUid = mContext.binder.callingUid; final String accountType = "com.example.account.type"; dpm.getParentProfileInstance(admin1).setAccountManagementDisabled(admin1, accountType, true); assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = DpmMockContext.ANOTHER_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).asList().containsExactly( accountType); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).asList().containsExactly( accountType); mContext.binder.callingUid = originalUid; dpm.getParentProfileInstance(admin1).setAccountManagementDisabled(admin1, accountType, false); mContext.binder.callingUid = DpmMockContext.ANOTHER_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); } // admin1 is the outgoing DPC, adminAnotherPakcage is the incoming one. private void assertDeviceOwnershipRevertedWithFakeTransferMetadata() throws Exception { writeFakeTransferMetadataFile(UserHandle.USER_SYSTEM, Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +28 −6 Original line number Diff line number Diff line Loading @@ -8497,6 +8497,11 @@ public class DevicePolicyManager { * From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use * {@link android.accounts.AccountManager} APIs to add or remove accounts when account * management for a specific type is disabled. * <p> * This method may be called on the {@code DevicePolicyManager} instance returned from * {@link #getParentProfileInstance(ComponentName)} by the profile owner on an * organization-owned device, to restrict accounts that may not be managed on the primary * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param accountType For which account management is disabled or enabled. Loading @@ -8506,10 +8511,10 @@ public class DevicePolicyManager { */ public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType, boolean disabled) { throwIfParentInstance("setAccountManagementDisabled"); if (mService != null) { try { mService.setAccountManagementDisabled(admin, accountType, disabled); mService.setAccountManagementDisabled(admin, accountType, disabled, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8517,28 +8522,43 @@ public class DevicePolicyManager { } /** * Gets the array of accounts for which account management is disabled by the profile owner. * Gets the array of accounts for which account management is disabled by the profile owner * or device owner. * * <p> Account management can be disabled/enabled by calling * {@link #setAccountManagementDisabled}. * <p> * This method may be called on the {@code DevicePolicyManager} instance returned from * {@link #getParentProfileInstance(ComponentName)}. Note that only a profile owner on * an organization-deviced can affect account types on the parent profile instance. * * @return a list of account types for which account management has been disabled. * * @see #setAccountManagementDisabled */ public @Nullable String[] getAccountTypesWithManagementDisabled() { throwIfParentInstance("getAccountTypesWithManagementDisabled"); return getAccountTypesWithManagementDisabledAsUser(myUserId()); return getAccountTypesWithManagementDisabledAsUser(myUserId(), mParentInstance); } /** * @see #getAccountTypesWithManagementDisabled() * Note that calling this method on the parent profile instance will return the same * value as calling it on the main {@code DevicePolicyManager} instance. * @hide */ public @Nullable String[] getAccountTypesWithManagementDisabledAsUser(int userId) { return getAccountTypesWithManagementDisabledAsUser(userId, false); } /** * @see #getAccountTypesWithManagementDisabled() * @hide */ public @Nullable String[] getAccountTypesWithManagementDisabledAsUser( int userId, boolean parentInstance) { if (mService != null) { try { return mService.getAccountTypesWithManagementDisabledAsUser(userId); return mService.getAccountTypesWithManagementDisabledAsUser(userId, parentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -9876,6 +9896,7 @@ public class DevicePolicyManager { * <li>{@link #setTrustAgentConfiguration}</li> * <li>{@link #getRequiredStrongAuthTimeout}</li> * <li>{@link #setRequiredStrongAuthTimeout}</li> * <li>{@link #getAccountTypesWithManagementDisabled}</li> * </ul> * <p> * The following methods are supported for the parent instance but can only be called by the Loading @@ -9884,6 +9905,7 @@ public class DevicePolicyManager { * <li>{@link #getPasswordComplexity}</li> * <li>{@link #setCameraDisabled}</li> * <li>{@link #getCameraDisabled}</li> * <li>{@link #setAccountManagementDisabled(ComponentName, String, boolean)}</li> * </ul> * * <p>The following methods can be called by the profile owner of a managed profile Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +2 −2 Original line number Diff line number Diff line Loading @@ -248,9 +248,9 @@ interface IDevicePolicyManager { int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled, in boolean parent); String[] getAccountTypesWithManagementDisabled(); String[] getAccountTypesWithManagementDisabledAsUser(int userId); String[] getAccountTypesWithManagementDisabledAsUser(int userId, in boolean parent); void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled); boolean isSecondaryLockscreenEnabled(int userId); Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +29 −10 Original line number Diff line number Diff line Loading @@ -11055,14 +11055,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setAccountManagementDisabled(ComponentName who, String accountType, boolean disabled) { boolean disabled, boolean parent) { if (!mHasFeature) { return; } Objects.requireNonNull(who, "ComponentName is null"); synchronized (getLockObject()) { /* * When called on the parent DPM instance (parent == true), affects active admin * selection in two ways: * * The ActiveAdmin must be of an org-owned profile owner. * * The parent ActiveAdmin instance should be used for managing the restriction. */ ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); parent ? DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER : DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent); if (disabled) { ap.accountTypesWithManagementDisabled.add(accountType); } else { Loading @@ -11074,23 +11081,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public String[] getAccountTypesWithManagementDisabled() { return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId()); return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId(), false); } @Override public String[] getAccountTypesWithManagementDisabledAsUser(int userId) { public String[] getAccountTypesWithManagementDisabledAsUser(int userId, boolean parent) { enforceFullCrossUsersPermission(userId); if (!mHasFeature) { return null; } synchronized (getLockObject()) { DevicePolicyData policy = getUserData(userId); final int N = policy.mAdminList.size(); ArraySet<String> resultSet = new ArraySet<>(); for (int i = 0; i < N; i++) { ActiveAdmin admin = policy.mAdminList.get(i); final ArraySet<String> resultSet = new ArraySet<>(); if (!parent) { final DevicePolicyData policy = getUserData(userId); for (ActiveAdmin admin : policy.mAdminList) { resultSet.addAll(admin.accountTypesWithManagementDisabled); } } // Check if there's a profile owner of an org-owned device and the method is called for // the parent user of this profile owner. final ActiveAdmin orgOwnedAdmin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); final boolean shouldGetParentAccounts = orgOwnedAdmin != null && (parent || UserHandle.getUserId(orgOwnedAdmin.getUid()) != userId); if (shouldGetParentAccounts) { resultSet.addAll( orgOwnedAdmin.getParentActiveAdmin().accountTypesWithManagementDisabled); } return resultSet.toArray(new String[resultSet.size()]); } } Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +49 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,6 @@ import android.test.MoreAsserts; import android.util.ArraySet; import android.util.Pair; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.internal.R; Loading Loading @@ -6058,6 +6057,55 @@ public class DevicePolicyManagerTest extends DpmTestBase { .thenReturn(packages); } public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception { setupProfileOwner(); final String accountType = "com.example.account.type"; int originalUid = mContext.binder.callingUid; dpm.setAccountManagementDisabled(admin1, accountType, true); assertThat(dpm.getAccountTypesWithManagementDisabled()).asList().containsExactly( accountType); mContext.binder.callingUid = DpmMockContext.ANOTHER_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = originalUid; dpm.setAccountManagementDisabled(admin1, accountType, false); assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); } public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile() throws Exception { final int managedProfileUserId = 15; final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436); addManagedProfile(admin1, managedProfileAdminUid, admin1); mContext.binder.callingUid = managedProfileAdminUid; configureProfileOwnerOfOrgOwnedDevice(admin1, managedProfileUserId); int originalUid = mContext.binder.callingUid; final String accountType = "com.example.account.type"; dpm.getParentProfileInstance(admin1).setAccountManagementDisabled(admin1, accountType, true); assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = DpmMockContext.ANOTHER_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).asList().containsExactly( accountType); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).asList().containsExactly( accountType); mContext.binder.callingUid = originalUid; dpm.getParentProfileInstance(admin1).setAccountManagementDisabled(admin1, accountType, false); mContext.binder.callingUid = DpmMockContext.ANOTHER_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty(); } // admin1 is the outgoing DPC, adminAnotherPakcage is the incoming one. private void assertDeviceOwnershipRevertedWithFakeTransferMetadata() throws Exception { writeFakeTransferMetadataFile(UserHandle.USER_SYSTEM, Loading