Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50495dd8 authored by Pavel Grafov's avatar Pavel Grafov Committed by Android (Google) Code Review
Browse files

Merge "Allow control over account management of parent profile"

parents 5cbf58e3 65d94931
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -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.
@@ -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();
            }
@@ -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();
            }
@@ -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
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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);
+29 −10
Original line number Diff line number Diff line
@@ -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 {
@@ -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()]);
        }
    }
+49 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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,