summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Prevot <nprevot@google.com>2015-04-24 15:08:01 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-04-24 15:08:02 +0000
commit7defaef1bfc05757652d3a5d00d35090397e7f3e (patch)
tree50cfedf437340a751bf4d70407a3f3347fbdb2d3
parentf74a212ffbdfdf39de128682ec174a9ee1403a9e (diff)
parent2806374f9531490296547d4e884ce9163f4ac867 (diff)
downloadframeworks_base-7defaef1bfc05757652d3a5d00d35090397e7f3e.zip
frameworks_base-7defaef1bfc05757652d3a5d00d35090397e7f3e.tar.gz
frameworks_base-7defaef1bfc05757652d3a5d00d35090397e7f3e.tar.bz2
Merge "Restrict setting the profile/device owner with a signature-level permission."
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java32
-rw-r--r--core/res/AndroidManifest.xml8
-rw-r--r--core/res/res/values/strings.xml6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java117
4 files changed, 106 insertions, 57 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a20aa66..47133d4 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2651,14 +2651,12 @@ 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.
+ * Sets the given package as the device owner.
+ * Same as {@link #setDeviceOwner(String, String)} but without setting a device owner name.
* @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.
+ * @throws IllegalStateException If the preconditions mentioned are not met.
*/
public boolean setDeviceOwner(String packageName) throws IllegalArgumentException,
IllegalStateException {
@@ -2667,15 +2665,17 @@ 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.
+ * Sets the given package as the device owner. The package must already be installed. There
+ * must not already be a device owner.
+ * Only apps with the MANAGE_PROFILE_AND_DEVICE_OWNERS permission and the shell uid can call
+ * this method.
+ * Calling this after the setup phase of the primary user has completed is allowed only if
+ * the caller is the shell uid, and there are no additional users and no accounts.
* @param packageName the package name of the application to be registered as the device owner.
* @param ownerName the human readable name of the institution that owns this device.
* @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.
+ * @throws IllegalStateException If the preconditions mentioned are not met.
*/
public boolean setDeviceOwner(String packageName, String ownerName)
throws IllegalArgumentException, IllegalStateException {
@@ -2961,14 +2961,18 @@ public class DevicePolicyManager {
/**
* @hide
* Sets the given component as the profile owner of the given user profile. The package must
- * already be installed and there shouldn't be an existing profile owner registered for this
- * user. Only the system can call this API if the user has already completed setup.
+ * already be installed. There must not already be a profile owner for this user.
+ * Only apps with the MANAGE_PROFILE_AND_DEVICE_OWNERS permission and the shell uid can call
+ * this method.
+ * Calling this after the setup phase of the specified user has completed is allowed only if:
+ * - the caller is SYSTEM_UID.
+ * - or the caller is the shell uid, and there are no accounts on the specified user.
* @param admin the component name to be registered as profile owner.
* @param ownerName the human readable name of the organisation associated with this DPM.
* @param userHandle the userId to set the profile owner for.
* @return whether the component was successfully registered as the profile owner.
- * @throws IllegalArgumentException if admin is null, the package isn't installed, or
- * the user has already been set up.
+ * @throws IllegalArgumentException if admin is null, the package isn't installed, or the
+ * preconditions mentioned are not met.
*/
public boolean setProfileOwner(ComponentName admin, String ownerName, int userHandle)
throws IllegalArgumentException {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 62685a1..dced051 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1309,6 +1309,14 @@
<permission android:name="android.permission.MANAGE_USERS"
android:protectionLevel="signature|system" />
+ <!-- @hide Allows an application to set the profile owners and the device owner.
+ This permission is not available to third party applications.-->
+ <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_manageProfileAndDeviceOwners"
+ android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+
<!-- Allows an application to get full detailed information about
recently running tasks, with full fidelity to the real state.
@hide -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6f554f0..51c2062 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -699,6 +699,12 @@
discover information about which applications are used on the device.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_manageProfileAndDeviceOwners">Manage profile and device owners</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to set the profile/device owners.
+ [CHAR LIMIT=NONE] -->
+ <string name="permdesc_manageProfileAndDeviceOwners">Allows apps to set the profile owners and the device owner.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_reorderTasks">reorder running apps</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_reorderTasks">Allows the app to move tasks to the
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index eb9234a..6fc3103 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3983,15 +3983,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ " for device owner");
}
synchronized (this) {
- if (!allowedToSetDeviceOwnerOnDevice()) {
- throw new IllegalStateException(
- "Trying to set device owner but device is already provisioned.");
- }
-
- if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner()) {
- throw new IllegalStateException(
- "Trying to set device owner but device owner is already set.");
- }
+ enforceCanSetDeviceOwner();
// Shutting down backup manager service permanently.
long ident = Binder.clearCallingIdentity();
@@ -4009,7 +4001,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Device owner is not set and does not exist, set it.
mDeviceOwner = DeviceOwner.createWithDeviceOwner(packageName, ownerName);
} else {
- // Device owner is not set but a profile owner exists, update Device owner state.
+ // Device owner state already exists, update it.
mDeviceOwner.setDeviceOwner(packageName, ownerName);
}
mDeviceOwner.writeOwnerFile();
@@ -4225,43 +4217,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (!mHasFeature) {
return false;
}
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-
- UserInfo info = mUserManager.getUserInfo(userHandle);
- if (info == null) {
- // User doesn't exist.
- throw new IllegalArgumentException(
- "Attempted to set profile owner for invalid userId: " + userHandle);
- }
- if (info.isGuest()) {
- throw new IllegalStateException("Cannot set a profile owner on a guest");
- }
-
if (who == null
|| !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
throw new IllegalArgumentException("Component " + who
+ " not installed for userId:" + userHandle);
}
synchronized (this) {
- // Only SYSTEM_UID can override the userSetupComplete
- if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
- && hasUserSetupCompleted(userHandle)) {
- throw new IllegalStateException(
- "Trying to set profile owner but user is already set-up.");
- }
-
+ enforceCanSetProfileOwner(userHandle);
if (mDeviceOwner == null) {
// Device owner state does not exist, create it.
mDeviceOwner = DeviceOwner.createWithProfileOwner(who, ownerName,
userHandle);
- mDeviceOwner.writeOwnerFile();
- return true;
} else {
- // Device owner already exists, update it.
+ // Device owner state already exists, update it.
mDeviceOwner.setProfileOwner(who, ownerName, userHandle);
- mDeviceOwner.writeOwnerFile();
- return true;
}
+ mDeviceOwner.writeOwnerFile();
+ return true;
}
}
@@ -4451,18 +4423,77 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
- * Device owner can only be set on an unprovisioned device. However, if initiated via "adb",
- * we also allow it if no accounts or additional users are present on the device.
+ * The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
+ * permission.
+ * The profile owner can only be set before the user setup phase has completed,
+ * except for:
+ * - SYSTEM_UID
+ * - adb if there are not accounts.
*/
- private boolean allowedToSetDeviceOwnerOnDevice() {
- if (!hasUserSetupCompleted(UserHandle.USER_OWNER)) {
- return true;
+ private void enforceCanSetProfileOwner(int userHandle) {
+ UserInfo info = mUserManager.getUserInfo(userHandle);
+ if (info == null) {
+ // User doesn't exist.
+ throw new IllegalArgumentException(
+ "Attempted to set profile owner for invalid userId: " + userHandle);
+ }
+ if (info.isGuest()) {
+ throw new IllegalStateException("Cannot set a profile owner on a guest");
+ }
+ if (getProfileOwner(userHandle) != null) {
+ throw new IllegalStateException("Trying to set the profile owner, but profile owner "
+ + "is already set.");
+ }
+ int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
+ if (hasUserSetupCompleted(userHandle) &&
+ AccountManager.get(mContext).getAccountsAsUser(userHandle).length > 0) {
+ throw new IllegalStateException("Not allowed to set the profile owner because "
+ + "there are already some accounts on the profile");
+ }
+ return;
+ }
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
+ if (hasUserSetupCompleted(userHandle)
+ && UserHandle.getAppId(callingUid) != Process.SYSTEM_UID) {
+ throw new IllegalStateException("Cannot set the profile owner on a user which is "
+ + "already set-up");
}
+ }
- int callingId = Binder.getCallingUid();
- return (callingId == Process.SHELL_UID || callingId == Process.ROOT_UID)
- && mUserManager.getUserCount() == 1
- && AccountManager.get(mContext).getAccounts().length == 0;
+ /**
+ * The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
+ * permission.
+ * The device owner can only be set before the setup phase of the primary user has completed,
+ * except for adb if no accounts or additional users are present on the device.
+ */
+ private void enforceCanSetDeviceOwner() {
+ if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner()) {
+ throw new IllegalStateException("Trying to set the device owner, but device owner "
+ + "is already set.");
+ }
+ int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
+ if (!hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ return;
+ }
+ if (mUserManager.getUserCount() > 1) {
+ throw new IllegalStateException("Not allowed to set the device owner because there "
+ + "are already several users on the device");
+ }
+ if (AccountManager.get(mContext).getAccounts().length > 0) {
+ throw new IllegalStateException("Not allowed to set the device owner because there "
+ + "are already some accounts on the device");
+ }
+ return;
+ }
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
+ if (hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ throw new IllegalStateException("Cannot set the device owner if the device is "
+ + "already set-up");
+ }
}
private void enforceCrossUserPermission(int userHandle) {