Modify getUserProfiles to return only enabled profiles:
Add a new enabled state for a managed profile.
Expose that as a new API on DevicePolicyManager.
Set the new state when enabling the profile.
Return only enabled profiles from the user manager.
Bug: 13755441
Bug: 13755091
Change-Id: I2907b182e19b3562592da688b3f68ef5f4088557
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8fa076b..ed007e9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16369,7 +16369,8 @@
* background.
*/
private void updateCurrentProfileIdsLocked() {
- final List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+ final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+ mCurrentUserId, false /* enabledOnly */);
int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
for (int i = 0; i < currentProfileIds.length; i++) {
currentProfileIds[i] = profiles.get(i).id;
@@ -16379,7 +16380,8 @@
private Set getProfileIdsLocked(int userId) {
Set userIds = new HashSet<Integer>();
- final List<UserInfo> profiles = getUserManagerLocked().getProfiles(userId);
+ final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+ userId, false /* enabledOnly */);
for (UserInfo user : profiles) {
userIds.add(Integer.valueOf(user.id));
}
@@ -16678,7 +16680,8 @@
void startProfilesLocked() {
if (DEBUG_MU) Slog.i(TAG_MU, "startProfilesLocked");
- List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+ List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+ mCurrentUserId, false /* enabledOnly */);
List<UserInfo> toStart = new ArrayList<UserInfo>(profiles.size());
for (UserInfo user : profiles) {
if ((user.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 53db9ef..210e151b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -24,6 +24,7 @@
import android.app.ActivityThread;
import android.app.admin.DevicePolicyManager;
import android.app.IStopUserCallback;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -258,11 +259,20 @@
}
@Override
- public List<UserInfo> getProfiles(int userId) {
+ public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
if (userId != UserHandle.getCallingUserId()) {
checkManageUsersPermission("getting profiles related to user " + userId);
}
synchronized (mPackagesLock) {
+ // Getting the service here is not good for testing purposes. However, this service
+ // is not available when UserManagerService starts up so we need a lazy load.
+
+ DevicePolicyManager dpm = null;
+ if (enabledOnly) {
+ dpm = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ }
+
UserInfo user = getUserInfoLocked(userId);
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
@@ -270,6 +280,23 @@
if (!isProfileOf(user, profile)) {
continue;
}
+
+ if (enabledOnly && profile.isManagedProfile()) {
+ if (dpm != null) {
+ if(!dpm.isProfileEnabled(profile.id)) {
+ continue;
+ }
+ } else {
+ Log.w(LOG_TAG,
+ "Attempting to reach DevicePolicyManager before it was started");
+ // TODO: There might be system apps that need to call this. Make sure that
+ // DevicePolicyManagerService is ready at that time (otherwise, any default
+ // value is a bad one).
+ throw new IllegalArgumentException(String.format(
+ "Attempting to get enabled profiles for %d before "
+ + "DevicePolicyManagerService has been started.", userId));
+ }
+ }
users.add(profile);
}
return users;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 1b048a1..3186527 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -53,6 +53,7 @@
private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
private static final String ATTR_USERID = "userId";
+ private static final String ATTR_ENABLED = "profileEnabled";
private AtomicFile fileForWriting;
@@ -61,11 +62,10 @@
private OutputStream mOutputStreamForTest;
// Internal state for the device owner package.
- private String mDeviceOwnerPackageName;
- private String mDeviceOwnerName;
+ private OwnerInfo mDeviceOwner;
// Internal state for the profile owner packages.
- private final HashMap<Integer, String[]> mProfileOwners = new HashMap<Integer, String[]>();
+ private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>();
// Private default constructor.
private DeviceOwner() {
@@ -95,8 +95,7 @@
*/
static DeviceOwner createWithDeviceOwner(String packageName, String ownerName) {
DeviceOwner owner = new DeviceOwner();
- owner.mDeviceOwnerPackageName = packageName;
- owner.mDeviceOwnerName = ownerName;
+ owner.mDeviceOwner = new OwnerInfo(ownerName, packageName);
return owner;
}
@@ -105,25 +104,25 @@
*/
static DeviceOwner createWithProfileOwner(String packageName, String ownerName, int userId) {
DeviceOwner owner = new DeviceOwner();
- owner.mProfileOwners.put(userId, new String[] { packageName, ownerName });
+ owner.mProfileOwners.put(
+ userId, new OwnerInfo(ownerName, packageName, false /* disabled */));
return owner;
}
String getDeviceOwnerPackageName() {
- return mDeviceOwnerPackageName;
+ return mDeviceOwner.packageName;
}
String getDeviceOwnerName() {
- return mDeviceOwnerName;
+ return mDeviceOwner.name;
}
void setDeviceOwner(String packageName, String ownerName) {
- mDeviceOwnerPackageName = packageName;
- mDeviceOwnerName = ownerName;
+ mDeviceOwner = new OwnerInfo(ownerName, packageName);
}
void setProfileOwner(String packageName, String ownerName, int userId) {
- mProfileOwners.put(userId, new String[] { packageName, ownerName });
+ mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName, false /* disabled */));
}
void removeProfileOwner(int userId) {
@@ -131,17 +130,30 @@
}
String getProfileOwnerPackageName(int userId) {
- String[] profileOwner = mProfileOwners.get(userId);
- return profileOwner != null ? profileOwner[0] : null;
+ OwnerInfo profileOwner = mProfileOwners.get(userId);
+ return profileOwner != null ? profileOwner.packageName : null;
}
String getProfileOwnerName(int userId) {
- String[] profileOwner = mProfileOwners.get(userId);
- return profileOwner != null ? profileOwner[1] : null;
+ OwnerInfo profileOwner = mProfileOwners.get(userId);
+ return profileOwner != null ? profileOwner.name : null;
+ }
+
+ boolean isProfileEnabled(int userId) {
+ OwnerInfo profileOwner = mProfileOwners.get(userId);
+ return profileOwner != null ? profileOwner.enabled : true;
+ }
+
+ void setProfileEnabled(int userId) {
+ OwnerInfo profileOwner = mProfileOwners.get(userId);
+ if (profileOwner == null) {
+ throw new IllegalArgumentException("No profile owner exists.");
+ }
+ profileOwner.enabled = true;
}
boolean hasDeviceOwner() {
- return mDeviceOwnerPackageName != null;
+ return mDeviceOwner != null;
}
static boolean isInstalled(String packageName, PackageManager pm) {
@@ -185,14 +197,18 @@
String tag = parser.getName();
if (tag.equals(TAG_DEVICE_OWNER)) {
- mDeviceOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
- mDeviceOwnerName = parser.getAttributeValue(null, ATTR_NAME);
+ mDeviceOwner = new OwnerInfo(
+ parser.getAttributeValue(null, ATTR_NAME),
+ parser.getAttributeValue(null, ATTR_PACKAGE));
} else if (tag.equals(TAG_PROFILE_OWNER)) {
String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
+ Boolean profileEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_ENABLED));
int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID));
mProfileOwners.put(userId,
- new String[] { profileOwnerPackageName, profileOwnerName });
+ new OwnerInfo(
+ profileOwnerPackageName, profileOwnerName, profileEnabled));
} else {
throw new XmlPullParserException(
"Unexpected tag in device owner file: " + tag);
@@ -220,21 +236,22 @@
out.startDocument(null, true);
// Write device owner tag
- if (mDeviceOwnerPackageName != null) {
+ if (mDeviceOwner != null) {
out.startTag(null, TAG_DEVICE_OWNER);
- out.attribute(null, ATTR_PACKAGE, mDeviceOwnerPackageName);
- if (mDeviceOwnerName != null) {
- out.attribute(null, ATTR_NAME, mDeviceOwnerName);
+ out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName);
+ if (mDeviceOwner.packageName != null) {
+ out.attribute(null, ATTR_NAME, mDeviceOwner.packageName);
}
out.endTag(null, TAG_DEVICE_OWNER);
}
// Write profile owner tags
if (mProfileOwners.size() > 0) {
- for (HashMap.Entry<Integer, String[]> owner : mProfileOwners.entrySet()) {
+ for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) {
out.startTag(null, TAG_PROFILE_OWNER);
- out.attribute(null, ATTR_PACKAGE, owner.getValue()[0]);
- out.attribute(null, ATTR_NAME, owner.getValue()[1]);
+ out.attribute(null, ATTR_PACKAGE, owner.getValue().packageName);
+ out.attribute(null, ATTR_NAME, owner.getValue().name);
+ out.attribute(null, ATTR_ENABLED, String.valueOf(owner.getValue().enabled));
out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey()));
out.endTag(null, TAG_PROFILE_OWNER);
}
@@ -271,4 +288,20 @@
fileForWriting.finishWrite((FileOutputStream) stream);
}
}
+
+ static class OwnerInfo {
+ public String name;
+ public String packageName;
+ public boolean enabled = true; // only makes sense for managed profiles
+
+ public OwnerInfo(String name, String packageName, boolean enabled) {
+ this(name, packageName);
+ this.enabled = enabled;
+ }
+
+ public OwnerInfo(String name, String packageName) {
+ this.name = name;
+ this.packageName = packageName;
+ }
+ }
}
\ No newline at end of file
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d6f9dea..cf45149 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2900,9 +2900,13 @@
}
// Check if this is the profile owner who is calling
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- Slog.d(LOG_TAG, "Enabling the profile for: " + UserHandle.getCallingUserId());
- long id = Binder.clearCallingIdentity();
+ int userId = UserHandle.getCallingUserId();
+ Slog.d(LOG_TAG, "Enabling the profile for: " + userId);
+ mDeviceOwner.setProfileEnabled(userId);
+ mDeviceOwner.writeOwnerFile();
+
+ long id = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
@@ -2944,6 +2948,23 @@
return null;
}
+ @Override
+ public boolean isProfileEnabled(int userHandle) {
+ if (!mHasFeature) {
+ // If device policy management is not enabled, then the userHandle cannot belong to a
+ // managed profile. All other profiles are considered enabled.
+ return true;
+ }
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+
+ synchronized (this) {
+ if (mDeviceOwner != null) {
+ return mDeviceOwner.isProfileEnabled(userHandle);
+ }
+ }
+ return true;
+ }
+
private boolean isDeviceProvisioned() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) > 0;