diff options
| author | 2016-01-27 20:58:55 +0000 | |
|---|---|---|
| committer | 2016-01-27 20:58:55 +0000 | |
| commit | 2b04a58dca450a03c5aab6cca02ae0ac8ec950e1 (patch) | |
| tree | 59900f3ee5ec27de21bc1f735f81feaa884e432c | |
| parent | 21d2113139dd05d120a391390e2bd88e526d951e (diff) | |
| parent | f348e8e22bed4b56fdb0c02702d12b36467dedd7 (diff) | |
Merge "Add policy for enforcing that all users are ephemeral."
5 files changed, 199 insertions, 15 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 1c1526fc2d45..768da6a41136 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2770,6 +2770,45 @@ public class DevicePolicyManager { } /** + * Called by a device owner to set whether all users created on the device should be ephemeral. + * + * <p>The system user is exempt from this policy - it is never ephemeral. + * + * <p>The calling device admin must be the device owner. If it is not, a security exception will + * be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param forceEphemeralUsers If true, all the existing users will be deleted and all + * subsequently created users will be ephemeral. + * @hide + */ + public void setForceEphemeralUsers( + @NonNull ComponentName admin, boolean forceEphemeralUsers) { + if (mService != null) { + try { + mService.setForceEphemeralUsers(admin, forceEphemeralUsers); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + } + + /** + * @return true if all users are created ephemeral. + * @hide + */ + public boolean getForceEphemeralUsers(@NonNull ComponentName admin) { + if (mService != null) { + try { + return mService.getForceEphemeralUsers(admin); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return false; + } + + /** * Called by an application that is administering the device to disable keyguard customizations, * such as widgets. After setting this, keyguard features will be disabled according to the * provided feature list. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index a80ed9b88a93..20d4a299d826 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -230,6 +230,9 @@ interface IDevicePolicyManager { void setAutoTimeRequired(in ComponentName who, boolean required); boolean getAutoTimeRequired(); + void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers); + boolean getForceEphemeralUsers(in ComponentName who); + boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle); void setUserIcon(in ComponentName admin, in Bitmap icon); diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java index f76533697cda..58a026904373 100644 --- a/core/java/android/os/UserManagerInternal.java +++ b/core/java/android/os/UserManagerInternal.java @@ -91,4 +91,19 @@ public abstract class UserManagerInternal { * the icon is in this method. */ public abstract void setUserIcon(int userId, Bitmap bitmap); + + /** + * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to inform the + * user manager whether all users should be created ephemeral. + */ + public abstract void setForceEphemeralUsers(boolean forceEphemeralUsers); + + /** + * Switches to the system user and deletes all other users. + * + * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when + * the force-ephemeral-users policy is toggled on to make sure there are no pre-existing + * non-ephemeral users left. + */ + public abstract void removeAllUsers(); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index fc798497a3eb..0f614cad1127 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -25,9 +25,11 @@ import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.IActivityManager; import android.app.IStopUserCallback; +import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -302,6 +304,12 @@ public class UserManagerService extends IUserManager.Stub { private final LockPatternUtils mLockPatternUtils; + /** + * Whether all users should be created ephemeral. + */ + @GuardedBy("mUsersLock") + private boolean mForceEphemeralUsers; + private static UserManagerService sInstance; public static UserManagerService getInstance() { @@ -1836,23 +1844,25 @@ public class UserManagerService extends IUserManager.Stub { } } - // Add ephemeral flag to guests if required. Also inherit it from parent. + userId = getNextAvailableId(); + Environment.getUserSystemDirectory(userId).mkdirs(); boolean ephemeralGuests = Resources.getSystem() .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral); - if ((isGuest && ephemeralGuests) - || (parent != null && parent.info.isEphemeral())) { - flags |= UserInfo.FLAG_EPHEMERAL; - } - userId = getNextAvailableId(); - userInfo = new UserInfo(userId, name, null, flags); - userInfo.serialNumber = mNextSerialNumber++; - long now = System.currentTimeMillis(); - userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0; - userInfo.partial = true; - userData = new UserData(); - userData.info = userInfo; - Environment.getUserSystemDirectory(userInfo.id).mkdirs(); + synchronized (mUsersLock) { + // Add ephemeral flag to guests/users if required. Also inherit it from parent. + if ((isGuest && ephemeralGuests) || mForceEphemeralUsers + || (parent != null && parent.info.isEphemeral())) { + flags |= UserInfo.FLAG_EPHEMERAL; + } + + userInfo = new UserInfo(userId, name, null, flags); + userInfo.serialNumber = mNextSerialNumber++; + long now = System.currentTimeMillis(); + userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0; + userInfo.partial = true; + userData = new UserData(); + userData.info = userInfo; mUsers.put(userId, userData); } writeUserListLP(); @@ -2914,6 +2924,61 @@ public class UserManagerService extends IUserManager.Stub { Binder.restoreCallingIdentity(ident); } } + + @Override + public void setForceEphemeralUsers(boolean forceEphemeralUsers) { + synchronized (mUsersLock) { + mForceEphemeralUsers = forceEphemeralUsers; + } + } + + @Override + public void removeAllUsers() { + if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) { + // Remove the non-system users straight away. + removeNonSystemUsers(); + } else { + // Switch to the system user first and then remove the other users. + BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int userId = + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); + if (userId != UserHandle.USER_SYSTEM) { + return; + } + mContext.unregisterReceiver(this); + removeNonSystemUsers(); + } + }; + IntentFilter userSwitchedFilter = new IntentFilter(); + userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED); + mContext.registerReceiver( + userSwitchedReceiver, userSwitchedFilter, null, mHandler); + + // Switch to the system user. + ActivityManager am = + (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + am.switchUser(UserHandle.USER_SYSTEM); + } + } + } + + /* Remove all the users except of the system one. */ + private void removeNonSystemUsers() { + ArrayList<UserInfo> usersToRemove = new ArrayList<>(); + synchronized (mUsersLock) { + final int userSize = mUsers.size(); + for (int i = 0; i < userSize; i++) { + UserInfo ui = mUsers.valueAt(i).info; + if (ui.id != UserHandle.USER_SYSTEM) { + usersToRemove.add(ui); + } + } + } + for (UserInfo ui: usersToRemove) { + removeUser(ui.id); + } } private class Shell extends ShellCommand { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4fd8990d2dca..fe62d1596365 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -471,6 +471,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture"; private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management"; private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time"; + private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users"; private static final String TAG_ACCOUNT_TYPE = "account-type"; private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES = "permitted-accessiblity-services"; @@ -559,6 +560,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean disableBluetoothContactSharing = true; boolean disableScreenCapture = false; // Can only be set by a device/profile owner. boolean requireAutoTime = false; // Can only be set by a device owner. + boolean forceEphemeralUsers = false; // Can only be set by a device owner. ActiveAdmin parentAdmin; final boolean isParent; @@ -749,6 +751,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, ATTR_VALUE, Boolean.toString(requireAutoTime)); out.endTag(null, TAG_REQUIRE_AUTO_TIME); } + if (forceEphemeralUsers) { + out.startTag(null, TAG_FORCE_EPHEMERAL_USERS); + out.attribute(null, ATTR_VALUE, Boolean.toString(forceEphemeralUsers)); + out.endTag(null, TAG_FORCE_EPHEMERAL_USERS); + } if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) { out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES); out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures)); @@ -919,7 +926,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { disableScreenCapture = Boolean.parseBoolean( parser.getAttributeValue(null, ATTR_VALUE)); } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) { - requireAutoTime= Boolean.parseBoolean( + requireAutoTime = Boolean.parseBoolean( + parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) { + forceEphemeralUsers = Boolean.parseBoolean( parser.getAttributeValue(null, ATTR_VALUE)); } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) { disabledKeyguardFeatures = Integer.parseInt( @@ -1150,6 +1160,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(disableScreenCapture); pw.print(prefix); pw.print("requireAutoTime="); pw.println(requireAutoTime); + pw.print(prefix); pw.print("forceEphemeralUsers="); + pw.println(forceEphemeralUsers); pw.print(prefix); pw.print("disabledKeyguardFeatures="); pw.println(disabledKeyguardFeatures); pw.print(prefix); pw.print("crossProfileWidgetProviders="); @@ -2408,6 +2420,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (packageList != null) { mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList); } + + synchronized (this) { + // push the force-ephemeral-users policy to the user manager. + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + if (deviceOwner != null) { + mUserManagerInternal.setForceEphemeralUsers(deviceOwner.forceEphemeralUsers); + } + } } private void ensureDeviceOwnerUserStarted() { @@ -4789,6 +4809,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public void setForceEphemeralUsers(ComponentName who, boolean forceEphemeralUsers) { + if (!mHasFeature) { + return; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + boolean removeAllUsers = false; + synchronized (this) { + final ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + if (deviceOwner.forceEphemeralUsers != forceEphemeralUsers) { + deviceOwner.forceEphemeralUsers = forceEphemeralUsers; + saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + mUserManagerInternal.setForceEphemeralUsers(forceEphemeralUsers); + removeAllUsers = forceEphemeralUsers; + } + } + if (removeAllUsers) { + long identitity = mInjector.binderClearCallingIdentity(); + try { + mUserManagerInternal.removeAllUsers(); + } finally { + mInjector.binderRestoreCallingIdentity(identitity); + } + } + } + + @Override + public boolean getForceEphemeralUsers(ComponentName who) { + if (!mHasFeature) { + return false; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + synchronized (this) { + final ActiveAdmin deviceOwner = + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + return deviceOwner.forceEphemeralUsers; + } + } + private void ensureDeviceOwnerManagingSingleUser(ComponentName who) throws SecurityException { synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); @@ -5319,6 +5379,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (admin != null) { admin.disableCamera = false; admin.userRestrictions = null; + admin.forceEphemeralUsers = false; + mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers); } clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM)); |