diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 1c1526fc2d451..768da6a411366 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2769,6 +2769,45 @@ public class DevicePolicyManager { return false; } + /** + * Called by a device owner to set whether all users created on the device should be ephemeral. + * + *
The system user is exempt from this policy - it is never ephemeral. + * + *
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 diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index a80ed9b88a93d..20d4a299d8267 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 f76533697cda2..58a026904373c 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. + * + *
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 fc798497a3eb3..0f614cad11274 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