diff options
-rw-r--r-- | api/current.txt | 12 | ||||
-rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 53 | ||||
-rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 4 | ||||
-rw-r--r-- | core/java/android/os/IUserManager.aidl | 1 | ||||
-rw-r--r-- | core/java/android/os/UserManager.java | 93 | ||||
-rw-r--r-- | services/java/com/android/server/DevicePolicyManagerService.java | 177 | ||||
-rw-r--r-- | services/java/com/android/server/accounts/AccountManagerService.java | 8 | ||||
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 19 | ||||
-rw-r--r-- | services/java/com/android/server/pm/UserManagerService.java | 42 |
9 files changed, 349 insertions, 60 deletions
diff --git a/api/current.txt b/api/current.txt index 2e28d7b..d3f1afd 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4333,6 +4333,7 @@ package android.app.admin { method public boolean hasGrantedPolicy(android.content.ComponentName, int); method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); + method public boolean isDeviceOwner(java.lang.String); method public void lockNow(); method public void removeActiveAdmin(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); @@ -16784,9 +16785,20 @@ package android.os { method public int getUserCount(); method public android.os.UserHandle getUserForSerialNumber(long); method public java.lang.String getUserName(); + method public android.os.Bundle getUserRestrictions(); + method public android.os.Bundle getUserRestrictions(android.os.UserHandle); method public boolean isUserAGoat(); + method public boolean isUserRestricted(); method public boolean isUserRunning(android.os.UserHandle); method public boolean isUserRunningOrStopping(android.os.UserHandle); + method public void setUserRestriction(java.lang.String, boolean); + method public void setUserRestrictions(android.os.Bundle); + method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle); + field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi"; + field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps"; + field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts"; + field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location"; + field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps"; } public abstract class Vibrator { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4c0eba0..8284b2c 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1513,4 +1513,57 @@ public class DevicePolicyManager { } } } + + /** + * @hide + * Sets the given package as the device owner. The package must already be installed and there + * shouldn't be an existing device owner registered, for this call to succeed. Also, this + * method must be called before the device is provisioned. + * @param packageName the package name of the application to be registered as the device owner. + * @return whether the package was successfully registered as the device owner. + * @throws IllegalArgumentException if the package name is null or invalid + * @throws IllegalStateException if a device owner is already registered or the device has + * already been provisioned. + */ + public boolean setDeviceOwner(String packageName) throws IllegalArgumentException, + IllegalStateException { + if (mService != null) { + try { + return mService.setDeviceOwner(packageName); + } catch (RemoteException re) { + Log.w(TAG, "Failed to set device owner"); + } + } + return false; + } + + /** + * Used to determine if a particular package has been registered as a Device Owner admin. + * Device Owner admins cannot be deactivated by the user unless the Device Owner itself allows + * it. And Device Owner packages cannot be uninstalled, once registered. + * @param packageName the package name to check against the registered device owner. + * @return whether or not the package is registered as the Device Owner. + */ + public boolean isDeviceOwner(String packageName) { + if (mService != null) { + try { + return mService.isDeviceOwner(packageName); + } catch (RemoteException re) { + Log.w(TAG, "Failed to check device owner"); + } + } + return false; + } + + /** @hide */ + public String getDeviceOwner() { + if (mService != null) { + try { + return mService.getDeviceOwner(); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get device owner"); + } + } + return null; + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e061ab3..b2a65bf 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -97,4 +97,8 @@ interface IDevicePolicyManager { int numbers, int symbols, int nonletter, int userHandle); void reportFailedPasswordAttempt(int userHandle); void reportSuccessfulPasswordAttempt(int userHandle); + + boolean setDeviceOwner(String packageName); + boolean isDeviceOwner(String packageName); + String getDeviceOwner(); } diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 4c2d7a6..2e8092a 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -34,6 +34,7 @@ interface IUserManager { Bitmap getUserIcon(int userHandle); List<UserInfo> getUsers(boolean excludeDying); UserInfo getUserInfo(int userHandle); + boolean isRestricted(); void setGuestEnabled(boolean enable); boolean isGuestEnabled(); void wipeUser(int userHandle); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 7c05528..3f666c1 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -37,48 +37,56 @@ public class UserManager { private final Context mContext; /** - * @hide - * Key for user restrictions. Specifies if a user is allowed to add or remove accounts. + * Key for user restrictions. Specifies if a user is disallowed from adding and removing + * accounts. + * The default value is <code>false</code>. + * <p/> * Type: Boolean * @see #setUserRestrictions(Bundle) * @see #getUserRestrictions() */ - public static final String ALLOW_MODIFY_ACCOUNTS = "modify_accounts"; + public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts"; /** - * @hide - * Key for user restrictions. Specifies if a user is allowed to change Wi-Fi access points. + * Key for user restrictions. Specifies if a user is disallowed from changing Wi-Fi + * access points. + * The default value is <code>false</code>. + * <p/> * Type: Boolean * @see #setUserRestrictions(Bundle) * @see #getUserRestrictions() */ - public static final String ALLOW_CONFIG_WIFI = "config_wifi"; + public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi"; /** - * @hide - * Key for user restrictions. Specifies if a user is allowed to install applications. + * Key for user restrictions. Specifies if a user is disallowed from installing applications. + * The default value is <code>false</code>. + * <p/> * Type: Boolean * @see #setUserRestrictions(Bundle) * @see #getUserRestrictions() */ - public static final String ALLOW_INSTALL_APPS = "install_apps"; + public static final String DISALLOW_INSTALL_APPS = "no_install_apps"; /** - * @hide - * Key for user restrictions. Specifies if a user is allowed to uninstall applications. + * Key for user restrictions. Specifies if a user is disallowed from uninstalling applications. + * The default value is <code>false</code>. + * <p/> * Type: Boolean * @see #setUserRestrictions(Bundle) * @see #getUserRestrictions() */ - public static final String ALLOW_UNINSTALL_APPS = "uninstall_apps"; + public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps"; - /** @hide * - * Key for user restrictions. Specifies if a user is allowed to toggle location sharing. + /** + * Key for user restrictions. Specifies if a user is disallowed from toggling location sharing. + * The default value is <code>false</code>. + * <p/> * Type: Boolean * @see #setUserRestrictions(Bundle) * @see #getUserRestrictions() */ - public static final String ALLOW_CONFIG_LOCATION_ACCESS = "config_location_access"; + public static final String DISALLOW_SHARE_LOCATION = "no_share_location"; /** @hide */ public UserManager(Context context, IUserManager service) { @@ -129,11 +137,14 @@ public class UserManager { } /** - * @hide + * Used to check if the user making this call is a restricted user. Restricted users may have + * application restrictions imposed on them. All apps should default to the most restrictive + * version, unless they have specific restrictions available through a call to + * {@link Context#getApplicationRestrictions()}. */ public boolean isUserRestricted() { try { - return mService.getUserInfo(getUserHandle()).isRestricted(); + return mService.isRestricted(); } catch (RemoteException re) { Log.w(TAG, "Could not check if user restricted ", re); return false; @@ -189,12 +200,19 @@ public class UserManager { } } - /** @hide */ + /** + * Returns the user-wide restrictions imposed on this user. + * @return a Bundle containing all the restrictions. + */ public Bundle getUserRestrictions() { return getUserRestrictions(Process.myUserHandle()); } - /** @hide */ + /** + * Returns the user-wide restrictions imposed on the user specified by <code>userHandle</code>. + * @param userHandle the UserHandle of the user for whom to retrieve the restrictions. + * @return a Bundle containing all the restrictions. + */ public Bundle getUserRestrictions(UserHandle userHandle) { try { return mService.getUserRestrictions(userHandle.getIdentifier()); @@ -204,12 +222,21 @@ public class UserManager { } } - /** @hide */ + /** + * Sets all the user-wide restrictions for this user. + * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission. + * @param restrictions the Bundle containing all the restrictions. + */ public void setUserRestrictions(Bundle restrictions) { setUserRestrictions(restrictions, Process.myUserHandle()); } - /** @hide */ + /** + * Sets all the user-wide restrictions for the specified user. + * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission. + * @param restrictions the Bundle containing all the restrictions. + * @param userHandle the UserHandle of the user for whom to set the restrictions. + */ public void setUserRestrictions(Bundle restrictions, UserHandle userHandle) { try { mService.setUserRestrictions(restrictions, userHandle.getIdentifier()); @@ -218,7 +245,27 @@ public class UserManager { } } - /** @hide */ + /** + * Sets the value of a specific restriction. + * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission. + * @param key the key of the restriction + * @param value the value for the restriction + * @param userHandle the user whose restriction is to be changed. + */ + public void setUserRestriction(String key, boolean value) { + Bundle bundle = getUserRestrictions(); + bundle.putBoolean(key, value); + setUserRestrictions(bundle); + } + + /** + * @hide + * Sets the value of a specific restriction on a specific user. + * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission. + * @param key the key of the restriction + * @param value the value for the restriction + * @param userHandle the user whose restriction is to be changed. + */ public void setUserRestriction(String key, boolean value, UserHandle userHandle) { Bundle bundle = getUserRestrictions(userHandle); bundle.putBoolean(key, value); @@ -467,7 +514,7 @@ public class UserManager { * @hide */ public boolean isLocationSharingToggleAllowed() { - return getUserRestrictions().getBoolean(ALLOW_CONFIG_LOCATION_ACCESS); + return !getUserRestrictions().getBoolean(DISALLOW_SHARE_LOCATION, false); } /** diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 18b4ec1..d3e7c24 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -41,10 +41,14 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.Signature; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -62,6 +66,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.util.AtomicFile; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; @@ -88,10 +93,11 @@ import java.util.Set; * Implementation of the device policy APIs. */ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { - private static final String DEVICE_POLICIES_XML = "device_policies.xml"; private static final String TAG = "DevicePolicyManagerService"; + private static final String DEVICE_POLICIES_XML = "device_policies.xml"; + private static final int REQUEST_EXPIRE_PASSWORD = 5571; private static final long MS_PER_DAY = 86400 * 1000; @@ -109,6 +115,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { IPowerManager mIPowerManager; IWindowManager mIWindowManager; + private DeviceOwner mDeviceOwner; + public static class DevicePolicyData { int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; int mActivePasswordLength = 0; @@ -507,6 +515,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addDataScheme("package"); context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); } @@ -545,6 +554,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + void loadDeviceOwner() { + synchronized (this) { + if (DeviceOwner.isRegistered()) { + mDeviceOwner = new DeviceOwner(); + } + } + } + /** * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration * reminders. Clears alarm if no expirations are configured. @@ -709,7 +726,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Intent resolveIntent = new Intent(); resolveIntent.setComponent(adminName); List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers( - resolveIntent, PackageManager.GET_META_DATA, userHandle); + resolveIntent, + PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, + userHandle); if (infos == null || infos.size() <= 0) { throw new IllegalArgumentException("Unknown admin: " + adminName); } @@ -994,6 +1013,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void systemReady() { synchronized (this) { loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER); + loadDeviceOwner(); } } @@ -1052,6 +1072,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (replaceIndex == -1) { policy.mAdminList.add(newAdmin); + enableIfNecessary(info.getPackageName(), userHandle); } else { policy.mAdminList.set(replaceIndex, newAdmin); } @@ -1119,6 +1140,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } if (admin.getUid() != Binder.getCallingUid()) { + // If trying to remove device owner, refuse when the caller is not the owner. + if (mDeviceOwner != null + && adminReceiver.getPackageName().equals(mDeviceOwner.getPackageName())) { + return; + } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); } @@ -2351,6 +2377,49 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public boolean setDeviceOwner(String packageName) { + if (packageName == null + || !DeviceOwner.isInstalled(packageName, mContext.getPackageManager())) { + throw new IllegalArgumentException("Invalid package name " + packageName + + " for device owner"); + } + synchronized (this) { + if (mDeviceOwner == null && !isDeviceProvisioned()) { + mDeviceOwner = new DeviceOwner(packageName); + mDeviceOwner.writeOwnerFile(); + return true; + } else { + throw new IllegalStateException("Trying to set device owner to " + packageName + + ", owner=" + mDeviceOwner.getPackageName() + + ", device_provisioned=" + isDeviceProvisioned()); + } + } + } + + @Override + public boolean isDeviceOwner(String packageName) { + synchronized (this) { + return mDeviceOwner != null + && mDeviceOwner.getPackageName().equals(packageName); + } + } + + @Override + public String getDeviceOwner() { + synchronized (this) { + if (mDeviceOwner != null) { + return mDeviceOwner.getPackageName(); + } + } + return null; + } + + private boolean isDeviceProvisioned() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 0) > 0; + } + private void enforceCrossUserPermission(int userHandle) { if (userHandle < 0) { throw new IllegalArgumentException("Invalid userId " + userHandle); @@ -2364,6 +2433,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void enableIfNecessary(String packageName, int userId) { + try { + IPackageManager ipm = AppGlobals.getPackageManager(); + ApplicationInfo ai = ipm.getApplicationInfo(packageName, + PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, + userId); + if (ai.enabledSetting + == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { + ipm.setApplicationEnabledSetting(packageName, + PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP, userId); + } + } catch (RemoteException e) { + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -2399,4 +2484,92 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } + + static class DeviceOwner { + private static final String DEVICE_OWNER_XML = "device_owner.xml"; + private static final String TAG_DEVICE_OWNER = "device-owner"; + private static final String ATTR_PACKAGE = "package"; + private String mPackageName; + + DeviceOwner() { + readOwnerFile(); + } + + DeviceOwner(String packageName) { + this.mPackageName = packageName; + } + + static boolean isRegistered() { + return new File(Environment.getSystemSecureDirectory(), + DEVICE_OWNER_XML).exists(); + } + + String getPackageName() { + return mPackageName; + } + + static boolean isInstalled(String packageName, PackageManager pm) { + try { + PackageInfo pi; + if ((pi = pm.getPackageInfo(packageName, 0)) != null) { + if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + return true; + } + } + } catch (NameNotFoundException nnfe) { + Slog.w(TAG, "Device Owner package " + packageName + " not installed."); + } + return false; + } + + void readOwnerFile() { + AtomicFile file = new AtomicFile(new File(Environment.getSystemSecureDirectory(), + DEVICE_OWNER_XML)); + try { + FileInputStream input = file.openRead(); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(input, null); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + } + String tag = parser.getName(); + if (!TAG_DEVICE_OWNER.equals(tag)) { + throw new XmlPullParserException( + "Device Owner file does not start with device-owner tag: found " + tag); + } + mPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); + input.close(); + } catch (XmlPullParserException xppe) { + Slog.e(TAG, "Error parsing device-owner file\n" + xppe); + } catch (IOException ioe) { + Slog.e(TAG, "IO Exception when reading device-owner file\n" + ioe); + } + } + + void writeOwnerFile() { + synchronized (this) { + writeOwnerFileLocked(); + } + } + + private void writeOwnerFileLocked() { + AtomicFile file = new AtomicFile(new File(Environment.getSystemSecureDirectory(), + DEVICE_OWNER_XML)); + try { + FileOutputStream output = file.startWrite(); + XmlSerializer out = new FastXmlSerializer(); + out.setOutput(output, "utf-8"); + out.startDocument(null, true); + out.startTag(null, TAG_DEVICE_OWNER); + out.attribute(null, ATTR_PACKAGE, mPackageName); + out.endTag(null, TAG_DEVICE_OWNER); + out.endDocument(); + out.flush(); + file.finishWrite(output); + } catch (IOException ioe) { + Slog.e(TAG, "IO Exception when writing device-owner file\n" + ioe); + } + } + } } diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index 09daf56..c4b98ad 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -1425,9 +1425,9 @@ public class AccountManagerService if (accountType == null) throw new IllegalArgumentException("accountType is null"); checkManageAccountsPermission(); - // Is user allowed to modify accounts? - if (!getUserManager().getUserRestrictions(Binder.getCallingUserHandle()) - .getBoolean(UserManager.ALLOW_MODIFY_ACCOUNTS)) { + // Is user disallowed from modifying accounts? + if (getUserManager().getUserRestrictions(Binder.getCallingUserHandle()) + .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -2572,7 +2572,7 @@ public class AccountManagerService if (callingUid != android.os.Process.myUid()) { Bundle restrictions = getUserManager().getUserRestrictions( new UserHandle(UserHandle.getUserId(callingUid))); - if (!restrictions.getBoolean(UserManager.ALLOW_MODIFY_ACCOUNTS)) { + if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { return false; } } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index f1af634..f7ed9d7 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -5933,7 +5933,7 @@ public class PackageManagerService extends IPackageManager.Stub { null); final int uid = Binder.getCallingUid(); - if (!isUserAllowed(UserHandle.getUserId(uid), UserManager.ALLOW_INSTALL_APPS)) { + if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) { try { observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED); } catch (RemoteException re) { @@ -5981,7 +5981,7 @@ public class PackageManagerService extends IPackageManager.Stub { android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "installExistingPackage for user " + userId); } - if (!isUserAllowed(userId, UserManager.ALLOW_INSTALL_APPS)) { + if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { return PackageManager.INSTALL_FAILED_USER_RESTRICTED; } @@ -6015,13 +6015,13 @@ public class PackageManagerService extends IPackageManager.Stub { return PackageManager.INSTALL_SUCCEEDED; } - private boolean isUserAllowed(int userId, String restrictionKey) { + private boolean isUserRestricted(int userId, String restrictionKey) { Bundle restrictions = sUserManager.getUserRestrictions(userId); - if (!restrictions.getBoolean(UserManager.ALLOW_INSTALL_APPS)) { - Log.w(TAG, "User does not have permission to: " + restrictionKey); - return false; + if (restrictions.getBoolean(restrictionKey, false)) { + Log.w(TAG, "User is restricted: " + restrictionKey); + return true; } - return true; + return false; } @Override @@ -8418,7 +8418,7 @@ public class PackageManagerService extends IPackageManager.Stub { android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "deletePackage for user " + userId); } - if (!isUserAllowed(userId, UserManager.ALLOW_UNINSTALL_APPS)) { + if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) { try { observer.packageDeleted(packageName, PackageManager.DELETE_FAILED_USER_RESTRICTED); } catch (RemoteException re) { @@ -8464,7 +8464,8 @@ public class PackageManagerService extends IPackageManager.Stub { IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface( ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); try { - if (dpm != null && dpm.packageHasActiveAdmins(packageName, userId)) { + if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId) + || dpm.isDeviceOwner(packageName))) { Slog.w(TAG, "Not removing package " + packageName + ": has active device admin"); return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER; } diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java index 636b0e5..fecc2df 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/java/com/android/server/pm/UserManagerService.java @@ -226,6 +226,13 @@ public class UserManagerService extends IUserManager.Stub { } } + @Override + public boolean isRestricted() { + synchronized (mPackagesLock) { + return getUserInfoLocked(UserHandle.getCallingUserId()).isRestricted(); + } + } + /* * Should be locked on mUsers before calling this. */ @@ -558,7 +565,6 @@ public class UserManagerService extends IUserManager.Stub { mNextSerialNumber = MIN_USER_ID; Bundle restrictions = new Bundle(); - initRestrictionsToDefaults(restrictions); mUserRestrictions.append(UserHandle.USER_OWNER, restrictions); updateUserIdsLocked(); @@ -608,11 +614,11 @@ public class UserManagerService extends IUserManager.Stub { Bundle restrictions = mUserRestrictions.get(userInfo.id); if (restrictions != null) { serializer.startTag(null, TAG_RESTRICTIONS); - writeBoolean(serializer, restrictions, UserManager.ALLOW_CONFIG_WIFI); - writeBoolean(serializer, restrictions, UserManager.ALLOW_MODIFY_ACCOUNTS); - writeBoolean(serializer, restrictions, UserManager.ALLOW_INSTALL_APPS); - writeBoolean(serializer, restrictions, UserManager.ALLOW_UNINSTALL_APPS); - writeBoolean(serializer, restrictions, UserManager.ALLOW_CONFIG_LOCATION_ACCESS); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_WIFI); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_INSTALL_APPS); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNINSTALL_APPS); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_SHARE_LOCATION); serializer.endTag(null, TAG_RESTRICTIONS); } serializer.endTag(null, TAG_USER); @@ -676,7 +682,6 @@ public class UserManagerService extends IUserManager.Stub { long lastLoggedInTime = 0L; boolean partial = false; Bundle restrictions = new Bundle(); - initRestrictionsToDefaults(restrictions); FileInputStream fis = null; try { @@ -725,11 +730,11 @@ public class UserManagerService extends IUserManager.Stub { name = parser.getText(); } } else if (TAG_RESTRICTIONS.equals(tag)) { - readBoolean(parser, restrictions, UserManager.ALLOW_CONFIG_WIFI); - readBoolean(parser, restrictions, UserManager.ALLOW_MODIFY_ACCOUNTS); - readBoolean(parser, restrictions, UserManager.ALLOW_INSTALL_APPS); - readBoolean(parser, restrictions, UserManager.ALLOW_UNINSTALL_APPS); - readBoolean(parser, restrictions, UserManager.ALLOW_CONFIG_LOCATION_ACCESS); + readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_WIFI); + readBoolean(parser, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS); + readBoolean(parser, restrictions, UserManager.DISALLOW_INSTALL_APPS); + readBoolean(parser, restrictions, UserManager.DISALLOW_UNINSTALL_APPS); + readBoolean(parser, restrictions, UserManager.DISALLOW_SHARE_LOCATION); } } } @@ -758,7 +763,9 @@ public class UserManagerService extends IUserManager.Stub { private void readBoolean(XmlPullParser parser, Bundle restrictions, String restrictionKey) { String value = parser.getAttributeValue(null, restrictionKey); - restrictions.putBoolean(restrictionKey, value == null ? true : Boolean.parseBoolean(value)); + if (value != null) { + restrictions.putBoolean(restrictionKey, Boolean.parseBoolean(value)); + } } private void writeBoolean(XmlSerializer xml, Bundle restrictions, String restrictionKey) @@ -769,14 +776,6 @@ public class UserManagerService extends IUserManager.Stub { } } - private void initRestrictionsToDefaults(Bundle restrictions) { - restrictions.putBoolean(UserManager.ALLOW_CONFIG_WIFI, true); - restrictions.putBoolean(UserManager.ALLOW_MODIFY_ACCOUNTS, true); - restrictions.putBoolean(UserManager.ALLOW_INSTALL_APPS, true); - restrictions.putBoolean(UserManager.ALLOW_UNINSTALL_APPS, true); - restrictions.putBoolean(UserManager.ALLOW_CONFIG_LOCATION_ACCESS, true); - } - private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) { String valueString = parser.getAttributeValue(null, attr); if (valueString == null) return defaultValue; @@ -823,7 +822,6 @@ public class UserManagerService extends IUserManager.Stub { writeUserLocked(userInfo); updateUserIdsLocked(); Bundle restrictions = new Bundle(); - initRestrictionsToDefaults(restrictions); mUserRestrictions.append(userId, restrictions); } } |