diff options
| -rw-r--r-- | api/system-current.txt | 8 | ||||
| -rw-r--r-- | core/java/android/os/IUserManager.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 59 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 75 |
4 files changed, 143 insertions, 0 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index c489435bc093..aea96bd12482 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -31928,6 +31928,7 @@ package android.os { method public deprecated void setUserRestrictions(android.os.Bundle); method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle); method public static boolean supportsMultipleUsers(); + method public int getUserRestrictionSource(java.lang.String, android.os.UserHandle); field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking"; field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user"; field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume"; @@ -31965,6 +31966,13 @@ package android.os { field public static final java.lang.String KEY_RESTRICTIONS_PENDING = "restrictions_pending"; field public static final int USER_CREATION_FAILED_NOT_PERMITTED = 1; // 0x1 field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2 + field public static final int RESTRICTION_NOT_SET = 0; // 0x0 + field public static final int RESTRICTION_SOURCE_SYSTEM = 1; // 0x1 + field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2 + field public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 4; // 0x4 + } + + public static abstract class UserManager.UserRestrictionSource implements java.lang.annotation.Annotation { } public abstract class Vibrator { diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 55b0d2a15317..b27cb32bd4eb 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -58,6 +58,7 @@ interface IUserManager { boolean canHaveRestrictedProfile(int userHandle); int getUserSerialNumber(int userHandle); int getUserHandle(int userSerialNumber); + int getUserRestrictionSource(String restrictionKey, int userHandle); Bundle getUserRestrictions(int userHandle); boolean hasBaseUserRestriction(String restrictionKey, int userHandle); boolean hasUserRestriction(in String restrictionKey, int userHandle); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index cd3205976aa8..1a7d8516d8d3 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -18,6 +18,7 @@ package android.os; import android.Manifest; import android.accounts.AccountManager; +import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -44,6 +45,8 @@ import android.view.WindowManager.LayoutParams; import com.android.internal.R; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; @@ -64,6 +67,41 @@ public class UserManager { private final Context mContext; /** + * @hide + * No user restriction. + */ + @SystemApi + public static final int RESTRICTION_NOT_SET = 0x0; + + /** + * @hide + * User restriction set by system/user. + */ + @SystemApi + public static final int RESTRICTION_SOURCE_SYSTEM = 0x1; + + /** + * @hide + * User restriction set by a device owner. + */ + @SystemApi + public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 0x2; + + /** + * @hide + * User restriction set by a profile owner. + */ + @SystemApi + public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 0x4; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag=true, value={RESTRICTION_NOT_SET, RESTRICTION_SOURCE_SYSTEM, + RESTRICTION_SOURCE_DEVICE_OWNER, RESTRICTION_SOURCE_PROFILE_OWNER}) + @SystemApi + public @interface UserRestrictionSource {} + + /** * Specifies if a user is disallowed from adding and removing accounts, unless they are * {@link android.accounts.AccountManager#addAccountExplicitly programmatically} added by * Authenticator. @@ -1006,6 +1044,27 @@ public class UserManager { } /** + * @hide + * + * Returns who set a user restriction on a user. + * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * @param restrictionKey the string key representing the restriction + * @param userHandle the UserHandle of the user for whom to retrieve the restrictions. + * @return The source of user restriction. Any combination of {@link #RESTRICTION_NOT_SET}, + * {@link #RESTRICTION_SOURCE_SYSTEM}, {@link #RESTRICTION_SOURCE_DEVICE_OWNER} + * and {@link #RESTRICTION_SOURCE_PROFILE_OWNER} + */ + @SystemApi + @UserRestrictionSource + public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) { + try { + return mService.getUserRestrictionSource(restrictionKey, userHandle.getIdentifier()); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * Returns the user-wide restrictions imposed on this user. * @return a Bundle containing all the restrictions. */ diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 7ea59190981a..8d1abb0c7d1c 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -23,6 +23,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; @@ -31,7 +32,9 @@ import android.app.ActivityManagerNative; import android.app.IActivityManager; import android.app.IStopUserCallback; import android.app.KeyguardManager; +import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -143,6 +146,7 @@ public class UserManagerService extends IUserManager.Stub { private static final String TAG_USER = "user"; private static final String TAG_RESTRICTIONS = "restrictions"; private static final String TAG_DEVICE_POLICY_RESTRICTIONS = "device_policy_restrictions"; + private static final String TAG_GLOBAL_RESTRICTION_OWNER_ID = "globalRestrictionOwnerUserId"; private static final String TAG_ENTRY = "entry"; private static final String TAG_VALUE = "value"; private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions"; @@ -276,6 +280,12 @@ public class UserManagerService extends IUserManager.Stub { private Bundle mDevicePolicyGlobalUserRestrictions; /** + * Id of the user that set global restrictions. + */ + @GuardedBy("mRestrictionsLock") + private int mGlobalRestrictionOwnerUserId = UserHandle.USER_NULL; + + /** * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService} * for each user. */ @@ -991,6 +1001,13 @@ public class UserManagerService extends IUserManager.Stub { if (globalChanged) { mDevicePolicyGlobalUserRestrictions = global; } + // Remember the global restriction owner userId to be able to make a distinction + // in getUserRestrictionSource on who set local policies. + mGlobalRestrictionOwnerUserId = userId; + } else { + // When profile owner sets restrictions it passes null global bundle and we reset + // global restriction owner userId. + mGlobalRestrictionOwnerUserId = UserHandle.USER_NULL; } { // Update local. @@ -1074,6 +1091,54 @@ public class UserManagerService extends IUserManager.Stub { } /** + * @hide + * + * Returns who set a user restriction on a user. + * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * @param restrictionKey the string key representing the restriction + * @param userId the id of the user for whom to retrieve the restrictions. + * @return The source of user restriction. Any combination of + * {@link UserManager#RESTRICTION_NOT_SET}, + * {@link UserManager#RESTRICTION_SOURCE_SYSTEM}, + * {@link UserManager#RESTRICTION_SOURCE_DEVICE_OWNER} + * and {@link UserManager#RESTRICTION_SOURCE_PROFILE_OWNER} + */ + @Override + public int getUserRestrictionSource(String restrictionKey, int userId) { + checkManageUsersPermission("getUserRestrictionSource"); + int result = UserManager.RESTRICTION_NOT_SET; + + // Shortcut for the most common case + if (!hasUserRestriction(restrictionKey, userId)) { + return result; + } + + if (hasBaseUserRestriction(restrictionKey, userId)) { + result |= UserManager.RESTRICTION_SOURCE_SYSTEM; + } + + synchronized(mRestrictionsLock) { + Bundle localRestrictions = mDevicePolicyLocalUserRestrictions.get(userId); + if (!UserRestrictionsUtils.isEmpty(localRestrictions) + && localRestrictions.getBoolean(restrictionKey)) { + // Local restrictions may have been set by device owner the userId of which is + // stored in mGlobalRestrictionOwnerUserId. + if (mGlobalRestrictionOwnerUserId == userId) { + result |= UserManager.RESTRICTION_SOURCE_DEVICE_OWNER; + } else { + result |= UserManager.RESTRICTION_SOURCE_PROFILE_OWNER; + } + } + if (!UserRestrictionsUtils.isEmpty(mDevicePolicyGlobalUserRestrictions) + && mDevicePolicyGlobalUserRestrictions.getBoolean(restrictionKey)) { + result |= UserManager.RESTRICTION_SOURCE_DEVICE_OWNER; + } + } + + return result; + } + + /** * @return UserRestrictions that are in effect currently. This always returns a new * {@link Bundle}. */ @@ -1470,6 +1535,11 @@ public class UserManagerService extends IUserManager.Stub { break; } } + } else if (name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) { + String ownerUserId = parser.getAttributeValue(null, ATTR_ID); + if (ownerUserId != null) { + mGlobalRestrictionOwnerUserId = Integer.parseInt(ownerUserId); + } } } } @@ -1729,6 +1799,9 @@ public class UserManagerService extends IUserManager.Stub { UserRestrictionsUtils.writeRestrictions(serializer, mDevicePolicyGlobalUserRestrictions, TAG_DEVICE_POLICY_RESTRICTIONS); } + serializer.startTag(null, TAG_GLOBAL_RESTRICTION_OWNER_ID); + serializer.attribute(null, ATTR_ID, Integer.toString(mGlobalRestrictionOwnerUserId)); + serializer.endTag(null, TAG_GLOBAL_RESTRICTION_OWNER_ID); int[] userIdsToWrite; synchronized (mUsersLock) { userIdsToWrite = new int[mUsers.size()]; @@ -2964,6 +3037,8 @@ public class UserManagerService extends IUserManager.Stub { .dumpRestrictions(pw, " ", mDevicePolicyGlobalUserRestrictions); } pw.println(); + pw.println(" Global restrictions owner id:" + mGlobalRestrictionOwnerUserId); + pw.println(); pw.println(" Guest restrictions:"); synchronized (mGuestRestrictions) { UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions); |