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

Commit 8a0fa6e8 authored by Emily Bernier's avatar Emily Bernier Committed by Android (Google) Code Review
Browse files

Merge "Allow device or profile owner app to modify user restrictions."

parents 4e8cf150 7a2b4d11
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -300,7 +300,8 @@ public class UserManager {

    /**
     * Sets all the user-wide restrictions for this user.
     * Requires the MANAGE_USERS permission.
     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission or profile/device owner
     * privileges.
     * @param restrictions the Bundle containing all the restrictions.
     */
    public void setUserRestrictions(Bundle restrictions) {
@@ -309,7 +310,8 @@ public class UserManager {

    /**
     * Sets all the user-wide restrictions for the specified user.
     * Requires the MANAGE_USERS permission.
     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission or profile/device owner
     * privileges.
     * @param restrictions the Bundle containing all the restrictions.
     * @param userHandle the UserHandle of the user for whom to set the restrictions.
     */
@@ -323,7 +325,8 @@ public class UserManager {

    /**
     * Sets the value of a specific restriction.
     * Requires the MANAGE_USERS permission.
     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission or profile/device owner
     * privileges.
     * @param key the key of the restriction
     * @param value the value for the restriction
     */
@@ -336,7 +339,8 @@ public class UserManager {
    /**
     * @hide
     * Sets the value of a specific restriction on a specific user.
     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission or profile/device owner
     * privileges.
     * @param key the key of the restriction
     * @param value the value for the restriction
     * @param userHandle the user whose restriction is to be changed.
+50 −9
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.admin.DevicePolicyManager;
import android.app.IStopUserCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -437,7 +438,7 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public void setUserRestrictions(Bundle restrictions, int userId) {
        checkManageUsersPermission("setUserRestrictions");
        checkProfileOwnerOrManageUsersPermission("setUserRestrictions");
        if (restrictions == null) return;

        synchronized (mPackagesLock) {
@@ -463,16 +464,53 @@ public class UserManagerService extends IUserManager.Stub {
     * @param message used as message if SecurityException is thrown
     * @throws SecurityException if the caller is not system or root
     */
    private static final void checkManageUsersPermission(String message) {
    private final void checkManageUsersPermission(String message) {
        final int uid = Binder.getCallingUid();
        if (uid != Process.SYSTEM_UID && uid != 0
                && ActivityManager.checkComponentPermission(
                        android.Manifest.permission.MANAGE_USERS,
                        uid, -1, true) != PackageManager.PERMISSION_GRANTED) {

        if (missingManageUsersPermission(uid)) {
            throw new SecurityException("You need MANAGE_USERS permission to: " + message);
        }
    }

    /**
     * Enforces that only the system UID, root's UID, apps that have the
     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
     * permission, the profile owner, or the device owner can make certain calls to the
     * UserManager.
     *
     * @param message used as message if SecurityException is thrown
     * @throws SecurityException if the caller is not system, root, or device
     * owner
     */
    private final void checkProfileOwnerOrManageUsersPermission(String message) {
        final int uid = Binder.getCallingUid();
        boolean isProfileOwner = false;
        if (mContext != null && mContext.getPackageManager() != null) {
            String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
            DevicePolicyManager dpm =
                    (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
            if (dpm != null) {
                for (String pkg : pkgs) {
                    if (dpm.isDeviceOwnerApp(pkg) || dpm.isProfileOwnerApp(pkg)) {
                        isProfileOwner = true;
                    }
                }
            }
        }

        if (missingManageUsersPermission(uid) && !isProfileOwner) {
            throw new SecurityException(
                    "You need MANAGE_USERS permission or device owner privileges to: " + message);
        }
    }

    private boolean missingManageUsersPermission(int uid) {
        return uid != Process.SYSTEM_UID && uid != 0
                && ActivityManager.checkComponentPermission(
                        android.Manifest.permission.MANAGE_USERS,
                        uid, -1, true) != PackageManager.PERMISSION_GRANTED;
    }

    private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
        try {
            File dir = new File(mUsersDir, Integer.toString(info.id));
@@ -1175,7 +1213,8 @@ public class UserManagerService extends IUserManager.Stub {
    public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
        if (UserHandle.getCallingUserId() != userId
                || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
            checkManageUsersPermission("Only system can get restrictions for other users/apps");
            checkProfileOwnerOrManageUsersPermission(
                    "Only system or device owner can get restrictions for other users/apps");
        }
        synchronized (mPackagesLock) {
            // Read the restrictions from XML
@@ -1188,7 +1227,8 @@ public class UserManagerService extends IUserManager.Stub {
            int userId) {
        if (UserHandle.getCallingUserId() != userId
                || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
            checkManageUsersPermission("Only system can set restrictions for other users/apps");
            checkProfileOwnerOrManageUsersPermission(
                    "Only system or device owner can set restrictions for other users/apps");
        }
        synchronized (mPackagesLock) {
            // Write the restrictions to XML
@@ -1290,7 +1330,8 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public void removeRestrictions() {
        checkManageUsersPermission("Only system can remove restrictions");
        checkProfileOwnerOrManageUsersPermission(
                "Only system or device owner can remove restrictions");
        final int userHandle = UserHandle.getCallingUserId();
        removeRestrictionsForUser(userHandle, true);
    }