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

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

Merge "More work on layered user restrictions."

parents dd311b25 1a2cd745
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.app.admin;

import android.os.Bundle;

import java.util.List;

/**
@@ -71,13 +69,4 @@ public abstract class DevicePolicyManagerInternal {
     * @return true if the uid is an active admin with the given policy.
     */
    public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);

    /**
     * Takes a {@link Bundle} containing "base" user restrictions stored in
     * {@link com.android.server.pm.UserManagerService}, mixes restrictions set by the device owner
     * and the profile owner and returns the merged restrictions.
     *
     * This method always returns a new {@link Bundle}.
     */
    public abstract Bundle getComposedUserRestrictions(int userId, Bundle inBundle);
}
+13 −24
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package android.os;

import android.annotation.NonNull;
import android.annotation.Nullable;

/**
 * @hide Only for use within the system server.
 */
@@ -31,32 +34,18 @@ public abstract class UserManagerInternal {
    }

    /**
     * Lock that must be held when calling certain methods in this class.
     *
     * This is used to avoid dead lock between
     * {@link com.android.server.pm.UserManagerService} and
     * {@link com.android.server.devicepolicy.DevicePolicyManagerService}.  This lock should not
     * be newly taken while holding the DPMS lock, which would cause a dead lock.  Take this
     * lock first before taking the DPMS lock to avoid that.
     */
    public abstract Object getUserRestrictionsLock();

    /**
     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to get
     * {@link com.android.server.pm.UserManagerService} to update effective user restrictions.
     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
     * to set per-user as well as global user restrictions.
     *
     * Must be called while taking the {@link #getUserRestrictionsLock()} lock.
     * @param userId target user id for the local restrictions.
     * @param localRestrictions per-user restrictions.
     *     Caller must not change it once passed to this method.
     * @param globalRestrictions global restrictions set by DO.  Must be null when PO changed user
     *     restrictions, in which case global restrictions won't change.
     *     Caller must not change it once passed to this method.
     */
    public abstract void updateEffectiveUserRestrictionsLR(int userId);

    /**
     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to get
     * {@link com.android.server.pm.UserManagerService} to update effective user restrictions.
     *
     * Must be called while taking the {@link #getUserRestrictionsLock()} lock.
     */
    public abstract void updateEffectiveUserRestrictionsForAllUsersLR();

    public abstract void setDevicePolicyUserRestrictions(int userId,
            @NonNull Bundle localRestrictions, @Nullable Bundle globalRestrictions);
    /**
     * Returns the "base" user restrictions.
     *
+3 −0
Original line number Diff line number Diff line
@@ -522,6 +522,9 @@ final class UserController {
                }

                if (uss.mState == UserState.STATE_BOOTING) {
                    // Let user manager propagate user restrictions to other services.
                    getUserManager().onBeforeStartUser(userId);

                    // Booting up a new user, need to tell system services about it.
                    // Note that this is on the same handler as scheduling of broadcasts,
                    // which is important because it needs to go first.
+213 −104

File changed.

Preview size limit exceeded, changes collapsed.

+153 −7
Original line number Diff line number Diff line
@@ -18,6 +18,10 @@ package com.android.server.pm;

import com.google.android.collect.Sets;

import com.android.internal.util.Preconditions;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
@@ -26,6 +30,7 @@ import android.os.Bundle;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
@@ -79,22 +84,64 @@ public class UserRestrictionsUtils {
            UserManager.DISALLOW_SAFE_BOOT,
            UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
            UserManager.DISALLOW_RECORD_AUDIO,
            UserManager.DISALLOW_CAMERA,
    };

    /**
     * Set of user restrictions, which can only be enforced by the system.
     */
    public static final Set<String> SYSTEM_CONTROLLED_USER_RESTRICTIONS = Sets.newArraySet(
            UserManager.DISALLOW_RECORD_AUDIO);
            UserManager.DISALLOW_RECORD_AUDIO
    );

    /**
     * Set of user restriction which we don't want to persist.
     */
    public static final Set<String> NON_PERSIST_USER_RESTRICTIONS = Sets.newArraySet(
            UserManager.DISALLOW_RECORD_AUDIO);
    private static final Set<String> NON_PERSIST_USER_RESTRICTIONS = Sets.newArraySet(
            UserManager.DISALLOW_RECORD_AUDIO
    );

    /**
     * User restrictions that can not be set by profile owners.
     */
    private static final Set<String> DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet(
            UserManager.DISALLOW_USB_FILE_TRANSFER,
            UserManager.DISALLOW_CONFIG_TETHERING,
            UserManager.DISALLOW_NETWORK_RESET,
            UserManager.DISALLOW_FACTORY_RESET,
            UserManager.DISALLOW_ADD_USER,
            UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
            UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
            UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
            UserManager.DISALLOW_SMS,
            UserManager.DISALLOW_FUN,
            UserManager.DISALLOW_SAFE_BOOT,
            UserManager.DISALLOW_CREATE_WINDOWS
    );

    /**
     * User restrictions that can't be changed by device owner or profile owner.
     */
    private static final Set<String> IMMUTABLE_BY_OWNERS = Sets.newArraySet(
            UserManager.DISALLOW_RECORD_AUDIO,
            UserManager.DISALLOW_WALLPAPER
    );

    /**
     * Special user restrictions that can be applied to a user as well as to all users globally,
     * depending on callers.  When device owner sets them, they'll be applied to all users.
     */
    private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
            UserManager.DISALLOW_ADJUST_VOLUME,
            UserManager.DISALLOW_UNMUTE_MICROPHONE
    );

    public static void writeRestrictions(@NonNull XmlSerializer serializer,
            @Nullable Bundle restrictions, @NonNull String tag) throws IOException {
        if (restrictions == null) {
            return;
        }

    public static void writeRestrictions(XmlSerializer serializer, Bundle restrictions,
            String tag) throws IOException {
        serializer.startTag(null, tag);
        for (String key : USER_RESTRICTIONS) {
            if (restrictions.getBoolean(key)
@@ -115,7 +162,31 @@ public class UserRestrictionsUtils {
        }
    }

    public static void merge(Bundle dest, Bundle in) {
    /**
     * @return {@code in} itself when it's not null, or an empty bundle (which can writable).
     */
    public static Bundle nonNull(@Nullable Bundle in) {
        return in != null ? in : new Bundle();
    }

    public static boolean isEmpty(@Nullable Bundle in) {
        return (in == null) || (in.size() == 0);
    }

    /**
     * Creates a copy of the {@code in} Bundle.  If {@code in} is null, it'll return an empty
     * bundle.
     *
     * <p>The resulting {@link Bundle} is always writable. (i.e. it won't return
     * {@link Bundle#EMPTY})
     */
    public static @NonNull Bundle clone(@Nullable Bundle in) {
        return (in != null) ? new Bundle(in) : new Bundle();
    }

    public static void merge(@NonNull Bundle dest, @Nullable Bundle in) {
        Preconditions.checkNotNull(dest);
        Preconditions.checkArgument(dest != in);
        if (in == null) {
            return;
        }
@@ -126,6 +197,77 @@ public class UserRestrictionsUtils {
        }
    }

    /**
     * @return true if a restriction is "system controlled"; i.e. can not be overwritten via
     * {@link UserManager#setUserRestriction}.
     */
    public static boolean isSystemControlled(String restriction) {
        return SYSTEM_CONTROLLED_USER_RESTRICTIONS.contains(restriction);
    }

    /**
     * @return true if a restriction is settable by device owner.
     */
    public static boolean canDeviceOwnerChange(String restriction) {
        return !IMMUTABLE_BY_OWNERS.contains(restriction);
    }

    /**
     * @return true if a restriction is settable by profile owner.
     */
    public static boolean canProfileOwnerChange(String restriction) {
        return !(IMMUTABLE_BY_OWNERS.contains(restriction)
                || DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction));
    }

    /**
     * Takes restrictions that can be set by device owner, and sort them into what should be applied
     * globally and what should be applied only on the current user.
     */
    public static void sortToGlobalAndLocal(@Nullable Bundle in, @NonNull Bundle global,
            @NonNull Bundle local) {
        if (in == null || in.size() == 0) {
            return;
        }
        for (String key : in.keySet()) {
            if (!in.getBoolean(key)) {
                continue;
            }
            if (DEVICE_OWNER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)) {
                global.putBoolean(key, true);
            } else {
                local.putBoolean(key, true);
            }
        }
    }

    /**
     * @return true if two Bundles contain the same user restriction.
     * A null bundle and an empty bundle are considered to be equal.
     */
    public static boolean areEqual(@Nullable Bundle a, @Nullable Bundle b) {
        if (a == b) {
            return true;
        }
        if (isEmpty(a)) {
            return isEmpty(b);
        }
        if (isEmpty(b)) {
            return false;
        }
        for (String key : a.keySet()) {
            if (a.getBoolean(key) != b.getBoolean(key)) {
                return false;
            }
        }
        for (String key : b.keySet()) {
            if (a.getBoolean(key) != b.getBoolean(key)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Takes a new use restriction set and the previous set, and apply the restrictions that have
     * changed.
@@ -155,6 +297,10 @@ public class UserRestrictionsUtils {
     */
    private static void applyUserRestrictionLR(Context context, int userId, String key,
            boolean newValue) {
        if (UserManagerService.DBG) {
            Log.d(TAG, "Applying user restriction: userId=" + userId
                    + " key=" + key + " value=" + newValue);
        }
        // When certain restrictions are cleared, we don't update the system settings,
        // because these settings are changeable on the Settings UI and we don't know the original
        // value -- for example LOCATION_MODE might have been off already when the restriction was
Loading