Layer user restrictions
- Now DPMS remembers user restrictions set by DO / PO in their ActiveAdmin. - User restrictions set by DO/PO will no longer be saved by UserManger. Instead, when needed, UMS will consult DPMS to build "effective" user restrictions. - UM.getUserRestrictions() will now always return "effective" user restrictions. - DPMS migrates existing user restrictions per the eng spec. - Also now UM.setUserRestrictions() will crash. UMS.setUserRestrictions() has been removed. This was needed because UM.setUserRestrctions(UM.getUserRestrictions()) will no longer be a valid use like it used to be. - Also introduced a fined-grained lock for user restrictions in UM to avoid deadlock between DPMS and also for better performance. Bug 23902097 Change-Id: If0e1e49344e2f3e9226532d00777976d1eaa7df3
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.app.admin;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -69,4 +71,13 @@ 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);
|
||||
}
|
||||
|
||||
@@ -55,14 +55,12 @@ interface IUserManager {
|
||||
int getUserHandle(int userSerialNumber);
|
||||
Bundle getUserRestrictions(int userHandle);
|
||||
boolean hasUserRestriction(in String restrictionKey, int userHandle);
|
||||
void setUserRestrictions(in Bundle restrictions, int userHandle);
|
||||
void setUserRestriction(String key, boolean value, int userId);
|
||||
void setSystemControlledUserRestriction(String key, boolean value, int userId);
|
||||
void setApplicationRestrictions(in String packageName, in Bundle restrictions,
|
||||
int userHandle);
|
||||
Bundle getApplicationRestrictions(in String packageName);
|
||||
Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
|
||||
void removeRestrictions();
|
||||
void setDefaultGuestRestrictions(in Bundle restrictions);
|
||||
Bundle getDefaultGuestRestrictions();
|
||||
boolean markGuestForDeletion(int userHandle);
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.annotation.SystemApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
@@ -55,7 +56,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
|
||||
@@ -67,7 +69,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
|
||||
@@ -78,7 +81,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_INSTALL_APPS = "no_install_apps";
|
||||
@@ -89,7 +93,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
|
||||
@@ -102,7 +107,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
|
||||
@@ -114,7 +120,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
|
||||
@@ -127,7 +134,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
|
||||
@@ -139,7 +147,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
|
||||
@@ -150,7 +159,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
|
||||
@@ -163,7 +173,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_REMOVE_USER = "no_remove_user";
|
||||
@@ -174,7 +185,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
|
||||
@@ -187,7 +199,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";
|
||||
@@ -199,7 +212,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
|
||||
@@ -213,7 +227,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_NETWORK_RESET = "no_network_reset";
|
||||
@@ -227,7 +242,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_FACTORY_RESET = "no_factory_reset";
|
||||
@@ -241,7 +257,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_ADD_USER = "no_add_user";
|
||||
@@ -252,7 +269,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";
|
||||
@@ -266,7 +284,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
|
||||
@@ -280,7 +299,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
|
||||
@@ -300,7 +320,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_APPS_CONTROL = "no_control_apps";
|
||||
@@ -312,7 +333,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
|
||||
@@ -324,7 +346,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
|
||||
@@ -336,7 +359,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
|
||||
@@ -350,7 +374,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
|
||||
@@ -361,7 +386,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_SMS = "no_sms";
|
||||
@@ -373,7 +399,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_FUN = "no_fun";
|
||||
@@ -393,7 +420,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";
|
||||
@@ -406,7 +434,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
|
||||
@@ -417,7 +446,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
|
||||
@@ -426,7 +456,8 @@ public class UserManager {
|
||||
* Hidden user restriction to disallow access to wallpaper manager APIs. This user restriction
|
||||
* is always set for managed profiles.
|
||||
* @hide
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_WALLPAPER = "no_wallpaper";
|
||||
@@ -438,7 +469,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String DISALLOW_SAFE_BOOT = "no_safe_boot";
|
||||
@@ -447,7 +479,8 @@ public class UserManager {
|
||||
* Specifies if a user is not allowed to record audio. This restriction is always enabled for
|
||||
* background users. The default value is <code>false</code>.
|
||||
*
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
* @hide
|
||||
*/
|
||||
@@ -466,7 +499,8 @@ public class UserManager {
|
||||
*
|
||||
* <p/>Key for user restrictions.
|
||||
* <p/>Type: Boolean
|
||||
* @see #setUserRestrictions(Bundle)
|
||||
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
|
||||
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
|
||||
* @see #getUserRestrictions()
|
||||
*/
|
||||
public static final String ALLOW_PARENT_PROFILE_APP_LINKING
|
||||
@@ -740,36 +774,20 @@ public class UserManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all the user-wide restrictions for this user.
|
||||
* Requires the MANAGE_USERS permission.
|
||||
* @param restrictions the Bundle containing all the restrictions.
|
||||
* @deprecated use {@link android.app.admin.DevicePolicyManager#addUserRestriction(
|
||||
* android.content.ComponentName, String)} or
|
||||
* {@link android.app.admin.DevicePolicyManager#clearUserRestriction(
|
||||
* android.content.ComponentName, String)} instead.
|
||||
* This will no longer work. Use {@link #setUserRestriction(String, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUserRestrictions(Bundle restrictions) {
|
||||
setUserRestrictions(restrictions, Process.myUserHandle());
|
||||
throw new UnsupportedOperationException("This method is no longer supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all the user-wide restrictions for the specified user.
|
||||
* 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.
|
||||
* @deprecated use {@link android.app.admin.DevicePolicyManager#addUserRestriction(
|
||||
* android.content.ComponentName, String)} or
|
||||
* {@link android.app.admin.DevicePolicyManager#clearUserRestriction(
|
||||
* android.content.ComponentName, String)} instead.
|
||||
* This will no longer work. Use {@link #setUserRestriction(String, boolean, UserHandle)}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUserRestrictions(Bundle restrictions, UserHandle userHandle) {
|
||||
try {
|
||||
mService.setUserRestrictions(restrictions, userHandle.getIdentifier());
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not set user restrictions", re);
|
||||
}
|
||||
throw new UnsupportedOperationException("This method is no longer supported");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -784,9 +802,7 @@ public class UserManager {
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUserRestriction(String key, boolean value) {
|
||||
Bundle bundle = getUserRestrictions();
|
||||
bundle.putBoolean(key, value);
|
||||
setUserRestrictions(bundle);
|
||||
setUserRestriction(key, value, Process.myUserHandle());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -882,9 +898,8 @@ public class UserManager {
|
||||
try {
|
||||
user = mService.createUser(name, flags);
|
||||
if (user != null && !user.isAdmin()) {
|
||||
Bundle userRestrictions = mService.getUserRestrictions(user.id);
|
||||
addDefaultUserRestrictions(userRestrictions);
|
||||
mService.setUserRestrictions(userRestrictions, user.id);
|
||||
mService.setUserRestriction(DISALLOW_SMS, true, user.id);
|
||||
mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id);
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not create a user", re);
|
||||
@@ -899,27 +914,22 @@ public class UserManager {
|
||||
* @hide
|
||||
*/
|
||||
public UserInfo createGuest(Context context, String name) {
|
||||
UserInfo guest = createUser(name, UserInfo.FLAG_GUEST);
|
||||
if (guest != null) {
|
||||
Settings.Secure.putStringForUser(context.getContentResolver(),
|
||||
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
|
||||
try {
|
||||
Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
|
||||
guestRestrictions.putBoolean(DISALLOW_SMS, true);
|
||||
guestRestrictions.putBoolean(DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
|
||||
mService.setUserRestrictions(guestRestrictions, guest.id);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not update guest restrictions");
|
||||
UserInfo guest = null;
|
||||
try {
|
||||
guest = mService.createUser(name, UserInfo.FLAG_GUEST);
|
||||
if (guest != null) {
|
||||
Settings.Secure.putStringForUser(context.getContentResolver(),
|
||||
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
|
||||
|
||||
mService.setUserRestriction(DISALLOW_SMS, true, guest.id);
|
||||
mService.setUserRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES, true, guest.id);
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not create a user", re);
|
||||
}
|
||||
return guest;
|
||||
}
|
||||
|
||||
private static void addDefaultUserRestrictions(Bundle restrictions) {
|
||||
restrictions.putBoolean(DISALLOW_OUTGOING_CALLS, true);
|
||||
restrictions.putBoolean(DISALLOW_SMS, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a user with the specified name and options as a profile of another user.
|
||||
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
|
||||
@@ -1465,15 +1475,6 @@ public class UserManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void removeRestrictions() {
|
||||
try {
|
||||
mService.removeRestrictions();
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Could not change restrictions pin");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Set restrictions that should apply to any future guest user that's created.
|
||||
|
||||
63
core/java/android/os/UserManagerInternal.java
Normal file
63
core/java/android/os/UserManagerInternal.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.os;
|
||||
|
||||
/**
|
||||
* @hide Only for use within the system server.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* Must be called while taking the {@link #getUserRestrictionsLock()} lock.
|
||||
*/
|
||||
public abstract void updateEffectiveUserRestrictionsRL(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 updateEffectiveUserRestrictionsForAllUsersRL();
|
||||
|
||||
/**
|
||||
* Returns the "base" user restrictions.
|
||||
*
|
||||
* Used by {@link com.android.server.devicepolicy.DevicePolicyManagerService} for upgrading
|
||||
* from MNC.
|
||||
*/
|
||||
public abstract Bundle getBaseUserRestrictions(int userId);
|
||||
|
||||
/**
|
||||
* Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} for upgrading
|
||||
* from MNC.
|
||||
*/
|
||||
public abstract void setBaseUserRestrictionsByDpmsForMigration(int userId,
|
||||
Bundle baseRestrictions);
|
||||
}
|
||||
@@ -16,14 +16,15 @@
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.IStopUserCallback;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -46,6 +47,7 @@ import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.UserManagerInternal;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.system.ErrnoException;
|
||||
@@ -59,9 +61,11 @@ import android.util.SparseBooleanArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
@@ -83,11 +87,18 @@ import java.util.List;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
/**
|
||||
* Service for {@link UserManager}.
|
||||
*
|
||||
* Method naming convention:
|
||||
* - Methods suffixed with "Locked" should be called within the {@code this} lock.
|
||||
* - Methods suffixed with "RL" should be called within the {@link #mRestrictionsLock} lock.
|
||||
*/
|
||||
public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
private static final String LOG_TAG = "UserManagerService";
|
||||
|
||||
private static final boolean DBG = false;
|
||||
private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
|
||||
|
||||
private static final String TAG_NAME = "name";
|
||||
private static final String ATTR_FLAGS = "flags";
|
||||
@@ -160,7 +171,38 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
private final File mUserListFile;
|
||||
|
||||
private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
|
||||
private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
|
||||
|
||||
private final Object mRestrictionsLock = new Object();
|
||||
|
||||
/**
|
||||
* User restrictions set via UserManager. This doesn't include restrictions set by
|
||||
* device owner / profile owners.
|
||||
*
|
||||
* DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
|
||||
* a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
|
||||
* maybe shared between {@link #mBaseUserRestrictions} and
|
||||
* {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
|
||||
* (Otherwise we won't be able to detect what restrictions have changed in
|
||||
* {@link #updateUserRestrictionsInternalRL).
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined
|
||||
* with device / profile owner restrictions. We'll initialize it lazily; use
|
||||
* {@link #getEffectiveUserRestrictions} to access it.
|
||||
*
|
||||
* DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
|
||||
* a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
|
||||
* maybe shared between {@link #mBaseUserRestrictions} and
|
||||
* {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
|
||||
* (Otherwise we won't be able to detect what restrictions have changed in
|
||||
* {@link #updateUserRestrictionsInternalRL).
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
|
||||
|
||||
private final Bundle mGuestRestrictions = new Bundle();
|
||||
|
||||
/**
|
||||
@@ -176,6 +218,8 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
private IAppOpsService mAppOpsService;
|
||||
|
||||
private final LocalService mLocalService;
|
||||
|
||||
private static UserManagerService sInstance;
|
||||
|
||||
public static UserManagerService getInstance() {
|
||||
@@ -231,6 +275,8 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
sInstance = this;
|
||||
}
|
||||
}
|
||||
mLocalService = new LocalService();
|
||||
LocalServices.addService(UserManagerInternal.class, mLocalService);
|
||||
}
|
||||
|
||||
void systemReady() {
|
||||
@@ -258,8 +304,9 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
mAppOpsService = IAppOpsService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.APP_OPS_SERVICE));
|
||||
for (int i = 0; i < mUserIds.length; ++i) {
|
||||
final int userId = mUserIds[i];
|
||||
try {
|
||||
mAppOpsService.setUserRestrictions(mUserRestrictions.get(mUserIds[i]), mUserIds[i]);
|
||||
mAppOpsService.setUserRestrictions(getEffectiveUserRestrictions(userId), userId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
|
||||
}
|
||||
@@ -588,75 +635,171 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasUserRestriction(String restrictionKey, int userId) {
|
||||
synchronized (mPackagesLock) {
|
||||
Bundle restrictions = mUserRestrictions.get(userId);
|
||||
return restrictions != null && restrictions.getBoolean(restrictionKey);
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private Bundle computeEffectiveUserRestrictionsRL(int userId) {
|
||||
final DevicePolicyManagerInternal dpmi =
|
||||
LocalServices.getService(DevicePolicyManagerInternal.class);
|
||||
final Bundle systemRestrictions = mBaseUserRestrictions.get(userId);
|
||||
|
||||
final Bundle effective;
|
||||
if (dpmi == null) {
|
||||
// TODO Make sure it's because DPMS is disabled and not because we called it too early.
|
||||
effective = systemRestrictions;
|
||||
} else {
|
||||
effective = dpmi.getComposedUserRestrictions(userId, systemRestrictions);
|
||||
}
|
||||
return effective;
|
||||
}
|
||||
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private void invalidateEffectiveUserRestrictionsRL(int userId) {
|
||||
if (DBG) {
|
||||
Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
|
||||
}
|
||||
mCachedEffectiveUserRestrictions.remove(userId);
|
||||
}
|
||||
|
||||
private Bundle getEffectiveUserRestrictions(int userId) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
|
||||
if (restrictions == null) {
|
||||
restrictions = computeEffectiveUserRestrictionsRL(userId);
|
||||
mCachedEffectiveUserRestrictions.put(userId, restrictions);
|
||||
}
|
||||
return restrictions;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return a specific user restriction that's in effect currently. */
|
||||
@Override
|
||||
public boolean hasUserRestriction(String restrictionKey, int userId) {
|
||||
Bundle restrictions = getEffectiveUserRestrictions(userId);
|
||||
return restrictions != null && restrictions.getBoolean(restrictionKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserRestrictions that are in effect currently. This always returns a new
|
||||
* {@link Bundle}.
|
||||
*/
|
||||
@Override
|
||||
public Bundle getUserRestrictions(int userId) {
|
||||
synchronized (mPackagesLock) {
|
||||
Bundle restrictions = mUserRestrictions.get(userId);
|
||||
return restrictions != null ? new Bundle(restrictions) : new Bundle();
|
||||
}
|
||||
Bundle restrictions = getEffectiveUserRestrictions(userId);
|
||||
return restrictions != null ? new Bundle(restrictions) : new Bundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserRestriction(String key, boolean value, int userId) {
|
||||
checkManageUsersPermission("setUserRestriction");
|
||||
synchronized (mPackagesLock) {
|
||||
if (!UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS.contains(key)) {
|
||||
Bundle restrictions = getUserRestrictions(userId);
|
||||
restrictions.putBoolean(key, value);
|
||||
setUserRestrictionsInternalLocked(restrictions, userId);
|
||||
}
|
||||
if (!UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS.contains(key)) {
|
||||
setUserRestrictionNoCheck(key, value, userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemControlledUserRestriction(String key, boolean value, int userId) {
|
||||
checkSystemOrRoot("setSystemControlledUserRestriction");
|
||||
synchronized (mPackagesLock) {
|
||||
Bundle restrictions = getUserRestrictions(userId);
|
||||
restrictions.putBoolean(key, value);
|
||||
setUserRestrictionsInternalLocked(restrictions, userId);
|
||||
setUserRestrictionNoCheck(key, value, userId);
|
||||
}
|
||||
|
||||
private void setUserRestrictionNoCheck(String key, boolean value, int userId) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
// Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
|
||||
// a copy.
|
||||
final Bundle newRestrictions = new Bundle();
|
||||
UserRestrictionsUtils.merge(newRestrictions, mBaseUserRestrictions.get(userId));
|
||||
newRestrictions.putBoolean(key, value);
|
||||
|
||||
updateUserRestrictionsInternalRL(newRestrictions, userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserRestrictions(Bundle restrictions, int userId) {
|
||||
checkManageUsersPermission("setUserRestrictions");
|
||||
if (restrictions == null) return;
|
||||
|
||||
synchronized (mPackagesLock) {
|
||||
final Bundle oldUserRestrictions = mUserRestrictions.get(userId);
|
||||
// Restore the original state of system controlled restrictions from oldUserRestrictions
|
||||
for (String key : UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS) {
|
||||
restrictions.remove(key);
|
||||
if (oldUserRestrictions.containsKey(key)) {
|
||||
restrictions.putBoolean(key, oldUserRestrictions.getBoolean(key));
|
||||
}
|
||||
}
|
||||
setUserRestrictionsInternalLocked(restrictions, userId);
|
||||
/**
|
||||
* Optionally updating user restrictions, calculate the effective user restrictions by
|
||||
* consulting {@link com.android.server.devicepolicy.DevicePolicyManagerService} and also
|
||||
* apply it to {@link com.android.server.AppOpsService}.
|
||||
* TODO applyUserRestrictionsLocked() should also apply to system settings.
|
||||
*
|
||||
* @param newRestrictions User restrictions to set. If null, only the effective restrictions
|
||||
* will be updated. Note don't pass an existing Bundle in {@link #mBaseUserRestrictions}
|
||||
* or {@link #mCachedEffectiveUserRestrictions}; that'll most likely cause a sub
|
||||
* @param userId target user ID.
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private void updateUserRestrictionsInternalRL(
|
||||
@Nullable Bundle newRestrictions, int userId) {
|
||||
if (DBG) {
|
||||
Log.d(LOG_TAG, "updateUserRestrictionsInternalLocked userId=" + userId
|
||||
+ " bundle=" + newRestrictions);
|
||||
}
|
||||
final Bundle prevRestrictions = getEffectiveUserRestrictions(userId);
|
||||
|
||||
// Update system restrictions.
|
||||
if (newRestrictions != null) {
|
||||
// If newRestrictions == the current one, it's probably a bug.
|
||||
Preconditions.checkState(mBaseUserRestrictions.get(userId) != newRestrictions);
|
||||
Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
|
||||
!= newRestrictions);
|
||||
mBaseUserRestrictions.put(userId, newRestrictions);
|
||||
}
|
||||
|
||||
mCachedEffectiveUserRestrictions.put(
|
||||
userId, computeEffectiveUserRestrictionsRL(userId));
|
||||
|
||||
applyUserRestrictionsRL(userId, mBaseUserRestrictions.get(userId), prevRestrictions);
|
||||
}
|
||||
|
||||
private void setUserRestrictionsInternalLocked(Bundle restrictions, int userId) {
|
||||
final Bundle userRestrictions = mUserRestrictions.get(userId);
|
||||
userRestrictions.clear();
|
||||
userRestrictions.putAll(restrictions);
|
||||
long token = Binder.clearCallingIdentity();
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private void applyUserRestrictionsRL(int userId,
|
||||
Bundle newRestrictions, Bundle prevRestrictions) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppOpsService.setUserRestrictions(userRestrictions, userId);
|
||||
mAppOpsService.setUserRestrictions(newRestrictions, userId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
scheduleWriteUserLocked(mUsers.get(userId));
|
||||
|
||||
// TODO Move the code from DPMS.setUserRestriction().
|
||||
}
|
||||
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private void updateEffectiveUserRestrictionsRL(int userId) {
|
||||
updateUserRestrictionsInternalRL(null, userId);
|
||||
}
|
||||
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private void updateEffectiveUserRestrictionsForAllUsersRL() {
|
||||
// First, invalidate all cached values.
|
||||
synchronized (mRestrictionsLock) {
|
||||
mCachedEffectiveUserRestrictions.clear();
|
||||
}
|
||||
// We don't want to call into ActivityManagerNative while taking a lock, so we'll call
|
||||
// it on a handler.
|
||||
final Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Then get the list of running users.
|
||||
final int[] runningUsers;
|
||||
try {
|
||||
runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Unable to access ActivityManagerNative");
|
||||
return;
|
||||
}
|
||||
// Then re-calculate the effective restrictions and apply, only for running users.
|
||||
// It's okay if a new user has started after the getRunningUserIds() call,
|
||||
// because we'll do the same thing (re-calculate the restrictions and apply)
|
||||
// when we start a user.
|
||||
// TODO: "Apply restrictions upon user start hasn't been implemented. Implement it.
|
||||
synchronized (mRestrictionsLock) {
|
||||
for (int i = 0; i < runningUsers.length; i++) {
|
||||
updateUserRestrictionsInternalRL(null, runningUsers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mHandler.post(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -926,7 +1069,9 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
mUserVersion = USER_VERSION;
|
||||
|
||||
Bundle restrictions = new Bundle();
|
||||
mUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
|
||||
synchronized (mRestrictionsLock) {
|
||||
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
|
||||
}
|
||||
|
||||
updateUserIdsLocked();
|
||||
initDefaultGuestRestrictions();
|
||||
@@ -989,9 +1134,13 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
serializer.startTag(null, TAG_NAME);
|
||||
serializer.text(userInfo.name);
|
||||
serializer.endTag(null, TAG_NAME);
|
||||
Bundle restrictions = mUserRestrictions.get(userInfo.id);
|
||||
Bundle restrictions;
|
||||
synchronized (mRestrictionsLock) {
|
||||
restrictions = mBaseUserRestrictions.get(userInfo.id);
|
||||
}
|
||||
if (restrictions != null) {
|
||||
UserRestrictionsUtils.writeRestrictions(serializer, restrictions, TAG_RESTRICTIONS);
|
||||
UserRestrictionsUtils
|
||||
.writeRestrictions(serializer, restrictions, TAG_RESTRICTIONS);
|
||||
}
|
||||
serializer.endTag(null, TAG_USER);
|
||||
|
||||
@@ -1131,7 +1280,9 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
userInfo.guestToRemove = guestToRemove;
|
||||
userInfo.profileGroupId = profileGroupId;
|
||||
userInfo.restrictedProfileParentId = restrictedProfileParentId;
|
||||
mUserRestrictions.append(id, restrictions);
|
||||
synchronized (mRestrictionsLock) {
|
||||
mBaseUserRestrictions.append(id, restrictions);
|
||||
}
|
||||
return userInfo;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
@@ -1333,7 +1484,9 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
scheduleWriteUserLocked(userInfo);
|
||||
updateUserIdsLocked();
|
||||
Bundle restrictions = new Bundle();
|
||||
mUserRestrictions.append(userId, restrictions);
|
||||
synchronized (mRestrictionsLock) {
|
||||
mBaseUserRestrictions.append(userId, restrictions);
|
||||
}
|
||||
}
|
||||
}
|
||||
mPm.newUserCreated(userId);
|
||||
@@ -1616,25 +1769,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRestrictions() {
|
||||
checkManageUsersPermission("remove restrictions");
|
||||
final int userHandle = UserHandle.getCallingUserId();
|
||||
removeRestrictionsForUser(userHandle, true);
|
||||
}
|
||||
|
||||
private void removeRestrictionsForUser(final int userHandle, boolean unhideApps) {
|
||||
synchronized (mPackagesLock) {
|
||||
// Remove all user restrictions
|
||||
setUserRestrictions(new Bundle(), userHandle);
|
||||
// Remove any app restrictions
|
||||
cleanAppRestrictions(userHandle);
|
||||
}
|
||||
if (unhideApps) {
|
||||
unhideAllInstalledAppsForUser(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private void unhideAllInstalledAppsForUser(final int userHandle) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
@@ -2062,7 +2196,10 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
pw.println(" Restrictions:");
|
||||
UserRestrictionsUtils.dumpRestrictions(
|
||||
pw, " ", mUserRestrictions.get(user.id));
|
||||
pw, " ", mBaseUserRestrictions.get(user.id));
|
||||
pw.println(" Effective restrictions:");
|
||||
UserRestrictionsUtils.dumpRestrictions(
|
||||
pw, " ", mCachedEffectiveUserRestrictions.get(user.id));
|
||||
}
|
||||
pw.println();
|
||||
pw.println("Guest restrictions:");
|
||||
@@ -2095,4 +2232,49 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
boolean isInitialized(int userId) {
|
||||
return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0;
|
||||
}
|
||||
|
||||
private class LocalService extends UserManagerInternal {
|
||||
|
||||
@Override
|
||||
public Object getUserRestrictionsLock() {
|
||||
return mRestrictionsLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
public void updateEffectiveUserRestrictionsRL(int userId) {
|
||||
UserManagerService.this.updateEffectiveUserRestrictionsRL(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
public void updateEffectiveUserRestrictionsForAllUsersRL() {
|
||||
UserManagerService.this.updateEffectiveUserRestrictionsForAllUsersRL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getBaseUserRestrictions(int userId) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
return mBaseUserRestrictions.get(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBaseUserRestrictionsByDpmsForMigration(
|
||||
int userId, Bundle baseRestrictions) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions));
|
||||
invalidateEffectiveUserRestrictionsRL(userId);
|
||||
}
|
||||
|
||||
synchronized (mPackagesLock) {
|
||||
final UserInfo userInfo = mUsers.get(userId);
|
||||
if (userInfo != null) {
|
||||
writeUserLocked(userInfo);
|
||||
} else {
|
||||
Slog.w(LOG_TAG, "UserInfo not found for " + userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,6 @@ public class UserRestrictionsUtils {
|
||||
String tag) throws IOException {
|
||||
serializer.startTag(null, tag);
|
||||
for (String key : USER_RESTRICTIONS) {
|
||||
//
|
||||
if (restrictions.getBoolean(key)
|
||||
&& !NON_PERSIST_USER_RESTRICTIONS.contains(key)) {
|
||||
serializer.attribute(null, key, "true");
|
||||
@@ -105,6 +104,17 @@ public class UserRestrictionsUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void merge(Bundle dest, Bundle in) {
|
||||
if (in == null) {
|
||||
return;
|
||||
}
|
||||
for (String key : in.keySet()) {
|
||||
if (in.getBoolean(key, false)) {
|
||||
dest.putBoolean(key, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
|
||||
boolean noneSet = true;
|
||||
if (restrictions != null) {
|
||||
@@ -114,9 +124,11 @@ public class UserRestrictionsUtils {
|
||||
noneSet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (noneSet) {
|
||||
pw.println(prefix + "none");
|
||||
if (noneSet) {
|
||||
pw.println(prefix + "none");
|
||||
}
|
||||
} else {
|
||||
pw.println(prefix + "null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.google.android.collect.Sets;
|
||||
|
||||
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
|
||||
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
|
||||
@@ -88,6 +90,7 @@ import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.UserManagerInternal;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.provider.ContactsContract.QuickContact;
|
||||
import android.provider.ContactsInternal;
|
||||
@@ -183,8 +186,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning;
|
||||
private static final int PROFILE_WIPED_NOTIFICATION_ID = 1001;
|
||||
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
|
||||
private static final String ATTR_SETUP_COMPLETE = "setup-complete";
|
||||
private static final String ATTR_PERMISSION_POLICY = "permission-policy";
|
||||
@@ -274,6 +275,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
final Injector mInjector;
|
||||
final IPackageManager mIPackageManager;
|
||||
final UserManager mUserManager;
|
||||
final UserManagerInternal mUserManagerInternal;
|
||||
|
||||
final LocalService mLocalService;
|
||||
|
||||
@@ -357,8 +359,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
getSendingUserId());
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|
||||
|| ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
|
||||
if (DBG) Slog.v(LOG_TAG, "Sending password expiration notifications for action "
|
||||
+ action + " for user " + userHandle);
|
||||
if (VERBOSE_LOG) {
|
||||
Slog.v(LOG_TAG, "Sending password expiration notifications for action "
|
||||
+ action + " for user " + userHandle);
|
||||
}
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -1014,7 +1018,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
|
||||
private void handlePackagesChanged(String packageName, int userHandle) {
|
||||
boolean removed = false;
|
||||
if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
|
||||
if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
|
||||
DevicePolicyData policy = getUserData(userHandle);
|
||||
synchronized (this) {
|
||||
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
|
||||
@@ -1079,6 +1083,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
return UserManager.get(mContext);
|
||||
}
|
||||
|
||||
UserManagerInternal getUserManagerInternal() {
|
||||
return LocalServices.getService(UserManagerInternal.class);
|
||||
}
|
||||
|
||||
NotificationManager getNotificationManager() {
|
||||
return mContext.getSystemService(NotificationManager.class);
|
||||
}
|
||||
@@ -1233,6 +1241,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
mOwners = Preconditions.checkNotNull(injector.newOwners());
|
||||
|
||||
mUserManager = Preconditions.checkNotNull(injector.getUserManager());
|
||||
mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal());
|
||||
mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
|
||||
|
||||
mLocalService = new LocalService();
|
||||
@@ -1327,10 +1336,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
synchronized (this) {
|
||||
mOwners.load();
|
||||
findOwnerComponentIfNecessaryLocked();
|
||||
migrateUserRestrictionsIfNecessaryLocked();
|
||||
|
||||
// TODO PO may not have a class name either due to b/17652534. Address that too.
|
||||
|
||||
updateDeviceOwnerLocked();
|
||||
|
||||
// TODO Notify UM to update restrictions (?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1350,14 +1362,113 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
if (doComponent == null) {
|
||||
Slog.e(LOG_TAG, "Device-owner isn't registered as device-admin");
|
||||
} else {
|
||||
mOwners.setDeviceOwner(
|
||||
mOwners.setDeviceOwnerWithRestrictionsMigrated(
|
||||
doComponent,
|
||||
mOwners.getDeviceOwnerName(),
|
||||
mOwners.getDeviceOwnerUserId());
|
||||
mOwners.getDeviceOwnerUserId(),
|
||||
!mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
mOwners.writeDeviceOwner();
|
||||
if (VERBOSE_LOG) {
|
||||
Log.v(LOG_TAG, "Device owner component filled in");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We didn't use to persist user restrictions for each owners but only persisted in user
|
||||
* manager.
|
||||
*/
|
||||
private void migrateUserRestrictionsIfNecessaryLocked() {
|
||||
boolean migrated = false;
|
||||
// Migrate for the DO. Basically all restrictions should be considered to be set by DO,
|
||||
// except for the "system controlled" ones.
|
||||
if (mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()) {
|
||||
if (VERBOSE_LOG) {
|
||||
Log.v(LOG_TAG, "Migrating DO user restrictions");
|
||||
}
|
||||
migrated = true;
|
||||
|
||||
// Migrate user 0 restrictions to DO, except for "system" restrictions.
|
||||
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
|
||||
|
||||
migrateUserRestrictionsForUser(UserHandle.SYSTEM, deviceOwnerAdmin,
|
||||
/* exceptionList =*/ UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS);
|
||||
|
||||
mOwners.setDeviceOwnerUserRestrictionsMigrated();
|
||||
}
|
||||
|
||||
// Migrate for POs. We have a few more exceptions.
|
||||
final Set<String> normalExceptionList = Sets.newArraySet(
|
||||
UserManager.DISALLOW_OUTGOING_CALLS,
|
||||
UserManager.DISALLOW_SMS);
|
||||
normalExceptionList.addAll(UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS);
|
||||
|
||||
final Set<String> managedExceptionList = new ArraySet<>(normalExceptionList.size() + 1);
|
||||
managedExceptionList.addAll(normalExceptionList);
|
||||
managedExceptionList.add(UserManager.DISALLOW_WALLPAPER);
|
||||
|
||||
for (UserInfo ui : mUserManager.getUsers()) {
|
||||
final int userId = ui.id;
|
||||
if (mOwners.getProfileOwnerUserRestrictionsNeedsMigration(userId)) {
|
||||
if (userId != UserHandle.USER_SYSTEM) {
|
||||
if (VERBOSE_LOG) {
|
||||
Log.v(LOG_TAG, "Migrating PO user restrictions for user " + userId);
|
||||
}
|
||||
migrated = true;
|
||||
|
||||
final ActiveAdmin profileOwnerAdmin = getProfileOwnerAdminLocked(userId);
|
||||
|
||||
final Set<String> exceptionList =
|
||||
ui.isManagedProfile() ? managedExceptionList : normalExceptionList;
|
||||
|
||||
migrateUserRestrictionsForUser(ui.getUserHandle(), profileOwnerAdmin,
|
||||
exceptionList);
|
||||
}
|
||||
|
||||
mOwners.setProfileOwnerUserRestrictionsMigrated(userId);
|
||||
}
|
||||
}
|
||||
if (VERBOSE_LOG && migrated) {
|
||||
Log.v(LOG_TAG, "User restrictions migrated.");
|
||||
}
|
||||
}
|
||||
|
||||
private void migrateUserRestrictionsForUser(UserHandle user, ActiveAdmin admin,
|
||||
Set<String> exceptionList) {
|
||||
final Bundle origRestrictions = mUserManagerInternal.getBaseUserRestrictions(
|
||||
user.getIdentifier());
|
||||
|
||||
final Bundle newSystemRestrictions = new Bundle();
|
||||
final Bundle newOwnerRestrictions = new Bundle();
|
||||
|
||||
for (String key : origRestrictions.keySet()) {
|
||||
if (!origRestrictions.getBoolean(key)) {
|
||||
continue;
|
||||
}
|
||||
if (exceptionList.contains(key)) {
|
||||
newSystemRestrictions.putBoolean(key, true);
|
||||
} else {
|
||||
newOwnerRestrictions.putBoolean(key, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (VERBOSE_LOG) {
|
||||
Log.v(LOG_TAG, "origRestrictions=" + origRestrictions);
|
||||
Log.v(LOG_TAG, "newSystemRestrictions=" + newSystemRestrictions);
|
||||
Log.v(LOG_TAG, "newOwnerRestrictions=" + newOwnerRestrictions);
|
||||
}
|
||||
mUserManagerInternal.setBaseUserRestrictionsByDpmsForMigration(user.getIdentifier(),
|
||||
newSystemRestrictions);
|
||||
|
||||
if (admin != null) {
|
||||
admin.ensureUserRestrictions().clear();
|
||||
admin.ensureUserRestrictions().putAll(newOwnerRestrictions);
|
||||
} else {
|
||||
Slog.w(LOG_TAG, "ActiveAdmin for DO/PO not found. user=" + user.getIdentifier());
|
||||
}
|
||||
saveSettingsLocked(user.getIdentifier());
|
||||
}
|
||||
|
||||
private ComponentName findAdminComponentWithPackageLocked(String packageName, int userId) {
|
||||
final DevicePolicyData policy = getUserData(userId);
|
||||
final int n = policy.mAdminList.size();
|
||||
@@ -1373,7 +1484,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
nFound++;
|
||||
}
|
||||
}
|
||||
if (nFound > 0) {
|
||||
if (nFound > 1) {
|
||||
Slog.w(LOG_TAG, "Multiple DA found; assume the first one is DO.");
|
||||
}
|
||||
return found;
|
||||
@@ -1636,6 +1747,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
? mInjector.getDevicePolicyFilePathForSystemUser() + DEVICE_POLICIES_XML
|
||||
: new File(mInjector.environmentGetUserSystemDirectory(userHandle),
|
||||
DEVICE_POLICIES_XML).getAbsolutePath();
|
||||
if (VERBOSE_LOG) {
|
||||
Log.v(LOG_TAG, "Opening " + base);
|
||||
}
|
||||
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
||||
}
|
||||
|
||||
@@ -1808,7 +1922,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
try {
|
||||
DeviceAdminInfo dai = findAdmin(
|
||||
ComponentName.unflattenFromString(name), userHandle);
|
||||
if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
|
||||
if (VERBOSE_LOG
|
||||
&& (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
|
||||
!= userHandle)) {
|
||||
Slog.w(LOG_TAG, "findAdmin returned an incorrect uid "
|
||||
+ dai.getActivityInfo().applicationInfo.uid + " for user "
|
||||
@@ -1988,8 +2103,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
long token = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
String value = cameraDisabled ? "1" : "0";
|
||||
if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
|
||||
+ cameraPropertyForUser + "] = " + value);
|
||||
if (VERBOSE_LOG) {
|
||||
Slog.v(LOG_TAG, "Change in camera state ["
|
||||
+ cameraPropertyForUser + "] = " + value);
|
||||
}
|
||||
mInjector.systemPropertiesSet(cameraPropertyForUser, value);
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(token);
|
||||
@@ -4513,8 +4630,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
UserHandle callingUser = mInjector.binderGetCallingUserHandle();
|
||||
// Check if this is the profile owner who is calling
|
||||
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||
final ActiveAdmin admin =
|
||||
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||
synchronized (this) {
|
||||
admin.userRestrictions = null;
|
||||
clearUserPoliciesLocked(callingUser);
|
||||
final int userId = callingUser.getIdentifier();
|
||||
mOwners.removeProfileOwner(userId);
|
||||
@@ -4533,38 +4652,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
|
||||
final long ident = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
clearUserRestrictions(userHandle);
|
||||
mIPackageManager.updatePermissionFlagsForAllApps(
|
||||
PackageManager.FLAG_PERMISSION_POLICY_FIXED,
|
||||
0 /* flagValues */, userHandle.getIdentifier());
|
||||
// TODO This will not revert audio mute restrictions if they were set. b/24981972
|
||||
synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
|
||||
mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle.getIdentifier());
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void clearUserRestrictions(UserHandle userHandle) {
|
||||
Bundle userRestrictions = mUserManager.getUserRestrictions();
|
||||
mUserManager.setUserRestrictions(new Bundle(), userHandle);
|
||||
if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) {
|
||||
try {
|
||||
mInjector.getIAudioService().setMasterMute(true, 0, mContext.getPackageName(),
|
||||
userHandle.getIdentifier());
|
||||
} catch (RemoteException e) {
|
||||
// Not much we can do here.
|
||||
}
|
||||
}
|
||||
if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) {
|
||||
try {
|
||||
mInjector.getIAudioService().setMicrophoneMute(true, mContext.getPackageName(),
|
||||
userHandle.getIdentifier());
|
||||
} catch (RemoteException e) {
|
||||
// Not much we can do here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasUserSetupCompleted() {
|
||||
return hasUserSetupCompleted(UserHandle.getCallingUserId());
|
||||
@@ -5503,95 +5603,123 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
|
||||
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
|
||||
Preconditions.checkNotNull(who, "ComponentName is null");
|
||||
final int userHandle = mInjector.userHandleGetCallingUserId();
|
||||
final UserHandle user = new UserHandle(userHandle);
|
||||
synchronized (this) {
|
||||
ActiveAdmin activeAdmin =
|
||||
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||
boolean isDeviceOwner = isDeviceOwner(who);
|
||||
if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
|
||||
&& DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
|
||||
throw new SecurityException("Profile owners cannot set user restriction " + key);
|
||||
}
|
||||
if (IMMUTABLE_USER_RESTRICTIONS.contains(key)) {
|
||||
throw new SecurityException("User restriction " + key + " cannot be changed");
|
||||
}
|
||||
boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
|
||||
synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
|
||||
synchronized (this) {
|
||||
ActiveAdmin activeAdmin =
|
||||
getActiveAdminForCallerLocked(who,
|
||||
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
|
||||
boolean isDeviceOwner = isDeviceOwner(who);
|
||||
if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
|
||||
&& DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
|
||||
throw new SecurityException(
|
||||
"Profile owners cannot set user restriction " + key);
|
||||
}
|
||||
if (IMMUTABLE_USER_RESTRICTIONS.contains(key)) {
|
||||
throw new SecurityException("User restriction " + key + " cannot be changed");
|
||||
}
|
||||
|
||||
long id = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
if (enabled && !alreadyRestricted) {
|
||||
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMicrophoneMute(true, mContext.getPackageName(), userHandle);
|
||||
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMasterMute(true, 0, mContext.getPackageName(), userHandle);
|
||||
} else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
|
||||
mInjector.settingsSecurePutIntForUser(
|
||||
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
|
||||
mInjector.settingsSecurePutIntForUser(
|
||||
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF,
|
||||
userHandle);
|
||||
mInjector.settingsSecurePutStringForUser(
|
||||
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
|
||||
// Only disable adb if changing for system user, since it is global
|
||||
// TODO: should this be admin user?
|
||||
if (userHandle == UserHandle.USER_SYSTEM) {
|
||||
final long id = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
// Original value.
|
||||
final boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
|
||||
|
||||
// Save the restriction to ActiveAdmin.
|
||||
// TODO When DO sets a restriction, it'll always be treated as device-wide.
|
||||
// If there'll be a policy that can be set by both, we'll need scoping support,
|
||||
// and need to have another Bundle in DO active admin to hold restrictions as
|
||||
// PO.
|
||||
activeAdmin.ensureUserRestrictions().putBoolean(key, enabledFromThisOwner);
|
||||
saveSettingsLocked(userHandle);
|
||||
|
||||
// Tell UserManager the new value. Note this needs to be done before calling
|
||||
// into AudioService, because AS will check AppOps that'll be updated by UM.
|
||||
if (isDeviceOwner) {
|
||||
mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersRL();
|
||||
} else {
|
||||
mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle);
|
||||
}
|
||||
|
||||
// New value.
|
||||
final boolean enabled = mUserManager.hasUserRestriction(key, user);
|
||||
|
||||
// TODO The rest of the code should move to UserManagerService.
|
||||
|
||||
if (enabled && !alreadyRestricted) {
|
||||
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMicrophoneMute(true, mContext.getPackageName(), userHandle);
|
||||
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMasterMute(true, 0, mContext.getPackageName(), userHandle);
|
||||
} else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
|
||||
mInjector.settingsSecurePutIntForUser(
|
||||
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
|
||||
mInjector.settingsSecurePutIntForUser(
|
||||
Settings.Secure.LOCATION_MODE,
|
||||
Settings.Secure.LOCATION_MODE_OFF,
|
||||
userHandle);
|
||||
mInjector.settingsSecurePutStringForUser(
|
||||
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
|
||||
// Only disable adb if changing for system user, since it is global
|
||||
// TODO: should this be admin user?
|
||||
if (userHandle == UserHandle.USER_SYSTEM) {
|
||||
mInjector.settingsGlobalPutStringForUser(
|
||||
Settings.Global.ADB_ENABLED, "0", userHandle);
|
||||
}
|
||||
} else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
|
||||
mInjector.settingsGlobalPutStringForUser(
|
||||
Settings.Global.ADB_ENABLED, "0", userHandle);
|
||||
Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
|
||||
userHandle);
|
||||
mInjector.settingsGlobalPutStringForUser(
|
||||
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
|
||||
mInjector.settingsSecurePutIntForUser(
|
||||
Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
|
||||
userHandle);
|
||||
}
|
||||
} else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
|
||||
mInjector.settingsGlobalPutStringForUser(
|
||||
Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
|
||||
userHandle);
|
||||
mInjector.settingsGlobalPutStringForUser(
|
||||
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
|
||||
mInjector.settingsSecurePutIntForUser(
|
||||
Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
|
||||
userHandle);
|
||||
}
|
||||
}
|
||||
mUserManager.setUserRestriction(key, enabled, user);
|
||||
activeAdmin.ensureUserRestrictions().putBoolean(key, enabled);
|
||||
saveSettingsLocked(userHandle);
|
||||
|
||||
if (enabled != alreadyRestricted) {
|
||||
if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
|
||||
// Send out notifications however as some clients may want to reread the
|
||||
// value which actually changed due to a restriction having been applied.
|
||||
final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
|
||||
long version = mInjector.systemPropertiesGetLong(property, 0) + 1;
|
||||
mInjector.systemPropertiesSet(property, Long.toString(version));
|
||||
if (enabled != alreadyRestricted) {
|
||||
if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
|
||||
// Send out notifications however as some clients may want to reread the
|
||||
// value which actually changed due to a restriction having been
|
||||
// applied.
|
||||
final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
|
||||
long version = mInjector.systemPropertiesGetLong(property, 0) + 1;
|
||||
mInjector.systemPropertiesSet(property, Long.toString(version));
|
||||
|
||||
final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
|
||||
Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
|
||||
mContext.getContentResolver().notifyChange(url, null, true, userHandle);
|
||||
final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
|
||||
Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
|
||||
mContext.getContentResolver().notifyChange(url, null, true, userHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!enabled && alreadyRestricted) {
|
||||
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMicrophoneMute(false, mContext.getPackageName(), userHandle);
|
||||
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMasterMute(false, 0, mContext.getPackageName(), userHandle);
|
||||
if (!enabled && alreadyRestricted) {
|
||||
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMicrophoneMute(false, mContext.getPackageName(),
|
||||
userHandle);
|
||||
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
|
||||
mInjector.getIAudioService()
|
||||
.setMasterMute(false, 0, mContext.getPackageName(), userHandle);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(id);
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(id);
|
||||
|
||||
sendChangedNotification(userHandle);
|
||||
}
|
||||
sendChangedNotification(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5650,7 +5778,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
long id = mInjector.binderClearCallingIdentity();
|
||||
|
||||
try {
|
||||
if (DBG) {
|
||||
if (VERBOSE_LOG) {
|
||||
Slog.v(LOG_TAG, "installing " + packageName + " for "
|
||||
+ userId);
|
||||
}
|
||||
@@ -5705,7 +5833,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
0, // no flags
|
||||
primaryUser.id);
|
||||
|
||||
if (DBG) Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
|
||||
if (VERBOSE_LOG) {
|
||||
Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
|
||||
}
|
||||
int numberOfAppsInstalled = 0;
|
||||
if (activitiesToEnable != null) {
|
||||
for (ResolveInfo info : activitiesToEnable) {
|
||||
@@ -6275,7 +6405,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private final class LocalService extends DevicePolicyManagerInternal {
|
||||
@VisibleForTesting
|
||||
final class LocalService extends DevicePolicyManagerInternal {
|
||||
private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners;
|
||||
|
||||
@Override
|
||||
@@ -6322,6 +6453,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getComposedUserRestrictions(int userId, Bundle inBundle) {
|
||||
synchronized (DevicePolicyManagerService.this) {
|
||||
final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
|
||||
final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
|
||||
|
||||
final Bundle deviceOwnerRestrictions =
|
||||
deviceOwner == null ? null : deviceOwner.userRestrictions;
|
||||
final Bundle profileOwnerRestrictions =
|
||||
profileOwner == null ? null : profileOwner.userRestrictions;
|
||||
|
||||
if (deviceOwnerRestrictions == null && profileOwnerRestrictions == null) {
|
||||
// No restrictions to merge.
|
||||
return inBundle;
|
||||
}
|
||||
|
||||
final Bundle composed = new Bundle(inBundle);
|
||||
UserRestrictionsUtils.merge(composed, deviceOwnerRestrictions);
|
||||
UserRestrictionsUtils.merge(composed, profileOwnerRestrictions);
|
||||
|
||||
return composed;
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
|
||||
final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
|
||||
synchronized (DevicePolicyManagerService.this) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -75,6 +74,7 @@ class Owners {
|
||||
private static final String ATTR_PACKAGE = "package";
|
||||
private static final String ATTR_COMPONENT_NAME = "component";
|
||||
private static final String ATTR_USERID = "userId";
|
||||
private static final String ATTR_USER_RESTRICTIONS_MIGRATED = "userRestrictionsMigrated";
|
||||
|
||||
private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy";
|
||||
|
||||
@@ -155,7 +155,16 @@ class Owners {
|
||||
Slog.e(TAG, "Invalid user id for device owner user: " + userId);
|
||||
return;
|
||||
}
|
||||
mDeviceOwner = new OwnerInfo(ownerName, admin);
|
||||
// For a newly set DO, there's no need for migration.
|
||||
setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId,
|
||||
/* userRestrictionsMigrated =*/ true);
|
||||
}
|
||||
|
||||
// Note this should be only called during migration. Normally when DO is set,
|
||||
// userRestrictionsMigrated should always be true.
|
||||
void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId,
|
||||
boolean userRestrictionsMigrated) {
|
||||
mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated);
|
||||
mDeviceOwnerUserId = userId;
|
||||
}
|
||||
|
||||
@@ -165,7 +174,9 @@ class Owners {
|
||||
}
|
||||
|
||||
void setProfileOwner(ComponentName admin, String ownerName, int userId) {
|
||||
mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
|
||||
// For a newly set PO, there's no need for migration.
|
||||
mProfileOwners.put(userId, new OwnerInfo(ownerName, admin,
|
||||
/* userRestrictionsMigrated =*/ true));
|
||||
}
|
||||
|
||||
void removeProfileOwner(int userId) {
|
||||
@@ -207,6 +218,38 @@ class Owners {
|
||||
return mDeviceOwner != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if user restrictions need to be migrated for DO.
|
||||
*/
|
||||
boolean getDeviceOwnerUserRestrictionsNeedsMigration() {
|
||||
return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if user restrictions need to be migrated for PO.
|
||||
*/
|
||||
boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) {
|
||||
OwnerInfo profileOwner = mProfileOwners.get(userId);
|
||||
return profileOwner != null && !profileOwner.userRestrictionsMigrated;
|
||||
}
|
||||
|
||||
/** Sets the user restrictions migrated flag, and also writes to the file. */
|
||||
void setDeviceOwnerUserRestrictionsMigrated() {
|
||||
if (mDeviceOwner != null) {
|
||||
mDeviceOwner.userRestrictionsMigrated = true;
|
||||
}
|
||||
writeDeviceOwner();
|
||||
}
|
||||
|
||||
/** Sets the user restrictions migrated flag, and also writes to the file. */
|
||||
void setProfileOwnerUserRestrictionsMigrated(int userId) {
|
||||
OwnerInfo profileOwner = mProfileOwners.get(userId);
|
||||
if (profileOwner != null) {
|
||||
profileOwner.userRestrictionsMigrated = true;
|
||||
}
|
||||
writeProfileOwner(userId);
|
||||
}
|
||||
|
||||
private boolean readLegacyOwnerFile(File file) {
|
||||
if (!file.exists()) {
|
||||
// Already migrated or the device has no owners.
|
||||
@@ -226,7 +269,8 @@ class Owners {
|
||||
if (tag.equals(TAG_DEVICE_OWNER)) {
|
||||
String name = parser.getAttributeValue(null, ATTR_NAME);
|
||||
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
|
||||
mDeviceOwner = new OwnerInfo(name, packageName);
|
||||
mDeviceOwner = new OwnerInfo(name, packageName,
|
||||
/* userRestrictionsMigrated =*/ false);
|
||||
mDeviceOwnerUserId = UserHandle.USER_SYSTEM;
|
||||
} else if (tag.equals(TAG_DEVICE_INITIALIZER)) {
|
||||
// Deprecated tag
|
||||
@@ -241,7 +285,8 @@ class Owners {
|
||||
ComponentName admin = ComponentName.unflattenFromString(
|
||||
profileOwnerComponentStr);
|
||||
if (admin != null) {
|
||||
profileOwnerInfo = new OwnerInfo(profileOwnerName, admin);
|
||||
profileOwnerInfo = new OwnerInfo(profileOwnerName, admin,
|
||||
/* userRestrictionsMigrated =*/ false);
|
||||
} else {
|
||||
// This shouldn't happen but switch from package name -> component name
|
||||
// might have written bad device owner files. b/17652534
|
||||
@@ -250,7 +295,8 @@ class Owners {
|
||||
}
|
||||
}
|
||||
if (profileOwnerInfo == null) {
|
||||
profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName);
|
||||
profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName,
|
||||
/* userRestrictionsMigrated =*/ false);
|
||||
}
|
||||
mProfileOwners.put(userId, profileOwnerInfo);
|
||||
} else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) {
|
||||
@@ -503,21 +549,24 @@ class Owners {
|
||||
}
|
||||
}
|
||||
|
||||
private static class OwnerInfo {
|
||||
static class OwnerInfo {
|
||||
public final String name;
|
||||
public final String packageName;
|
||||
public final ComponentName admin;
|
||||
public boolean userRestrictionsMigrated;
|
||||
|
||||
public OwnerInfo(String name, String packageName) {
|
||||
public OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated) {
|
||||
this.name = name;
|
||||
this.packageName = packageName;
|
||||
this.admin = new ComponentName(packageName, "");
|
||||
this.userRestrictionsMigrated = userRestrictionsMigrated;
|
||||
}
|
||||
|
||||
public OwnerInfo(String name, ComponentName admin) {
|
||||
public OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated) {
|
||||
this.name = name;
|
||||
this.admin = admin;
|
||||
this.packageName = admin.getPackageName();
|
||||
this.userRestrictionsMigrated = userRestrictionsMigrated;
|
||||
}
|
||||
|
||||
public void writeToXml(XmlSerializer out, String tag) throws IOException {
|
||||
@@ -529,6 +578,8 @@ class Owners {
|
||||
if (admin != null) {
|
||||
out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString());
|
||||
}
|
||||
out.attribute(null, ATTR_USER_RESTRICTIONS_MIGRATED,
|
||||
String.valueOf(userRestrictionsMigrated));
|
||||
out.endTag(null, tag);
|
||||
}
|
||||
|
||||
@@ -537,12 +588,16 @@ class Owners {
|
||||
final String name = parser.getAttributeValue(null, ATTR_NAME);
|
||||
final String componentName =
|
||||
parser.getAttributeValue(null, ATTR_COMPONENT_NAME);
|
||||
final String userRestrictionsMigratedStr =
|
||||
parser.getAttributeValue(null, ATTR_USER_RESTRICTIONS_MIGRATED);
|
||||
final boolean userRestrictionsMigrated =
|
||||
("true".equals(userRestrictionsMigratedStr));
|
||||
|
||||
// Has component name? If so, return [name, component]
|
||||
if (componentName != null) {
|
||||
final ComponentName admin = ComponentName.unflattenFromString(componentName);
|
||||
if (admin != null) {
|
||||
return new OwnerInfo(name, admin);
|
||||
return new OwnerInfo(name, admin, userRestrictionsMigrated);
|
||||
} else {
|
||||
// This shouldn't happen but switch from package name -> component name
|
||||
// might have written bad device owner files. b/17652534
|
||||
@@ -552,7 +607,7 @@ class Owners {
|
||||
}
|
||||
|
||||
// Else, build with [name, package]
|
||||
return new OwnerInfo(name, packageName);
|
||||
return new OwnerInfo(name, packageName, userRestrictionsMigrated);
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter pw) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<device-owner package="com.android.frameworks.servicestests" />
|
||||
<profile-owner package="com.android.frameworks.servicestests" name="0" userId="10" component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin2" />
|
||||
<profile-owner package="com.android.frameworks.servicestests" name="0" userId="11" component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin3" />
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<policies setup-complete="true">
|
||||
<admin name="com.google.android.gms/com.google.android.gms.mdm.receivers.MdmDeviceAdminReceiver">
|
||||
</admin>
|
||||
<admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
|
||||
</admin>
|
||||
</policies>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<policies setup-complete="true">
|
||||
<admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin2">
|
||||
</admin>
|
||||
</policies>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||
<policies setup-complete="true">
|
||||
<admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin3">
|
||||
</admin>
|
||||
</policies>
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
|
||||
private DpmMockContext mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mContext = getContext();
|
||||
|
||||
when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
|
||||
.thenReturn(true);
|
||||
}
|
||||
|
||||
public void testMigration() throws Exception {
|
||||
final File user10dir = mMockContext.addUser(10, 0);
|
||||
final File user11dir = mMockContext.addUser(11, UserInfo.FLAG_MANAGED_PROFILE);
|
||||
final File user12dir = mMockContext.addUser(12, 0);
|
||||
|
||||
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
|
||||
setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123));
|
||||
setUpPackageManagerForAdmin(admin3, UserHandle.getUid(11, 456));
|
||||
|
||||
// Create the legacy owners & policies file.
|
||||
DpmTestUtils.writeToFile(
|
||||
(new File(mContext.dataDir, OwnersTestable.LEGACY_FILE)).getAbsoluteFile(),
|
||||
DpmTestUtils.readAsset(mRealTestContext,
|
||||
"DevicePolicyManagerServiceMigrationTest/legacy_device_owner.xml"));
|
||||
|
||||
DpmTestUtils.writeToFile(
|
||||
(new File(mContext.systemUserDataDir, "device_policies.xml")).getAbsoluteFile(),
|
||||
DpmTestUtils.readAsset(mRealTestContext,
|
||||
"DevicePolicyManagerServiceMigrationTest/legacy_device_policies.xml"));
|
||||
|
||||
DpmTestUtils.writeToFile(
|
||||
(new File(user10dir, "device_policies.xml")).getAbsoluteFile(),
|
||||
DpmTestUtils.readAsset(mRealTestContext,
|
||||
"DevicePolicyManagerServiceMigrationTest/legacy_device_policies_10.xml"));
|
||||
DpmTestUtils.writeToFile(
|
||||
(new File(user11dir, "device_policies.xml")).getAbsoluteFile(),
|
||||
DpmTestUtils.readAsset(mRealTestContext,
|
||||
"DevicePolicyManagerServiceMigrationTest/legacy_device_policies_11.xml"));
|
||||
|
||||
// Set up UserManager
|
||||
when(mMockContext.userManagerInternal.getBaseUserRestrictions(
|
||||
eq(UserHandle.USER_SYSTEM))).thenReturn(DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_ADD_USER,
|
||||
UserManager.DISALLOW_RECORD_AUDIO));
|
||||
|
||||
when(mMockContext.userManagerInternal.getBaseUserRestrictions(
|
||||
eq(10))).thenReturn(DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_REMOVE_USER,
|
||||
UserManager.DISALLOW_SMS,
|
||||
UserManager.DISALLOW_OUTGOING_CALLS,
|
||||
UserManager.DISALLOW_WALLPAPER,
|
||||
UserManager.DISALLOW_RECORD_AUDIO));
|
||||
|
||||
when(mMockContext.userManagerInternal.getBaseUserRestrictions(
|
||||
eq(11))).thenReturn(DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_REMOVE_USER,
|
||||
UserManager.DISALLOW_SMS,
|
||||
UserManager.DISALLOW_OUTGOING_CALLS,
|
||||
UserManager.DISALLOW_WALLPAPER,
|
||||
UserManager.DISALLOW_RECORD_AUDIO));
|
||||
|
||||
final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
Integer userId = (Integer) invocation.getArguments()[0];
|
||||
Bundle bundle = (Bundle) invocation.getArguments()[1];
|
||||
|
||||
newBaseRestrictions.put(userId, bundle);
|
||||
|
||||
return null;
|
||||
}
|
||||
}).when(mContext.userManagerInternal).setBaseUserRestrictionsByDpmsForMigration(
|
||||
anyInt(), any(Bundle.class));
|
||||
|
||||
// Initialize DPM/DPMS and let it migrate the persisted information.
|
||||
// (Need clearCallingIdentity() to pass permission checks.)
|
||||
|
||||
final DevicePolicyManagerServiceTestable dpms;
|
||||
|
||||
final long ident = mContext.binder.clearCallingIdentity();
|
||||
try {
|
||||
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
|
||||
|
||||
dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
|
||||
|
||||
dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY);
|
||||
dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED);
|
||||
} finally {
|
||||
mContext.binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
|
||||
// Now all information should be migrated.
|
||||
assertFalse(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12));
|
||||
|
||||
// Check the new base restrictions.
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_RECORD_AUDIO
|
||||
),
|
||||
newBaseRestrictions.get(UserHandle.USER_SYSTEM));
|
||||
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_SMS,
|
||||
UserManager.DISALLOW_OUTGOING_CALLS,
|
||||
UserManager.DISALLOW_RECORD_AUDIO
|
||||
),
|
||||
newBaseRestrictions.get(10));
|
||||
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_SMS,
|
||||
UserManager.DISALLOW_OUTGOING_CALLS,
|
||||
UserManager.DISALLOW_WALLPAPER,
|
||||
UserManager.DISALLOW_RECORD_AUDIO
|
||||
),
|
||||
newBaseRestrictions.get(11));
|
||||
|
||||
// Check the new owner restrictions.
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_ADD_USER
|
||||
),
|
||||
dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions());
|
||||
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_REMOVE_USER,
|
||||
UserManager.DISALLOW_WALLPAPER
|
||||
),
|
||||
dpms.getProfileOwnerAdminLocked(10).ensureUserRestrictions());
|
||||
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_REMOVE_USER
|
||||
),
|
||||
dpms.getProfileOwnerAdminLocked(11).ensureUserRestrictions());
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import android.os.Looper;
|
||||
import android.os.PowerManagerInternal;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.UserManagerInternal;
|
||||
import android.view.IWindowManager;
|
||||
|
||||
import java.io.File;
|
||||
@@ -106,6 +107,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
|
||||
return context.userManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
UserManagerInternal getUserManagerInternal() {
|
||||
return context.userManagerInternal;
|
||||
}
|
||||
|
||||
@Override
|
||||
PowerManagerInternal getPowerManagerInternal() {
|
||||
return context.powerManagerInternal;
|
||||
@@ -153,7 +159,7 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
|
||||
|
||||
@Override
|
||||
String getDevicePolicyFilePathForSystemUser() {
|
||||
return context.systemUserDataDir.getAbsolutePath();
|
||||
return context.systemUserDataDir.getAbsolutePath() + "/";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
@@ -70,9 +69,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
private DpmMockContext mContext;
|
||||
public DevicePolicyManager dpm;
|
||||
public DevicePolicyManagerServiceTestable dpms;
|
||||
public ComponentName admin1;
|
||||
public ComponentName admin2;
|
||||
public ComponentName admin3;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
@@ -85,10 +81,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
|
||||
initializeDpms();
|
||||
|
||||
admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
|
||||
admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
|
||||
admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
|
||||
|
||||
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
|
||||
setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
|
||||
setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_UID);
|
||||
@@ -113,67 +105,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpPackageManagerForAdmin(ComponentName admin, int packageUid) throws Exception {
|
||||
setUpPackageManagerForAdmin(admin, packageUid,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
|
||||
}
|
||||
|
||||
private void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
|
||||
int enabledSetting) throws Exception {
|
||||
|
||||
// Set up queryBroadcastReceivers().
|
||||
|
||||
final Intent resolveIntent = new Intent();
|
||||
resolveIntent.setComponent(admin);
|
||||
final List<ResolveInfo> realResolveInfo =
|
||||
mRealTestContext.getPackageManager().queryBroadcastReceivers(
|
||||
resolveIntent,
|
||||
PackageManager.GET_META_DATA);
|
||||
assertNotNull(realResolveInfo);
|
||||
assertEquals(1, realResolveInfo.size());
|
||||
|
||||
// We need to change AI, so set a clone.
|
||||
realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
|
||||
|
||||
// We need to rewrite the UID in the activity info.
|
||||
realResolveInfo.get(0).activityInfo.applicationInfo.uid = packageUid;
|
||||
|
||||
doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
|
||||
MockUtils.checkIntentComponent(admin),
|
||||
eq(PackageManager.GET_META_DATA
|
||||
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
|
||||
eq(UserHandle.getUserId(packageUid)));
|
||||
|
||||
// Set up getApplicationInfo().
|
||||
|
||||
final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
|
||||
mRealTestContext.getPackageManager().getApplicationInfo(
|
||||
admin1.getPackageName(),
|
||||
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
|
||||
|
||||
ai.enabledSetting = enabledSetting;
|
||||
ai.uid = packageUid;
|
||||
|
||||
doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
|
||||
eq(admin1.getPackageName()),
|
||||
eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
|
||||
eq(UserHandle.getUserId(packageUid)));
|
||||
|
||||
// Set up getPackageInfo().
|
||||
|
||||
final PackageInfo pi = DpmTestUtils.cloneParcelable(
|
||||
mRealTestContext.getPackageManager().getPackageInfo(
|
||||
admin1.getPackageName(), 0));
|
||||
assertTrue(pi.applicationInfo.flags != 0);
|
||||
|
||||
pi.applicationInfo.uid = packageUid;
|
||||
|
||||
doReturn(pi).when(mContext.ipackageManager).getPackageInfo(
|
||||
eq(admin1.getPackageName()),
|
||||
eq(0),
|
||||
eq(UserHandle.getUserId(packageUid)));
|
||||
}
|
||||
|
||||
private void setUpUserManager() {
|
||||
// Emulate UserManager.set/getApplicationRestriction().
|
||||
final Map<Pair<String, UserHandle>, Bundle> appRestrictions = new HashMap<>();
|
||||
@@ -220,7 +151,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
assertTrue(dpm.setProfileOwner(admin, "owner-name", DpmMockContext.CALLER_USER_HANDLE));
|
||||
|
||||
// Check
|
||||
assertEquals(admin1, dpm.getProfileOwnerAsUser(DpmMockContext.CALLER_USER_HANDLE));
|
||||
assertEquals(admin, dpm.getProfileOwnerAsUser(DpmMockContext.CALLER_USER_HANDLE));
|
||||
}
|
||||
|
||||
public void testHasNoFeature() throws Exception {
|
||||
@@ -743,6 +674,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
assertEquals("", dpms.getDeviceOwner().getClassName());
|
||||
|
||||
// Then create a new DPMS to have it load the settings from files.
|
||||
when(mContext.userManager.getUserRestrictions(any(UserHandle.class)))
|
||||
.thenReturn(new Bundle());
|
||||
initializeDpms();
|
||||
|
||||
// Now the DO component name is a full name.
|
||||
@@ -802,32 +735,33 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
|
||||
UserHandle.USER_SYSTEM));
|
||||
|
||||
assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_SMS));
|
||||
assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(),
|
||||
dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
);
|
||||
|
||||
dpm.addUserRestriction(admin1, UserManager.DISALLOW_SMS);
|
||||
dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
|
||||
|
||||
assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_SMS));
|
||||
assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_SMS, UserManager.DISALLOW_OUTGOING_CALLS),
|
||||
dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
);
|
||||
|
||||
dpm.clearUserRestriction(admin1, UserManager.DISALLOW_SMS);
|
||||
|
||||
assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_SMS));
|
||||
assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
|
||||
dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
);
|
||||
|
||||
dpm.clearUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
|
||||
|
||||
assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_SMS));
|
||||
assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(),
|
||||
dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
|
||||
);
|
||||
|
||||
// TODO Check inner calls.
|
||||
// TODO Make sure restrictions are written to the file.
|
||||
@@ -836,42 +770,106 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
public void testSetUserRestriction_asPo() {
|
||||
setAsProfileOwner(admin1);
|
||||
|
||||
assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
|
||||
assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(),
|
||||
dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
);
|
||||
|
||||
dpm.addUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
|
||||
dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
|
||||
|
||||
assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
|
||||
assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
|
||||
UserManager.DISALLOW_OUTGOING_CALLS
|
||||
),
|
||||
dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
);
|
||||
|
||||
dpm.clearUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
|
||||
|
||||
assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
|
||||
assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(
|
||||
UserManager.DISALLOW_OUTGOING_CALLS
|
||||
),
|
||||
dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
);
|
||||
|
||||
dpm.clearUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
|
||||
|
||||
assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
|
||||
assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions(),
|
||||
dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
|
||||
.ensureUserRestrictions()
|
||||
);
|
||||
|
||||
// TODO Check inner calls.
|
||||
// TODO Make sure restrictions are written to the file.
|
||||
}
|
||||
|
||||
public void testGetComposedUserRestrictions_noDoNoPo() throws Exception {
|
||||
final Bundle in = DpmTestUtils.newRestrictions(UserManager.DISALLOW_OUTGOING_CALLS);
|
||||
|
||||
Bundle actual = dpms.mLocalService.getComposedUserRestrictions(
|
||||
UserHandle.USER_SYSTEM, in);
|
||||
assertTrue(in == actual);
|
||||
|
||||
actual = dpms.mLocalService.getComposedUserRestrictions(
|
||||
DpmMockContext.CALLER_USER_HANDLE, in);
|
||||
assertTrue(in == actual);
|
||||
}
|
||||
|
||||
public void testGetComposedUserRestrictions() throws Exception {
|
||||
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
|
||||
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
|
||||
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
// First, set DO.
|
||||
|
||||
// Call from a process on the system user.
|
||||
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
|
||||
|
||||
// Make sure admin1 is installed on system user.
|
||||
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
|
||||
|
||||
// Call.
|
||||
dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
|
||||
assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
|
||||
UserHandle.USER_SYSTEM));
|
||||
|
||||
dpm.addUserRestriction(admin1, "rest1");
|
||||
dpm.addUserRestriction(admin1, "rest2");
|
||||
|
||||
// Set PO on CALLER_USER_HANDLE.
|
||||
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
|
||||
|
||||
setAsProfileOwner(admin2);
|
||||
|
||||
dpm.addUserRestriction(admin2, "restA");
|
||||
dpm.addUserRestriction(admin2, "restB");
|
||||
|
||||
final Bundle in = DpmTestUtils.newRestrictions("abc");
|
||||
|
||||
Bundle actual = dpms.mLocalService.getComposedUserRestrictions(
|
||||
UserHandle.USER_SYSTEM, in);
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions("abc", "rest1", "rest2"),
|
||||
actual);
|
||||
|
||||
actual = dpms.mLocalService.getComposedUserRestrictions(
|
||||
DpmMockContext.CALLER_USER_HANDLE, in);
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions("abc", "rest1", "rest2", "restA", "restB"),
|
||||
actual);
|
||||
|
||||
actual = dpms.mLocalService.getComposedUserRestrictions(
|
||||
DpmMockContext.CALLER_USER_HANDLE + 1, in);
|
||||
DpmTestUtils.assertRestrictions(
|
||||
DpmTestUtils.newRestrictions("abc", "rest1", "rest2"),
|
||||
actual);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.os.PowerManager.WakeLock;
|
||||
import android.os.PowerManagerInternal;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.UserManagerInternal;
|
||||
import android.test.mock.MockContentResolver;
|
||||
import android.test.mock.MockContext;
|
||||
import android.view.IWindowManager;
|
||||
@@ -203,6 +204,7 @@ public class DpmMockContext extends MockContext {
|
||||
public final EnvironmentForMock environment;
|
||||
public final SystemPropertiesForMock systemProperties;
|
||||
public final UserManager userManager;
|
||||
public final UserManagerInternal userManagerInternal;
|
||||
public final UserManagerForMock userManagerForMock;
|
||||
public final PowerManagerForMock powerManager;
|
||||
public final PowerManagerInternal powerManagerInternal;
|
||||
@@ -233,6 +235,7 @@ public class DpmMockContext extends MockContext {
|
||||
environment = mock(EnvironmentForMock.class);
|
||||
systemProperties= mock(SystemPropertiesForMock.class);
|
||||
userManager = mock(UserManager.class);
|
||||
userManagerInternal = mock(UserManagerInternal.class);
|
||||
userManagerForMock = mock(UserManagerForMock.class);
|
||||
powerManager = mock(PowerManagerForMock.class);
|
||||
powerManagerInternal = mock(PowerManagerInternal.class);
|
||||
@@ -257,6 +260,9 @@ public class DpmMockContext extends MockContext {
|
||||
|
||||
// System user is always running.
|
||||
setUserRunning(UserHandle.USER_SYSTEM, true);
|
||||
|
||||
// This method must return an object.
|
||||
when(userManagerInternal.getUserRestrictionsLock()).thenReturn(new Object());
|
||||
}
|
||||
|
||||
public File addUser(int userId, int flags) {
|
||||
|
||||
@@ -16,10 +16,21 @@
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
public abstract class DpmTestBase extends AndroidTestCase {
|
||||
public static final String TAG = "DpmTest";
|
||||
@@ -29,6 +40,10 @@ public abstract class DpmTestBase extends AndroidTestCase {
|
||||
|
||||
public File dataDir;
|
||||
|
||||
public ComponentName admin1;
|
||||
public ComponentName admin2;
|
||||
public ComponentName admin3;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -37,10 +52,77 @@ public abstract class DpmTestBase extends AndroidTestCase {
|
||||
|
||||
mMockContext = new DpmMockContext(
|
||||
mRealTestContext, new File(mRealTestContext.getCacheDir(), "test-data"));
|
||||
|
||||
admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
|
||||
admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
|
||||
admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DpmMockContext getContext() {
|
||||
return mMockContext;
|
||||
}
|
||||
|
||||
|
||||
protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid)
|
||||
throws Exception {
|
||||
setUpPackageManagerForAdmin(admin, packageUid,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
|
||||
}
|
||||
|
||||
protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
|
||||
int enabledSetting) throws Exception {
|
||||
|
||||
// Set up queryBroadcastReceivers().
|
||||
|
||||
final Intent resolveIntent = new Intent();
|
||||
resolveIntent.setComponent(admin);
|
||||
final List<ResolveInfo> realResolveInfo =
|
||||
mRealTestContext.getPackageManager().queryBroadcastReceivers(
|
||||
resolveIntent,
|
||||
PackageManager.GET_META_DATA);
|
||||
assertNotNull(realResolveInfo);
|
||||
assertEquals(1, realResolveInfo.size());
|
||||
|
||||
// We need to change AI, so set a clone.
|
||||
realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
|
||||
|
||||
// We need to rewrite the UID in the activity info.
|
||||
realResolveInfo.get(0).activityInfo.applicationInfo.uid = packageUid;
|
||||
|
||||
doReturn(realResolveInfo).when(mMockContext.packageManager).queryBroadcastReceivers(
|
||||
MockUtils.checkIntentComponent(admin),
|
||||
eq(PackageManager.GET_META_DATA
|
||||
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
|
||||
eq(UserHandle.getUserId(packageUid)));
|
||||
|
||||
// Set up getApplicationInfo().
|
||||
|
||||
final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
|
||||
mRealTestContext.getPackageManager().getApplicationInfo(
|
||||
admin.getPackageName(),
|
||||
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
|
||||
|
||||
ai.enabledSetting = enabledSetting;
|
||||
ai.uid = packageUid;
|
||||
|
||||
doReturn(ai).when(mMockContext.ipackageManager).getApplicationInfo(
|
||||
eq(admin.getPackageName()),
|
||||
eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
|
||||
eq(UserHandle.getUserId(packageUid)));
|
||||
|
||||
// Set up getPackageInfo().
|
||||
|
||||
final PackageInfo pi = DpmTestUtils.cloneParcelable(
|
||||
mRealTestContext.getPackageManager().getPackageInfo(
|
||||
admin.getPackageName(), 0));
|
||||
assertTrue(pi.applicationInfo.flags != 0);
|
||||
|
||||
pi.applicationInfo.uid = packageUid;
|
||||
|
||||
doReturn(pi).when(mMockContext.ipackageManager).getPackageInfo(
|
||||
eq(admin.getPackageName()),
|
||||
eq(0),
|
||||
eq(UserHandle.getUserId(packageUid)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,21 +16,35 @@
|
||||
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
import com.google.android.collect.Sets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.FileUtils;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
import android.util.Printer;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public class DpmTestUtils {
|
||||
private DpmTestUtils() {
|
||||
}
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
public class DpmTestUtils extends AndroidTestCase {
|
||||
public static void clearDir(File dir) {
|
||||
if (dir.exists()) {
|
||||
Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
|
||||
@@ -43,6 +57,44 @@ public class DpmTestUtils {
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
|
||||
public static Bundle newRestrictions(String... restrictions) {
|
||||
final Bundle ret = new Bundle();
|
||||
for (String restriction : restrictions) {
|
||||
ret.putBoolean(restriction, true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void assertRestrictions(Bundle expected, Bundle actual) {
|
||||
final ArrayList<String> elist;
|
||||
if (expected == null) {
|
||||
elist = null;
|
||||
} else {
|
||||
elist = Lists.newArrayList();
|
||||
for (String key : expected.keySet()) {
|
||||
if (expected.getBoolean(key)) {
|
||||
elist.add(key);
|
||||
}
|
||||
}
|
||||
Collections.sort(elist);
|
||||
}
|
||||
|
||||
final ArrayList<String> alist;
|
||||
if (actual == null) {
|
||||
alist = null;
|
||||
} else {
|
||||
alist = Lists.newArrayList();
|
||||
for (String key : actual.keySet()) {
|
||||
if (actual.getBoolean(key)) {
|
||||
alist.add(key);
|
||||
}
|
||||
}
|
||||
Collections.sort(alist);
|
||||
}
|
||||
|
||||
assertEquals(elist, alist);
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> T cloneParcelable(T source) {
|
||||
Parcel p = Parcel.obtain();
|
||||
p.writeParcelable(source, 0);
|
||||
@@ -58,4 +110,57 @@ public class DpmTestUtils {
|
||||
Log.i(DpmTestBase.TAG, x);
|
||||
}
|
||||
};
|
||||
|
||||
public static String readAsset(Context context, String assetPath) throws IOException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(
|
||||
context.getResources().getAssets().open(assetPath)))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void writeToFile(File path, String content)
|
||||
throws IOException {
|
||||
path.getParentFile().mkdirs();
|
||||
|
||||
try (FileWriter writer = new FileWriter(path)) {
|
||||
Log.i(DpmTestBase.TAG, "Writing to " + path);
|
||||
Log.i(DpmTestBase.TAG, content);
|
||||
writer.write(content);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkAssertRestrictions(Bundle a, Bundle b) {
|
||||
try {
|
||||
assertRestrictions(a, b);
|
||||
return true;
|
||||
} catch (AssertionFailedError e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void testAssertRestrictions() {
|
||||
final Bundle a = newRestrictions();
|
||||
final Bundle b = newRestrictions("a");
|
||||
final Bundle c = newRestrictions("a");
|
||||
final Bundle d = newRestrictions("b", "c");
|
||||
final Bundle e = newRestrictions("b", "c");
|
||||
|
||||
assertTrue(checkAssertRestrictions(null, null));
|
||||
assertFalse(checkAssertRestrictions(null, a));
|
||||
assertFalse(checkAssertRestrictions(a, null));
|
||||
assertTrue(checkAssertRestrictions(a, a));
|
||||
|
||||
assertFalse(checkAssertRestrictions(a, b));
|
||||
assertTrue(checkAssertRestrictions(b, c));
|
||||
|
||||
assertFalse(checkAssertRestrictions(c, d));
|
||||
assertTrue(checkAssertRestrictions(d, e));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,31 +47,6 @@ import static org.mockito.Mockito.when;
|
||||
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
|
||||
*/
|
||||
public class OwnersTest extends DpmTestBase {
|
||||
private String readAsset(String assetPath) throws IOException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(
|
||||
mRealTestContext.getResources().getAssets().open(assetPath)))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void createLegacyFile(File path, String content)
|
||||
throws IOException {
|
||||
path.getParentFile().mkdirs();
|
||||
|
||||
try (FileWriter writer = new FileWriter(path)) {
|
||||
Log.i(TAG, "Writing to " + path);
|
||||
Log.i(TAG, content);
|
||||
writer.write(content);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpgrade01() throws Exception {
|
||||
getContext().addUsers(10, 11, 20, 21);
|
||||
|
||||
@@ -79,8 +54,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test01/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test01/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -99,6 +74,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
|
||||
assertNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(0, owners.getProfileOwnerKeys().size());
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
|
||||
// Then re-read and check.
|
||||
@@ -110,6 +91,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
|
||||
assertNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(0, owners.getProfileOwnerKeys().size());
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +107,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test02/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test02/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -142,6 +129,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
assertNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(0, owners.getProfileOwnerKeys().size());
|
||||
|
||||
assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
|
||||
// Then re-read and check.
|
||||
@@ -156,6 +149,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
assertNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(0, owners.getProfileOwnerKeys().size());
|
||||
|
||||
assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +165,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test03/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test03/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -196,6 +195,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
owners.getProfileOwnerComponent(11));
|
||||
assertEquals("1", owners.getProfileOwnerName(11));
|
||||
assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
|
||||
// Then re-read and check.
|
||||
@@ -218,9 +223,19 @@ public class OwnersTest extends DpmTestBase {
|
||||
owners.getProfileOwnerComponent(11));
|
||||
assertEquals("1", owners.getProfileOwnerName(11));
|
||||
assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note this also tests {@link Owners#setDeviceOwnerUserRestrictionsMigrated()}
|
||||
* and {@link Owners#setProfileOwnerUserRestrictionsMigrated(int)}.
|
||||
*/
|
||||
public void testUpgrade04() throws Exception {
|
||||
getContext().addUsers(10, 11, 20, 21);
|
||||
|
||||
@@ -228,8 +243,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test04/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test04/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -262,6 +277,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
owners.getProfileOwnerComponent(11));
|
||||
assertEquals("1", owners.getProfileOwnerName(11));
|
||||
assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
|
||||
|
||||
assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
|
||||
// Then re-read and check.
|
||||
@@ -288,6 +309,40 @@ public class OwnersTest extends DpmTestBase {
|
||||
owners.getProfileOwnerComponent(11));
|
||||
assertEquals("1", owners.getProfileOwnerName(11));
|
||||
assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
|
||||
|
||||
assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
|
||||
owners.setDeviceOwnerUserRestrictionsMigrated();
|
||||
}
|
||||
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
owners.load();
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
|
||||
owners.setProfileOwnerUserRestrictionsMigrated(11);
|
||||
}
|
||||
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
owners.load();
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
|
||||
owners.setProfileOwnerUserRestrictionsMigrated(11);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,8 +353,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test05/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test05/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -319,6 +374,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
assertNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(0, owners.getProfileOwnerKeys().size());
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
|
||||
// Then re-read and check.
|
||||
@@ -332,6 +393,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
assertNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(0, owners.getProfileOwnerKeys().size());
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,8 +409,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
{
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test06/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test06/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
@@ -362,6 +429,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
assertNotNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
|
||||
// Then re-read and check.
|
||||
@@ -375,6 +448,12 @@ public class OwnersTest extends DpmTestBase {
|
||||
|
||||
assertNotNull(owners.getSystemUpdatePolicy());
|
||||
assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
|
||||
|
||||
assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
|
||||
assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,8 +463,8 @@ public class OwnersTest extends DpmTestBase {
|
||||
final OwnersTestable owners = new OwnersTestable(getContext());
|
||||
|
||||
// First, migrate to create new-style config files.
|
||||
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
readAsset("OwnersTest/test04/input.xml"));
|
||||
DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
|
||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test04/input.xml"));
|
||||
|
||||
owners.load();
|
||||
|
||||
|
||||
@@ -211,11 +211,14 @@ public class UserManagerTest extends AndroidTestCase {
|
||||
|
||||
public void testRestrictions() {
|
||||
UserInfo testUser = createUser("User 1", 0);
|
||||
Bundle restrictions = new Bundle();
|
||||
restrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, true);
|
||||
restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, false);
|
||||
mUserManager.setUserRestrictions(restrictions, new UserHandle(testUser.id));
|
||||
|
||||
mUserManager.setUserRestriction(
|
||||
UserManager.DISALLOW_INSTALL_APPS, true, new UserHandle(testUser.id));
|
||||
mUserManager.setUserRestriction(
|
||||
UserManager.DISALLOW_CONFIG_WIFI, false, new UserHandle(testUser.id));
|
||||
|
||||
Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id));
|
||||
// Note this will fail if DO already sets those restrictions.
|
||||
assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
|
||||
assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
|
||||
assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
|
||||
|
||||
Reference in New Issue
Block a user