diff options
8 files changed, 149 insertions, 35 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index db08a41..d7170e8 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1816,6 +1816,27 @@ public class DevicePolicyManager { /** * @hide + * @param userId the userId of a managed profile profile. + * + * @return whether or not the managed profile is enabled. + * @throws IllegalArgumentException if the userId is invalid. + */ + public boolean isProfileEnabled(int userId) throws IllegalArgumentException { + if (mService != null) { + try { + return mService.isProfileEnabled(userId); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get status for owner profile."); + throw new IllegalArgumentException( + "Failed to get status for owner profile.", re); + } + } + return true; + } + + + /** + * @hide * @return the human readable name of the organisation associated with this DPM or null if * one is not set. * @throws IllegalArgumentException if the userId is invalid. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 4ed85e9..85ba58b 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -109,6 +109,7 @@ interface IDevicePolicyManager { String getProfileOwner(int userHandle); String getProfileOwnerName(int userHandle); void setProfileEnabled(in ComponentName who); + boolean isProfileEnabled(int userHandle); boolean installCaCert(in byte[] certBuffer); void uninstallCaCert(in byte[] certBuffer); diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 1192a45..c3f7370 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -34,7 +34,7 @@ interface IUserManager { void setUserIcon(int userHandle, in Bitmap icon); Bitmap getUserIcon(int userHandle); List<UserInfo> getUsers(boolean excludeDying); - List<UserInfo> getProfiles(int userHandle); + List<UserInfo> getProfiles(int userHandle, boolean enabledOnly); UserInfo getUserInfo(int userHandle); boolean isRestricted(); void setGuestEnabled(boolean enable); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 7bac3af..63de9a0 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -466,6 +466,8 @@ public class UserManager { /** * Returns list of the profiles of userHandle including * userHandle itself. + * Note that it this returns both enabled and not enabled profiles. See + * {@link #getUserProfiles()} if you need only the enabled ones. * * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * @param userHandle profiles of this user will be returned. @@ -474,7 +476,7 @@ public class UserManager { */ public List<UserInfo> getProfiles(int userHandle) { try { - return mService.getProfiles(userHandle); + return mService.getProfiles(userHandle, false /* enabledOnly */); } catch (RemoteException re) { Log.w(TAG, "Could not get user list", re); return null; @@ -488,7 +490,13 @@ public class UserManager { */ public List<UserHandle> getUserProfiles() { ArrayList<UserHandle> profiles = new ArrayList<UserHandle>(); - List<UserInfo> users = getProfiles(UserHandle.myUserId()); + List<UserInfo> users = new ArrayList<UserInfo>(); + try { + users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */); + } catch (RemoteException re) { + Log.w(TAG, "Could not get user list", re); + return null; + } for (UserInfo info : users) { UserHandle userHandle = new UserHandle(info.id); profiles.add(userHandle); 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 @@ public final class ActivityManagerService extends ActivityManagerNative * 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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..210e151 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.ActivityManagerNative; 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 @@ public class UserManagerService extends IUserManager.Stub { } @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 @@ public class UserManagerService extends IUserManager.Stub { 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 @@ public class DeviceOwner { 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 @@ public class DeviceOwner { 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 @@ public class DeviceOwner { */ 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 @@ public class DeviceOwner { */ 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 @@ public class DeviceOwner { } 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 @@ public class DeviceOwner { 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 @@ public class DeviceOwner { 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 @@ public class DeviceOwner { 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } // 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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; |