Skip to content

Commit

Permalink
Merge "Add policy for enforcing that all users are ephemeral."
Browse files Browse the repository at this point in the history
  • Loading branch information
Lenka Trochtova authored and Android (Google) Code Review committed Jan 27, 2016
2 parents 21d2113 + f348e8e commit 2b04a58
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 15 deletions.
39 changes: 39 additions & 0 deletions core/java/android/app/admin/DevicePolicyManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,45 @@ public boolean getAutoTimeRequired() {
return false;
}

/**
* 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
Expand Down
3 changes: 3 additions & 0 deletions core/java/android/app/admin/IDevicePolicyManager.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 15 additions & 0 deletions core/java/android/os/UserManagerInternal.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,19 @@ public abstract void setBaseUserRestrictionsByDpmsForMigration(int userId,
* 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();
}
93 changes: 79 additions & 14 deletions services/core/java/com/android/server/pm/UserManagerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -302,6 +304,12 @@ void clearSeedAccountData() {

private final LockPatternUtils mLockPatternUtils;

/**
* Whether all users should be created ephemeral.
*/
@GuardedBy("mUsersLock")
private boolean mForceEphemeralUsers;

private static UserManagerService sInstance;

public static UserManagerService getInstance() {
Expand Down Expand Up @@ -1836,23 +1844,25 @@ private UserInfo createUserInternal(String name, int flags, int parentId) {
}
}

// 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();
Expand Down Expand Up @@ -2914,6 +2924,61 @@ public void setUserIcon(int userId, Bitmap bitmap) {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ static class ActiveAdmin {
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";
Expand Down Expand Up @@ -559,6 +560,7 @@ static class ActiveAdmin {
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;
Expand Down Expand Up @@ -749,6 +751,11 @@ void writeToXml(XmlSerializer out)
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));
Expand Down Expand Up @@ -919,7 +926,10 @@ void readFromXml(XmlPullParser parser)
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(
Expand Down Expand Up @@ -1150,6 +1160,8 @@ void dump(String prefix, PrintWriter pw) {
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=");
Expand Down Expand Up @@ -2408,6 +2420,14 @@ private void onLockSettingsReady() {
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() {
Expand Down Expand Up @@ -4789,6 +4809,46 @@ public boolean getAutoTimeRequired() {
}
}

@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);
Expand Down Expand Up @@ -5319,6 +5379,8 @@ public void clearDeviceOwner(String packageName) {
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
admin.forceEphemeralUsers = false;
mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
}

clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
Expand Down

0 comments on commit 2b04a58

Please sign in to comment.