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

Commit f1fdb580 authored by Jonathan Scott's avatar Jonathan Scott
Browse files

Update DO and role holder requirements to block if there are accounts on

any user.

Test: btest a.d.c.DeviceOwnerTest
Test: btest a.d.c.ProfileOwnerTest
Test: btest a.d.c.DevicePolicyManagementRoleHolderTest
Bug: 256655297
Change-Id: Ib0e872a4c2725ff10a4912cd43fbcd7174cbe2f6
parent e3e1d327
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -528,6 +528,7 @@ package android.app.admin {
    method @NonNull public static String operationSafetyReasonToString(int);
    method @NonNull public static String operationToString(int);
    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void resetDefaultCrossProfileIntentFilters(int);
    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
    method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int);
    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwner(@NonNull android.content.ComponentName, int);
    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, int);
+24 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.app.admin;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
@@ -4186,7 +4187,7 @@ public class DevicePolicyManager {
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
    @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
    public boolean packageHasActiveAdmins(String packageName) {
        return packageHasActiveAdmins(packageName, myUserId());
    }
@@ -8743,7 +8744,7 @@ public class DevicePolicyManager {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    @RequiresPermission(allOf = {
            android.Manifest.permission.MANAGE_DEVICE_ADMINS,
            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
            INTERACT_ACROSS_USERS_FULL
    })
    public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
            int userHandle) {
@@ -10654,7 +10655,7 @@ public class DevicePolicyManager {
     */
    @UserHandleAware
    @RequiresPermission(allOf = {
            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
            INTERACT_ACROSS_USERS_FULL,
            android.Manifest.permission.MANAGE_USERS
            }, conditional = true)
    public @Nullable List<String> getPermittedInputMethods() {
@@ -14845,7 +14846,7 @@ public class DevicePolicyManager {
     * @hide
     */
    @RequiresPermission(anyOf = {
            permission.INTERACT_ACROSS_USERS_FULL,
            INTERACT_ACROSS_USERS_FULL,
            permission.INTERACT_ACROSS_USERS
    }, conditional = true)
    public boolean isPackageAllowedToAccessCalendar(@NonNull  String packageName) {
@@ -14877,7 +14878,7 @@ public class DevicePolicyManager {
     * @hide
     */
    @RequiresPermission(anyOf = {
            permission.INTERACT_ACROSS_USERS_FULL,
            INTERACT_ACROSS_USERS_FULL,
            permission.INTERACT_ACROSS_USERS
    })
    public @Nullable Set<String> getCrossProfileCalendarPackages() {
@@ -14970,7 +14971,7 @@ public class DevicePolicyManager {
     * @hide
     */
    @RequiresPermission(anyOf = {
            permission.INTERACT_ACROSS_USERS_FULL,
            INTERACT_ACROSS_USERS_FULL,
            permission.INTERACT_ACROSS_USERS,
            permission.INTERACT_ACROSS_PROFILES
    })
@@ -16153,6 +16154,23 @@ public class DevicePolicyManager {
        return deviceManagerConfig;
    }
    /**
     * Reset cache for {@link #shouldAllowBypassingDevicePolicyManagementRoleQualification}.
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)
    public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState() {
        if (mService != null) {
            try {
                mService.resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
    /**
     * @return {@code true} if bypassing the device policy management role qualification is allowed
     * with the current state of the device.
+1 −0
Original line number Diff line number Diff line
@@ -575,6 +575,7 @@ interface IDevicePolicyManager {
    void resetStrings(in List<String> stringIds);
    ParcelableResource getString(String stringId);

    void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
    boolean shouldAllowBypassingDevicePolicyManagementRoleQualification();

    List<UserHandle> getPolicyManagedProfiles(in UserHandle userHandle);
+67 −11
Original line number Diff line number Diff line
@@ -8597,9 +8597,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Preconditions.checkArgument(admin != null);
        final CallerIdentity caller = getCallerIdentity();
        // Cannot be called while holding the lock:
        final boolean hasIncompatibleAccountsOrNonAdb =
                hasIncompatibleAccountsOrNonAdbNoLock(caller, userId, admin);
        boolean hasIncompatibleAccountsOrNonAdb =
                !isAdb(caller) || hasIncompatibleAccountsOnAnyUser();
        if (!hasIncompatibleAccountsOrNonAdb) {
            synchronized (getLockObject()) {
                if (!isAdminTestOnlyLocked(admin, userId) && hasAccountsOnAnyUser()) {
                    Slogf.w(LOG_TAG,
                            "Non test-only owner can't be installed with existing accounts.");
                    return false;
                }
            }
        }
        synchronized (getLockObject()) {
            enforceCanSetDeviceOwnerLocked(caller, admin, userId, hasIncompatibleAccountsOrNonAdb);
            Preconditions.checkArgument(isPackageInstalledForUser(admin.getPackageName(), userId),
@@ -14784,7 +14795,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
     */
    private boolean nonTestNonPrecreatedUsersExist() {
        int allowedUsers = UserManager.isHeadlessSystemUserMode() ? 2 : 1;
        return mUserManagerInternal.getUsers(/* excludeDying= */ true).stream()
                .filter(u -> !u.isForTesting())
                .count() > allowedUsers;
@@ -16061,8 +16071,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        wtfIfInLock();
        return mInjector.binderWithCleanCallingIdentity(() -> {
            final AccountManager am = AccountManager.get(mContext);
            final Account accounts[] = am.getAccountsAsUser(userId);
            AccountManager am =
                    mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0)
                            .getSystemService(AccountManager.class);
            Account[] accounts = am.getAccounts();
            if (accounts.length == 0) {
                return false;
            }
@@ -19540,6 +19552,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                mContext.getContentResolver(), MANAGED_PROVISIONING_DPC_DOWNLOADED, setTo));
    }
    @Override
    public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState() {
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
                android.Manifest.permission.MANAGE_ROLE_HOLDERS));
        setBypassDevicePolicyManagementRoleQualificationStateInternal(
                /* currentRoleHolder= */ null, /* allowBypass= */ false);
    }
    @Override
    public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() {
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
@@ -19557,12 +19577,48 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        if (nonTestNonPrecreatedUsersExist()) {
            return false;
        }
        AccountManager am = AccountManager.get(mContext);
        return !hasIncompatibleAccountsOnAnyUser();
    }
    private boolean hasAccountsOnAnyUser() {
        long callingIdentity = Binder.clearCallingIdentity();
        try {
            for (UserInfo user : mUserManagerInternal.getUsers(/* excludeDying= */ true)) {
                AccountManager am = mContext.createContextAsUser(
                                UserHandle.of(user.id), /* flags= */ 0)
                        .getSystemService(AccountManager.class);
                Account[] accounts = am.getAccounts();
                if (accounts.length != 0) {
                    return true;
                }
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(callingIdentity);
        }
    }
    private boolean hasIncompatibleAccountsOnAnyUser() {
        long callingIdentity = Binder.clearCallingIdentity();
        try {
            for (UserInfo user : mUserManagerInternal.getUsers(/* excludeDying= */ true)) {
                AccountManager am = mContext.createContextAsUser(
                        UserHandle.of(user.id), /* flags= */ 0)
                        .getSystemService(AccountManager.class);
                Account[] accounts = am.getAccounts();
        if (accounts.length == 0) {
                if (hasIncompatibleAccounts(am, accounts)) {
                    return true;
                }
        return !hasIncompatibleAccounts(am, accounts);
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(callingIdentity);
        }
    }
    private void setBypassDevicePolicyManagementRoleQualificationStateInternal(