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

Commit d85eec87 authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "Don't call DPM from UserManager to avoid lock inversion"

parents f20528b4 e7927da1
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -69,4 +69,16 @@ public abstract class UserManagerInternal {


    /** Remove a {@link UserRestrictionsListener}. */
    /** Remove a {@link UserRestrictionsListener}. */
    public abstract void removeUserRestrictionsListener(UserRestrictionsListener listener);
    public abstract void removeUserRestrictionsListener(UserRestrictionsListener listener);

    /**
     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update
     * whether the device is managed by device owner.
     */
    public abstract void setDeviceManaged(boolean isManaged);

    /**
     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update
     * whether the user is managed by profile owner.
     */
    public abstract void setUserManaged(int userId, boolean isManaged);
}
}
+45 −14
Original line number Original line Diff line number Diff line
@@ -24,7 +24,6 @@ import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
import android.app.IStopUserCallback;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
@@ -216,14 +215,15 @@ public class UserManagerService extends IUserManager.Stub {
    private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
    private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();


    /**
    /**
     * User restrictions set by {@link DevicePolicyManager} that should be applied to all users,
     * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
     * including guests.
     * that should be applied to all users, including guests.
     */
     */
    @GuardedBy("mRestrictionsLock")
    @GuardedBy("mRestrictionsLock")
    private Bundle mDevicePolicyGlobalUserRestrictions;
    private Bundle mDevicePolicyGlobalUserRestrictions;


    /**
    /**
     * User restrictions set by {@link DevicePolicyManager} for each user.
     * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
     * for each user.
     */
     */
    @GuardedBy("mRestrictionsLock")
    @GuardedBy("mRestrictionsLock")
    private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
    private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
@@ -248,6 +248,12 @@ public class UserManagerService extends IUserManager.Stub {


    private final LocalService mLocalService;
    private final LocalService mLocalService;


    @GuardedBy("mUsersLock")
    private boolean mIsDeviceManaged;

    @GuardedBy("mUsersLock")
    private final SparseBooleanArray mIsUserManaged = new SparseBooleanArray();

    @GuardedBy("mUserRestrictionsListeners")
    @GuardedBy("mUserRestrictionsListeners")
    private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
    private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
            new ArrayList<>();
            new ArrayList<>();
@@ -509,11 +515,9 @@ public class UserManagerService extends IUserManager.Stub {
            if (!userInfo.isAdmin()) {
            if (!userInfo.isAdmin()) {
                return false;
                return false;
            }
            }
            // restricted profile can be created if there is no DO set and the admin user has no PO;
            return !mIsDeviceManaged && !mIsUserManaged.get(userId);
        }
        }
        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
                Context.DEVICE_POLICY_SERVICE);
        // restricted profile can be created if there is no DO set and the admin user has no PO
        return !dpm.isDeviceManaged() && dpm.getProfileOwnerAsUser(userId) == null;
    }
    }


    /*
    /*
@@ -1596,13 +1600,12 @@ public class UserManagerService extends IUserManager.Stub {
                if (UserManager.isSplitSystemUser()
                if (UserManager.isSplitSystemUser()
                        && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
                        && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
                    flags |= UserInfo.FLAG_PRIMARY;
                    flags |= UserInfo.FLAG_PRIMARY;
                    DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
                    synchronized (mUsersLock) {
                            mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
                        if (!mIsDeviceManaged) {
                    if (devicePolicyManager == null
                            || !devicePolicyManager.isDeviceManaged()) {
                            flags |= UserInfo.FLAG_ADMIN;
                            flags |= UserInfo.FLAG_ADMIN;
                        }
                        }
                    }
                    }
                }
                userId = getNextAvailableId();
                userId = getNextAvailableId();
                userInfo = new UserInfo(userId, name, null, flags);
                userInfo = new UserInfo(userId, name, null, flags);
                userInfo.serialNumber = mNextSerialNumber++;
                userInfo.serialNumber = mNextSerialNumber++;
@@ -1865,6 +1868,13 @@ public class UserManagerService extends IUserManager.Stub {
        // Remove this user from the list
        // Remove this user from the list
        synchronized (mUsersLock) {
        synchronized (mUsersLock) {
            mUsers.remove(userHandle);
            mUsers.remove(userHandle);
            mIsUserManaged.delete(userHandle);
        }
        synchronized (mRestrictionsLock) {
            mBaseUserRestrictions.remove(userHandle);
            mAppliedUserRestrictions.remove(userHandle);
            mCachedEffectiveUserRestrictions.remove(userHandle);
            mDevicePolicyLocalUserRestrictions.remove(userHandle);
        }
        }
        // Remove user file
        // Remove user file
        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
@@ -2376,9 +2386,10 @@ public class UserManagerService extends IUserManager.Stub {
                    if (user == null) {
                    if (user == null) {
                        continue;
                        continue;
                    }
                    }
                    final int userId = user.id;
                    pw.print("  "); pw.print(user);
                    pw.print("  "); pw.print(user);
                    pw.print(" serialNo="); pw.print(user.serialNumber);
                    pw.print(" serialNo="); pw.print(user.serialNumber);
                    if (mRemovingUserIds.get(mUsers.keyAt(i))) {
                    if (mRemovingUserIds.get(userId)) {
                        pw.print(" <removing> ");
                        pw.print(" <removing> ");
                    }
                    }
                    if (user.partial) {
                    if (user.partial) {
@@ -2403,6 +2414,8 @@ public class UserManagerService extends IUserManager.Stub {
                        sb.append(" ago");
                        sb.append(" ago");
                        pw.println(sb);
                        pw.println(sb);
                    }
                    }
                    pw.print("    Has profile owner: ");
                    pw.println(mIsUserManaged.get(userId));
                    pw.println("    Restrictions:");
                    pw.println("    Restrictions:");
                    synchronized (mRestrictionsLock) {
                    synchronized (mRestrictionsLock) {
                        UserRestrictionsUtils.dumpRestrictions(
                        UserRestrictionsUtils.dumpRestrictions(
@@ -2427,6 +2440,10 @@ public class UserManagerService extends IUserManager.Stub {
            synchronized (mGuestRestrictions) {
            synchronized (mGuestRestrictions) {
                UserRestrictionsUtils.dumpRestrictions(pw, "    ", mGuestRestrictions);
                UserRestrictionsUtils.dumpRestrictions(pw, "    ", mGuestRestrictions);
            }
            }
            synchronized (mUsersLock) {
                pw.println();
                pw.println("  Device managed: " + mIsDeviceManaged);
            }
        }
        }
    }
    }


@@ -2507,6 +2524,20 @@ public class UserManagerService extends IUserManager.Stub {
                mUserRestrictionsListeners.remove(listener);
                mUserRestrictionsListeners.remove(listener);
            }
            }
        }
        }

        @Override
        public void setDeviceManaged(boolean isManaged) {
            synchronized (mUsersLock) {
                mIsDeviceManaged = isManaged;
            }
        }

        @Override
        public void setUserManaged(int userId, boolean isManaged) {
            synchronized (mUsersLock) {
                mIsUserManaged.put(userId, isManaged);
            }
        }
    }
    }


    private class Shell extends ShellCommand {
    private class Shell extends ShellCommand {
+40 −32
Original line number Original line Diff line number Diff line
@@ -1071,7 +1071,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        }


        Owners newOwners() {
        Owners newOwners() {
            return new Owners(mContext);
            return new Owners(mContext, getUserManager(), getUserManagerInternal());
        }
        }


        UserManager getUserManager() {
        UserManager getUserManager() {
@@ -2150,8 +2150,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    }


    private void ensureDeviceOwnerUserStarted() {
    private void ensureDeviceOwnerUserStarted() {
        if (mOwners.hasDeviceOwner()) {
        final int userId;
            final int userId = mOwners.getDeviceOwnerUserId();
        synchronized (this) {
            if (!mOwners.hasDeviceOwner()) {
                return;
            }
            userId = mOwners.getDeviceOwnerUserId();
        }
        if (VERBOSE_LOG) {
        if (VERBOSE_LOG) {
            Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
            Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
        }
        }
@@ -2166,7 +2171,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            }
        }
        }
    }
    }
    }


    private void onStartUser(int userId) {
    private void onStartUser(int userId) {
        updateScreenCaptureDisabledInWindowManager(userId,
        updateScreenCaptureDisabledInWindowManager(userId,
@@ -4584,7 +4588,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    + " for device owner");
                    + " for device owner");
        }
        }
        synchronized (this) {
        synchronized (this) {
            enforceCanSetDeviceOwner(userId);
            enforceCanSetDeviceOwnerLocked(userId);


            // Shutting down backup manager service permanently.
            // Shutting down backup manager service permanently.
            long ident = mInjector.binderClearCallingIdentity();
            long ident = mInjector.binderClearCallingIdentity();
@@ -4751,7 +4755,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    + " not installed for userId:" + userHandle);
                    + " not installed for userId:" + userHandle);
        }
        }
        synchronized (this) {
        synchronized (this) {
            enforceCanSetProfileOwner(userHandle);
            enforceCanSetProfileOwnerLocked(userHandle);
            mOwners.setProfileOwner(who, ownerName, userHandle);
            mOwners.setProfileOwner(who, ownerName, userHandle);
            mOwners.writeProfileOwner(userHandle);
            mOwners.writeProfileOwner(userHandle);
            return true;
            return true;
@@ -4953,7 +4957,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     * - SYSTEM_UID
     * - SYSTEM_UID
     * - adb if there are not accounts.
     * - adb if there are not accounts.
     */
     */
    private void enforceCanSetProfileOwner(int userHandle) {
    private void enforceCanSetProfileOwnerLocked(int userHandle) {
        UserInfo info = mUserManager.getUserInfo(userHandle);
        UserInfo info = mUserManager.getUserInfo(userHandle);
        if (info == null) {
        if (info == null) {
            // User doesn't exist.
            // User doesn't exist.
@@ -4995,7 +4999,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     * The device owner can only be set before the setup phase of the primary user has completed,
     * The device owner can only be set before the setup phase of the primary user has completed,
     * except for adb if no accounts or additional users are present on the device.
     * except for adb if no accounts or additional users are present on the device.
     */
     */
    private void enforceCanSetDeviceOwner(int userId) {
    private void enforceCanSetDeviceOwnerLocked(int userId) {
        if (mOwners.hasDeviceOwner()) {
        if (mOwners.hasDeviceOwner()) {
            throw new IllegalStateException("Trying to set the device owner, but device owner "
            throw new IllegalStateException("Trying to set the device owner, but device owner "
                    + "is already set.");
                    + "is already set.");
@@ -6819,6 +6823,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    public boolean isProvisioningAllowed(String action) {
    public boolean isProvisioningAllowed(String action) {
        final int callingUserId = mInjector.userHandleGetCallingUserId();
        final int callingUserId = mInjector.userHandleGetCallingUserId();
        if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
        if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
            synchronized (this) {
                if (mOwners.hasDeviceOwner()) {
                if (mOwners.hasDeviceOwner()) {
                    if (!mInjector.userManagerIsSplitSystemUser()) {
                    if (!mInjector.userManagerIsSplitSystemUser()) {
                        // Only split-system-user systems support managed-profiles in combination with
                        // Only split-system-user systems support managed-profiles in combination with
@@ -6835,6 +6840,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        return false;
                        return false;
                    }
                    }
                }
                }
            }
            if (getProfileOwner(callingUserId) != null) {
            if (getProfileOwner(callingUserId) != null) {
                // Managed user cannot have a managed profile.
                // Managed user cannot have a managed profile.
                return false;
                return false;
@@ -6877,9 +6883,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    }


    private boolean isDeviceOwnerProvisioningAllowed(int callingUserId) {
    private boolean isDeviceOwnerProvisioningAllowed(int callingUserId) {
        synchronized (this) {
            if (mOwners.hasDeviceOwner()) {
            if (mOwners.hasDeviceOwner()) {
                return false;
                return false;
            }
            }
        }
        if (getProfileOwner(callingUserId) != null) {
        if (getProfileOwner(callingUserId) != null) {
            return false;
            return false;
        }
        }
+43 −29
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.Environment;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Log;
@@ -50,6 +51,9 @@ import libcore.io.IoUtils;
/**
/**
 * Stores and restores state for the Device and Profile owners. By definition there can be
 * Stores and restores state for the Device and Profile owners. By definition there can be
 * only one device owner, but there may be a profile owner for each user.
 * only one device owner, but there may be a profile owner for each user.
 *
 * <p>This class is not thread safe.  (i.e. access to this class must always be synchronized
 * in the caller side.)
 */
 */
class Owners {
class Owners {
    private static final String TAG = "DevicePolicyManagerService";
    private static final String TAG = "DevicePolicyManagerService";
@@ -78,8 +82,8 @@ class Owners {


    private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy";
    private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy";


    private final Context mContext;
    private final UserManager mUserManager;
    private final UserManager mUserManager;
    private final UserManagerInternal mUserManagerInternal;


    // Internal state for the device owner package.
    // Internal state for the device owner package.
    private OwnerInfo mDeviceOwner;
    private OwnerInfo mDeviceOwner;
@@ -92,19 +96,21 @@ class Owners {
    // Local system update policy controllable by device owner.
    // Local system update policy controllable by device owner.
    private SystemUpdatePolicy mSystemUpdatePolicy;
    private SystemUpdatePolicy mSystemUpdatePolicy;


    public Owners(Context context) {
    public Owners(Context context, UserManager userManager,
        mContext = context;
            UserManagerInternal userManagerInternal) {
        mUserManager = context.getSystemService(UserManager.class);
        mUserManager = userManager;
        mUserManagerInternal = userManagerInternal;
    }
    }


    /**
    /**
     * Load configuration from the disk.
     * Load configuration from the disk.
     */
     */
    void load() {
    void load() {
        synchronized (this) {
        // First, try to read from the legacy file.
        // First, try to read from the legacy file.
        final File legacy = getLegacyConfigFileWithTestOverride();
        final File legacy = getLegacyConfigFileWithTestOverride();


        final List<UserInfo> users = mUserManager.getUsers();

        if (readLegacyOwnerFile(legacy)) {
        if (readLegacyOwnerFile(legacy)) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "Legacy config file found.");
                Log.d(TAG, "Legacy config file found.");
@@ -125,11 +131,13 @@ class Owners {
            // No legacy file, read from the new format files.
            // No legacy file, read from the new format files.
            new DeviceOwnerReadWriter().readFromFileLocked();
            new DeviceOwnerReadWriter().readFromFileLocked();


                final List<UserInfo> users = mUserManager.getUsers();
            for (UserInfo ui : users) {
            for (UserInfo ui : users) {
                new ProfileOwnerReadWriter(ui.id).readFromFileLocked();
                new ProfileOwnerReadWriter(ui.id).readFromFileLocked();
            }
            }
        }
        }
        mUserManagerInternal.setDeviceManaged(hasDeviceOwner());
        for (UserInfo ui : users) {
            mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id));
        }
        }
        if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) {
        if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) {
            Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
            Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
@@ -169,21 +177,27 @@ class Owners {
            boolean userRestrictionsMigrated) {
            boolean userRestrictionsMigrated) {
        mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated);
        mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated);
        mDeviceOwnerUserId = userId;
        mDeviceOwnerUserId = userId;

        mUserManagerInternal.setDeviceManaged(true);
    }
    }


    void clearDeviceOwner() {
    void clearDeviceOwner() {
        mDeviceOwner = null;
        mDeviceOwner = null;
        mDeviceOwnerUserId = UserHandle.USER_NULL;
        mDeviceOwnerUserId = UserHandle.USER_NULL;

        mUserManagerInternal.setDeviceManaged(false);
    }
    }


    void setProfileOwner(ComponentName admin, String ownerName, int userId) {
    void setProfileOwner(ComponentName admin, String ownerName, int userId) {
        // For a newly set PO, there's no need for migration.
        // For a newly set PO, there's no need for migration.
        mProfileOwners.put(userId, new OwnerInfo(ownerName, admin,
        mProfileOwners.put(userId, new OwnerInfo(ownerName, admin,
                /* userRestrictionsMigrated =*/ true));
                /* userRestrictionsMigrated =*/ true));
        mUserManagerInternal.setUserManaged(userId, true);
    }
    }


    void removeProfileOwner(int userId) {
    void removeProfileOwner(int userId) {
        mProfileOwners.remove(userId);
        mProfileOwners.remove(userId);
        mUserManagerInternal.setUserManaged(userId, false);
    }
    }


    ComponentName getProfileOwnerComponent(int userId) {
    ComponentName getProfileOwnerComponent(int userId) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -52,7 +52,7 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
        private final File mProfileOwnerBase;
        private final File mProfileOwnerBase;


        public OwnersTestable(DpmMockContext context) {
        public OwnersTestable(DpmMockContext context) {
            super(context);
            super(context, context.userManager, context.userManagerInternal);
            mLegacyFile = new File(context.dataDir, LEGACY_FILE);
            mLegacyFile = new File(context.dataDir, LEGACY_FILE);
            mDeviceOwnerFile = new File(context.dataDir, DEVICE_OWNER_FILE);
            mDeviceOwnerFile = new File(context.dataDir, DEVICE_OWNER_FILE);
            mProfileOwnerBase = new File(context.dataDir, PROFILE_OWNER_FILE_BASE);
            mProfileOwnerBase = new File(context.dataDir, PROFILE_OWNER_FILE_BASE);