Add policy for enforcing that all users are ephemeral.
BUG: 24883058
Change-Id: I8e53ca677c935a6c828dd6ece00b345d0eff182a
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fc79849..0f614ca 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.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 @@
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 @@
}
}
- // 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 @@
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 4fd8990..fe62d15 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+ @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 @@
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
+ admin.forceEphemeralUsers = false;
+ mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
}
clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));