Merge "Add policy for enforcing that all users are ephemeral."

This commit is contained in:
Lenka Trochtova
2016-01-27 20:58:55 +00:00
committed by Android (Google) Code Review
5 changed files with 199 additions and 15 deletions

View File

@@ -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.
*
* <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

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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 {

View File

@@ -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));