summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java107
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl6
-rw-r--r--core/java/android/os/UserManager.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java66
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java64
5 files changed, 218 insertions, 31 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0e6f86e..9310bf8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -361,6 +361,40 @@ public class DevicePolicyManager {
= "android.app.action.ADD_DEVICE_ADMIN";
/**
+ * @hide
+ * Activity action: ask the user to add a new device administrator as the profile owner
+ * for this user. Only system privileged apps that have MANAGE_USERS and MANAGE_DEVICE_ADMINS
+ * permission can call this API.
+ *
+ * <p>The ComponentName of the profile owner admin is pass in {@link #EXTRA_DEVICE_ADMIN} extra
+ * field. This will invoke a UI to bring the user through adding the profile owner admin
+ * to remotely control restrictions on the user.
+ *
+ * <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the
+ * result of whether or not the user approved the action. If approved, the result will
+ * be {@link Activity#RESULT_OK} and the component will be set as an active admin as well
+ * as a profile owner.
+ *
+ * <p>You can optionally include the {@link #EXTRA_ADD_EXPLANATION}
+ * field to provide the user with additional explanation (in addition
+ * to your component's description) about what is being added.
+ *
+ * <p>If there is already a profile owner active or the caller doesn't have the required
+ * permissions, the operation will return a failure result.
+ */
+ @SystemApi
+ public static final String ACTION_SET_PROFILE_OWNER
+ = "android.app.action.SET_PROFILE_OWNER";
+
+ /**
+ * @hide
+ * Name of the profile owner admin that controls the user.
+ */
+ @SystemApi
+ public static final String EXTRA_PROFILE_OWNER_NAME
+ = "android.app.extra.PROFILE_OWNER_NAME";
+
+ /**
* Activity action: send when any policy admin changes a policy.
* This is generally used to find out when a new policy is in effect.
*
@@ -397,6 +431,7 @@ public class DevicePolicyManager {
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_SET_NEW_PASSWORD
= "android.app.action.SET_NEW_PASSWORD";
+
/**
* Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a
* managed profile to its parent.
@@ -2018,7 +2053,6 @@ public class DevicePolicyManager {
return false;
}
-
/**
* Used to determine if a particular package has been registered as a Device Owner app.
* A device owner app is a special device admin that cannot be deactivated by the user, once
@@ -2096,6 +2130,7 @@ public class DevicePolicyManager {
/**
* @hide
+ * @deprecated Use #ACTION_SET_PROFILE_OWNER
* Sets the given component as an active admin and registers the package as the profile
* owner for this user. The package must already be installed and there shouldn't be
* an existing profile owner registered for this user. Also, this method must be called
@@ -2116,7 +2151,7 @@ public class DevicePolicyManager {
try {
final int myUserId = UserHandle.myUserId();
mService.setActiveAdmin(admin, false, myUserId);
- return mService.setProfileOwner(admin.getPackageName(), ownerName, myUserId);
+ return mService.setProfileOwner(admin, ownerName, myUserId);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set profile owner " + re);
throw new IllegalArgumentException("Couldn't set profile owner.", re);
@@ -2127,6 +2162,42 @@ public class DevicePolicyManager {
/**
* @hide
+ * Clears the active profile owner and removes all user restrictions. The caller must
+ * be from the same package as the active profile owner for this user, otherwise a
+ * SecurityException will be thrown.
+ *
+ * @param admin The component to remove as the profile owner.
+ * @return
+ */
+ @SystemApi
+ public void clearProfileOwner(ComponentName admin) {
+ if (mService != null) {
+ try {
+ mService.clearProfileOwner(admin);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to clear profile owner " + admin + re);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ * Checks if the user was already setup.
+ */
+ public boolean hasUserSetupCompleted() {
+ if (mService != null) {
+ try {
+ return mService.hasUserSetupCompleted();
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to check if user setup has completed");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @deprecated Use setProfileOwner(ComponentName ...)
+ * @hide
* Sets the given package 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. Also, this method must be called before the user has been used for the first time.
@@ -2139,9 +2210,35 @@ public class DevicePolicyManager {
*/
public boolean setProfileOwner(String packageName, String ownerName, int userHandle)
throws IllegalArgumentException {
+ if (packageName == null) {
+ throw new NullPointerException("packageName cannot be null");
+ }
+ return setProfileOwner(new ComponentName(packageName, ""), ownerName, userHandle);
+ }
+
+ /**
+ * @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.
+ * @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.
+ */
+ public boolean setProfileOwner(ComponentName admin, String ownerName, int userHandle)
+ throws IllegalArgumentException {
+ if (admin == null) {
+ throw new NullPointerException("admin cannot be null");
+ }
if (mService != null) {
try {
- return mService.setProfileOwner(packageName, ownerName, userHandle);
+ if (ownerName == null) {
+ ownerName = "";
+ }
+ return mService.setProfileOwner(admin, ownerName, userHandle);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set profile owner", re);
throw new IllegalArgumentException("Couldn't set profile owner.", re);
@@ -2200,7 +2297,7 @@ public class DevicePolicyManager {
if (mService != null) {
try {
String profileOwnerPackage = mService.getProfileOwner(
- Process.myUserHandle().getIdentifier());
+ Process.myUserHandle().getIdentifier()).getPackageName();
return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
} catch (RemoteException re) {
Log.w(TAG, "Failed to check profile owner");
@@ -2215,7 +2312,7 @@ public class DevicePolicyManager {
* owner has been set for that user.
* @throws IllegalArgumentException if the userId is invalid.
*/
- public String getProfileOwner() throws IllegalArgumentException {
+ public ComponentName getProfileOwner() throws IllegalArgumentException {
if (mService != null) {
try {
return mService.getProfileOwner(Process.myUserHandle().getIdentifier());
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a6544e6..6ce737a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -113,11 +113,13 @@ interface IDevicePolicyManager {
String getDeviceOwnerName();
void clearDeviceOwner(String packageName);
- boolean setProfileOwner(String packageName, String ownerName, int userHandle);
- String getProfileOwner(int userHandle);
+ boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
+ ComponentName getProfileOwner(int userHandle);
String getProfileOwnerName(int userHandle);
void setProfileEnabled(in ComponentName who);
void setProfileName(in ComponentName who, String profileName);
+ void clearProfileOwner(in ComponentName who);
+ boolean hasUserSetupCompleted();
boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
void uninstallCaCert(in ComponentName admin, in String alias);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a506c42..9935317 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -615,6 +615,12 @@ public class UserManager {
if (guest != null) {
Settings.Secure.putStringForUser(context.getContentResolver(),
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
+ try {
+ mService.setUserRestrictions(
+ mService.getDefaultGuestRestrictions(), guest.id);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not update guest restrictions");
+ }
}
return guest;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index f1284d8..4b60c9f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -17,6 +17,7 @@
package com.android.server.devicepolicy;
import android.app.AppGlobals;
+import android.content.ComponentName;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -53,6 +54,7 @@ public class DeviceOwner {
private static final String TAG_PROFILE_OWNER = "profile-owner";
private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
+ private static final String ATTR_COMPONENT_NAME = "component";
private static final String ATTR_USERID = "userId";
private AtomicFile fileForWriting;
@@ -100,6 +102,7 @@ public class DeviceOwner {
}
/**
+ * @deprecated Use a component name instead of package name
* Creates an instance of the device owner object with the profile owner set.
*/
static DeviceOwner createWithProfileOwner(String packageName, String ownerName, int userId) {
@@ -108,6 +111,15 @@ public class DeviceOwner {
return owner;
}
+ /**
+ * Creates an instance of the device owner object with the profile owner set.
+ */
+ static DeviceOwner createWithProfileOwner(ComponentName admin, String ownerName, int userId) {
+ DeviceOwner owner = new DeviceOwner();
+ owner.mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
+ return owner;
+ }
+
String getDeviceOwnerPackageName() {
return mDeviceOwner != null ? mDeviceOwner.packageName : null;
}
@@ -124,19 +136,36 @@ public class DeviceOwner {
mDeviceOwner = null;
}
+ /**
+ * @deprecated
+ */
void setProfileOwner(String packageName, String ownerName, int userId) {
mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName));
}
+ void setProfileOwner(ComponentName admin, String ownerName, int userId) {
+ mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
+ }
+
void removeProfileOwner(int userId) {
mProfileOwners.remove(userId);
}
+ /**
+ * @deprecated Use getProfileOwnerComponent
+ * @param userId
+ * @return
+ */
String getProfileOwnerPackageName(int userId) {
OwnerInfo profileOwner = mProfileOwners.get(userId);
return profileOwner != null ? profileOwner.packageName : null;
}
+ ComponentName getProfileOwnerComponent(int userId) {
+ OwnerInfo profileOwner = mProfileOwners.get(userId);
+ return profileOwner != null ? profileOwner.admin : null;
+ }
+
String getProfileOwnerName(int userId) {
OwnerInfo profileOwner = mProfileOwners.get(userId);
return profileOwner != null ? profileOwner.name : null;
@@ -191,15 +220,23 @@ public class DeviceOwner {
String tag = parser.getName();
if (tag.equals(TAG_DEVICE_OWNER)) {
- mDeviceOwner = new OwnerInfo(
- parser.getAttributeValue(null, ATTR_NAME),
- parser.getAttributeValue(null, ATTR_PACKAGE));
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ mDeviceOwner = new OwnerInfo(name, packageName);
} else if (tag.equals(TAG_PROFILE_OWNER)) {
String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
+ String profileOwnerComponentStr =
+ parser.getAttributeValue(null, ATTR_COMPONENT_NAME);
int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID));
- mProfileOwners.put(userId,
- new OwnerInfo(profileOwnerName, profileOwnerPackageName));
+ OwnerInfo profileOwnerInfo;
+ if (profileOwnerComponentStr != null) {
+ profileOwnerInfo = new OwnerInfo(profileOwnerName,
+ ComponentName.unflattenFromString(profileOwnerComponentStr));
+ } else {
+ profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName);
+ }
+ mProfileOwners.put(userId, profileOwnerInfo);
} else {
throw new XmlPullParserException(
"Unexpected tag in device owner file: " + tag);
@@ -230,9 +267,6 @@ public class DeviceOwner {
if (mDeviceOwner != null) {
out.startTag(null, TAG_DEVICE_OWNER);
out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName);
- if (mDeviceOwner.packageName != null) {
- out.attribute(null, ATTR_NAME, mDeviceOwner.packageName);
- }
out.endTag(null, TAG_DEVICE_OWNER);
}
@@ -240,9 +274,13 @@ public class DeviceOwner {
if (mProfileOwners.size() > 0) {
for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) {
out.startTag(null, TAG_PROFILE_OWNER);
- out.attribute(null, ATTR_PACKAGE, owner.getValue().packageName);
- out.attribute(null, ATTR_NAME, owner.getValue().name);
+ OwnerInfo ownerInfo = owner.getValue();
+ out.attribute(null, ATTR_PACKAGE, ownerInfo.packageName);
+ out.attribute(null, ATTR_NAME, ownerInfo.name);
out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey()));
+ if (ownerInfo.admin != null) {
+ out.attribute(null, ATTR_COMPONENT_NAME, ownerInfo.admin.flattenToString());
+ }
out.endTag(null, TAG_PROFILE_OWNER);
}
}
@@ -282,10 +320,18 @@ public class DeviceOwner {
static class OwnerInfo {
public String name;
public String packageName;
+ public ComponentName admin;
public OwnerInfo(String name, String packageName) {
this.name = name;
this.packageName = packageName;
+ this.admin = new ComponentName(packageName, "");
+ }
+
+ public OwnerInfo(String name, ComponentName admin) {
+ this.name = name;
+ this.admin = admin;
+ this.packageName = admin.getPackageName();
}
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f49451e..15bea5a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -905,7 +905,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
for (ActiveAdmin admin : candidates) {
boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
boolean ownsProfile = (getProfileOwner(userHandle) != null
- && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
+ && getProfileOwner(userHandle).getPackageName()
+ .equals(admin.info.getPackageName()));
if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
if (ownsDevice) {
@@ -3310,7 +3311,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public boolean setProfileOwner(String packageName, String ownerName, int userHandle) {
+ public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
if (!mHasFeature) {
return false;
}
@@ -3322,26 +3323,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Attempted to set profile owner for invalid userId: " + userHandle);
}
- if (packageName == null
- || !DeviceOwner.isInstalledForUser(packageName, userHandle)) {
- throw new IllegalArgumentException("Package name " + packageName
+ if (who == null
+ || !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
+ throw new IllegalArgumentException("Component " + who
+ " not installed for userId:" + userHandle);
}
synchronized (this) {
- if (isUserSetupComplete(userHandle)) {
+ // Only SYSTEM_UID can override the userSetupComplete
+ if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
+ && isUserSetupComplete(userHandle)) {
throw new IllegalStateException(
"Trying to set profile owner but user is already set-up.");
}
if (mDeviceOwner == null) {
// Device owner state does not exist, create it.
- mDeviceOwner = DeviceOwner.createWithProfileOwner(packageName, ownerName,
+ mDeviceOwner = DeviceOwner.createWithProfileOwner(who, ownerName,
userHandle);
mDeviceOwner.writeOwnerFile();
return true;
} else {
// Device owner already exists, update it.
- mDeviceOwner.setProfileOwner(packageName, ownerName, userHandle);
+ mDeviceOwner.setProfileOwner(who, ownerName, userHandle);
mDeviceOwner.writeOwnerFile();
return true;
}
@@ -3349,6 +3352,38 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
+ public void clearProfileOwner(ComponentName who) {
+ if (!mHasFeature) {
+ return;
+ }
+ UserHandle callingUser = Binder.getCallingUserHandle();
+ // Check if this is the profile owner who is calling
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ synchronized (this) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mUserManager.setUserRestrictions(new Bundle(), callingUser);
+ if (mDeviceOwner != null) {
+ mDeviceOwner.removeProfileOwner(callingUser.getIdentifier());
+ mDeviceOwner.writeOwnerFile();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ @Override
+ public boolean hasUserSetupCompleted() {
+ if (!mHasFeature) {
+ return true;
+ }
+ DevicePolicyData policy = getUserData(UserHandle.getCallingUserId());
+ // If policy is null, return true, else check if the setup has completed.
+ return policy == null || policy.mUserSetupComplete;
+ }
+
+ @Override
public void setProfileEnabled(ComponentName who) {
if (!mHasFeature) {
return;
@@ -3397,14 +3432,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public String getProfileOwner(int userHandle) {
+ public ComponentName getProfileOwner(int userHandle) {
if (!mHasFeature) {
return null;
}
synchronized (this) {
if (mDeviceOwner != null) {
- return mDeviceOwner.getProfileOwnerPackageName(userHandle);
+ return mDeviceOwner.getProfileOwnerComponent(userHandle);
}
}
return null;
@@ -3413,8 +3448,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Returns the active profile owner for this user or null if the current user has no
// profile owner.
private ActiveAdmin getProfileOwnerAdmin(int userHandle) {
- String profileOwnerPackage = getProfileOwner(userHandle);
- if (profileOwnerPackage == null) {
+ ComponentName profileOwner =
+ mDeviceOwner != null ? mDeviceOwner.getProfileOwnerComponent(userHandle) : null;
+ if (profileOwner == null) {
return null;
}
@@ -3422,7 +3458,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int n = policy.mAdminList.size();
for (int i = 0; i < n; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
- if (profileOwnerPackage.equals(admin.info.getPackageName())) {
+ if (profileOwner.equals(admin.info)) {
return admin;
}
}
@@ -3800,7 +3836,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
setActiveAdmin(profileOwnerComponent, true, user.getIdentifier(), adminExtras);
- setProfileOwner(profileOwnerPkg, ownerName, user.getIdentifier());
+ setProfileOwner(profileOwnerComponent, ownerName, user.getIdentifier());
return user;
} finally {
restoreCallingIdentity(id);