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

Commit 250bb6e3 authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Allow profile owners to set user restrictions"

parents b22aabbb be46532c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4967,7 +4967,9 @@ package android.app.admin {
  public class DevicePolicyManager {
    method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
    method public void addUserRestriction(android.content.ComponentName, java.lang.String);
    method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
    method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
    method public java.util.List<android.content.ComponentName> getActiveAdmins();
    method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
    method public boolean getCameraDisabled(android.content.ComponentName);
+44 −0
Original line number Diff line number Diff line
@@ -1957,4 +1957,48 @@ public class DevicePolicyManager {
        }
        return null;
    }

    /**
     * Called by a profile or device owner to set a user restriction specified
     * by the key.
     * <p>
     * The calling device admin must be a profile or device owner; if it is not,
     * a security exception will be thrown.
     * 
     * @param admin Which {@link DeviceAdminReceiver} this request is associated
     *            with.
     * @param key The key of the restriction. See the constants in
     *            {@link android.os.UserManager} for the list of keys.
     */
    public void addUserRestriction(ComponentName admin, String key) {
        if (mService != null) {
            try {
                mService.setUserRestriction(admin, key, true);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
    }

    /**
     * Called by a profile or device owner to clear a user restriction specified
     * by the key.
     * <p>
     * The calling device admin must be a profile or device owner; if it is not,
     * a security exception will be thrown.
     * 
     * @param admin Which {@link DeviceAdminReceiver} this request is associated
     *            with.
     * @param key The key of the restriction. See the constants in
     *            {@link android.os.UserManager} for the list of keys.
     */
    public void clearUserRestriction(ComponentName admin, String key) {
        if (mService != null) {
            try {
                mService.setUserRestriction(admin, key, false);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -119,4 +119,6 @@ interface IDevicePolicyManager {

    void setApplicationRestrictions(in ComponentName who, in String packageName, in Bundle settings);
    Bundle getApplicationRestrictions(in ComponentName who, in String packageName);

    void setUserRestriction(in ComponentName who, in String key, boolean enable);
}
+5 −9
Original line number Diff line number Diff line
@@ -300,8 +300,7 @@ public class UserManager {

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

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

    /**
     * Sets the value of a specific restriction.
     * Requires the MANAGE_USERS permission or profile/device owner
     * privileges.
     * Requires the MANAGE_USERS permission.
     * @param key the key of the restriction
     * @param value the value for the restriction
     */
@@ -339,8 +336,7 @@ public class UserManager {
    /**
     * @hide
     * Sets the value of a specific restriction on a specific user.
     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission or profile/device owner
     * privileges.
     * Requires the MANAGE_USERS permission.
     * @param key the key of the restriction
     * @param value the value for the restriction
     * @param userHandle the user whose restriction is to be changed.
+53 −82
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ 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.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
@@ -263,9 +262,21 @@ public class UserManagerService extends IUserManager.Stub {
        if (userId != UserHandle.getCallingUserId()) {
            checkManageUsersPermission("getting profiles related to user " + userId);
        }
        final long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mPackagesLock) {
            // Getting the service here is not good for testing purposes. However, this service
            // is not available when UserManagerService starts up so we need a lazy load.
                return getProfilesLocked(userId, enabledOnly);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    /** Assume permissions already checked and caller's identity cleared */
    private List<UserInfo> getProfilesLocked(int userId, boolean enabledOnly) {
        // Getting the service here is not good for testing purposes.
        // However, this service is not available when UserManagerService starts
        // up so we need a lazy load.

        DevicePolicyManager dpm = null;
        if (enabledOnly) {
@@ -288,20 +299,20 @@ public class UserManagerService extends IUserManager.Stub {
                    }
                } else {
                    Log.w(LOG_TAG,
                                "Attempting to reach DevicePolicyManager before it was started");
                        // TODO: There might be system apps that need to call this. Make sure that
                        // DevicePolicyManagerService is ready at that time (otherwise, any default
                        // value is a bad one).
                            "Attempting to reach DevicePolicyManager before it is started");
                    // TODO: There might be system apps that need to call this.
                    // Make sure that DevicePolicyManagerService is ready at that
                    // time (otherwise, any default value is a bad one).
                    throw new IllegalArgumentException(String.format(
                            "Attempting to get enabled profiles for %d before "
                                + "DevicePolicyManagerService has been started.", userId));
                                    + "DevicePolicyManagerService has been started.",
                            userId));
                }
            }
            users.add(profile);
        }
        return users;
    }
    }

    private boolean isProfileOf(UserInfo user, UserInfo profile) {
        return user.id == profile.id ||
@@ -459,13 +470,13 @@ public class UserManagerService extends IUserManager.Stub {

        synchronized (mPackagesLock) {
            Bundle restrictions = mUserRestrictions.get(userId);
            return restrictions != null ? restrictions : Bundle.EMPTY;
            return restrictions != null ? new Bundle(restrictions) : new Bundle();
        }
    }

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

        synchronized (mPackagesLock) {
@@ -491,51 +502,14 @@ 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 final void checkManageUsersPermission(String message) {
        final int uid = Binder.getCallingUid();

        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) {
    private static final void checkManageUsersPermission(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
        if (uid != Process.SYSTEM_UID && uid != 0
                && ActivityManager.checkComponentPermission(
                        android.Manifest.permission.MANAGE_USERS,
                        uid, -1, true) != PackageManager.PERMISSION_GRANTED;
                        uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("You need MANAGE_USERS permission to: " + message);
        }
    }

    private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
@@ -1240,8 +1214,7 @@ public class UserManagerService extends IUserManager.Stub {
    public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
        if (UserHandle.getCallingUserId() != userId
                || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
            checkProfileOwnerOrManageUsersPermission(
                    "Only system or device owner can get restrictions for other users/apps");
            checkManageUsersPermission("Only system can get restrictions for other users/apps");
        }
        synchronized (mPackagesLock) {
            // Read the restrictions from XML
@@ -1254,8 +1227,7 @@ public class UserManagerService extends IUserManager.Stub {
            int userId) {
        if (UserHandle.getCallingUserId() != userId
                || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
            checkProfileOwnerOrManageUsersPermission(
                    "Only system or device owner can set restrictions for other users/apps");
            checkManageUsersPermission("Only system can set restrictions for other users/apps");
        }
        synchronized (mPackagesLock) {
            // Write the restrictions to XML
@@ -1357,8 +1329,7 @@ public class UserManagerService extends IUserManager.Stub {

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