Merge "Fixed DPM.logoutUser() for headless system user mode." into sc-v2-dev
This commit is contained in:
@@ -9565,7 +9565,14 @@ public class DevicePolicyManager {
|
||||
|
||||
/**
|
||||
* Called by a profile owner of secondary user that is affiliated with the device to stop the
|
||||
* calling user and switch back to primary.
|
||||
* calling user and switch back to primary user.
|
||||
*
|
||||
* <p>Notice that on devices running with
|
||||
* {@link UserManager#isHeadlessSystemUserMode() headless system user mode}, there is no primary
|
||||
* user, so it switches back to the user that was in the foreground before the first call to
|
||||
* {@link #switchUser(ComponentName, UserHandle)} (or fails with
|
||||
* {@link UserManager#USER_OPERATION_ERROR_UNKNOWN} if that method was not called prior to this
|
||||
* call).
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
|
||||
* @return one of the following result codes:
|
||||
|
||||
@@ -697,6 +697,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
|
||||
private DevicePolicyConstants mConstants;
|
||||
|
||||
/**
|
||||
* User to be switched to on {@code logoutUser()}.
|
||||
*
|
||||
* <p>Only used on devices with headless system user mode
|
||||
*/
|
||||
@GuardedBy("getLockObject()")
|
||||
private @UserIdInt int mLogoutUserId = UserHandle.USER_NULL;
|
||||
|
||||
private static final boolean ENABLE_LOCK_GUARD = true;
|
||||
|
||||
/**
|
||||
@@ -9673,6 +9681,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
mStatLogger.dump(pw);
|
||||
pw.println();
|
||||
pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
|
||||
pw.println("Logout user: " + getLogoutUserId());
|
||||
pw.println();
|
||||
|
||||
if (mPendingUserCreatedCallbackTokens.isEmpty()) {
|
||||
@@ -10782,6 +10791,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
|
||||
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SWITCH_USER);
|
||||
|
||||
boolean switched = false;
|
||||
// Save previous logout user id in case of failure
|
||||
int logoutUserId = getLogoutUserId();
|
||||
synchronized (getLockObject()) {
|
||||
long id = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
@@ -10789,16 +10801,55 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
if (userHandle != null) {
|
||||
userId = userHandle.getIdentifier();
|
||||
}
|
||||
return mInjector.getIActivityManager().switchUser(userId);
|
||||
Slogf.i(LOG_TAG, "Switching to user %d (logout user is %d)", userId, logoutUserId);
|
||||
setLogoutUserIdLocked(UserHandle.USER_CURRENT);
|
||||
switched = mInjector.getIActivityManager().switchUser(userId);
|
||||
if (!switched) {
|
||||
Slogf.w(LOG_TAG, "Failed to switch to user %d", userId);
|
||||
}
|
||||
return switched;
|
||||
} catch (RemoteException e) {
|
||||
Slogf.e(LOG_TAG, "Couldn't switch user", e);
|
||||
return false;
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(id);
|
||||
if (!switched) {
|
||||
setLogoutUserIdLocked(logoutUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @UserIdInt int getLogoutUserId() {
|
||||
if (!mInjector.userManagerIsHeadlessSystemUserMode()) {
|
||||
// mLogoutUserId is USER_SYSTEM as well, but there's no need to acquire the lock
|
||||
return UserHandle.USER_SYSTEM;
|
||||
}
|
||||
synchronized (getLockObject()) {
|
||||
return mLogoutUserId;
|
||||
}
|
||||
}
|
||||
|
||||
private void setLogoutUserId(@UserIdInt int userId) {
|
||||
if (!mInjector.userManagerIsHeadlessSystemUserMode()) return; // ignore
|
||||
|
||||
synchronized (getLockObject()) {
|
||||
setLogoutUserIdLocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("getLockObject()")
|
||||
private void setLogoutUserIdLocked(@UserIdInt int userId) {
|
||||
if (!mInjector.userManagerIsHeadlessSystemUserMode()) return; // ignore
|
||||
|
||||
if (userId == UserHandle.USER_CURRENT) {
|
||||
userId = getCurrentForegroundUserId();
|
||||
}
|
||||
|
||||
Slogf.d(LOG_TAG, "setLogoutUserId(): %d -> %d", mLogoutUserId, userId);
|
||||
mLogoutUserId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startUserInBackground(ComponentName who, UserHandle userHandle) {
|
||||
Objects.requireNonNull(who, "ComponentName is null");
|
||||
@@ -10820,10 +10871,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
return UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
|
||||
}
|
||||
|
||||
Slogf.i(LOG_TAG, "Starting user %d in background", userId);
|
||||
if (mInjector.getIActivityManager().startUserInBackground(userId)) {
|
||||
Slogf.i(LOG_TAG, "Started used %d in background", userId);
|
||||
return UserManager.USER_OPERATION_SUCCESS;
|
||||
} else {
|
||||
Slogf.w(LOG_TAG, "failed to start user %d in background", userId);
|
||||
return UserManager.USER_OPERATION_ERROR_UNKNOWN;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
@@ -10871,13 +10923,30 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
return UserManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
|
||||
}
|
||||
|
||||
// TODO(b/204585343): remove the headless system user check?
|
||||
if (mInjector.userManagerIsHeadlessSystemUserMode() && callingUserId != mInjector
|
||||
.binderWithCleanCallingIdentity(() -> getCurrentForegroundUserId())) {
|
||||
Slogf.d(LOG_TAG, "logoutUser(): user %d is in background, just stopping, not switching",
|
||||
callingUserId);
|
||||
return stopUserUnchecked(callingUserId);
|
||||
}
|
||||
|
||||
int logoutUserId = getLogoutUserId();
|
||||
if (logoutUserId == UserHandle.USER_NULL) {
|
||||
// Could happen on devices using headless system user mode when called before calling
|
||||
// switchUser() or startUserInBackground() first
|
||||
Slogf.w(LOG_TAG, "logoutUser(): could not determine which user to switch to");
|
||||
return UserManager.USER_OPERATION_ERROR_UNKNOWN;
|
||||
}
|
||||
final long id = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
if (!mInjector.getIActivityManager().switchUser(UserHandle.USER_SYSTEM)) {
|
||||
Slogf.w(LOG_TAG, "Failed to switch to primary user");
|
||||
// This should never happen as target user is UserHandle.USER_SYSTEM
|
||||
Slogf.i(LOG_TAG, "logoutUser(): switching to user %d", logoutUserId);
|
||||
if (!mInjector.getIActivityManager().switchUser(logoutUserId)) {
|
||||
Slogf.w(LOG_TAG, "Failed to switch to user %d", logoutUserId);
|
||||
// This should never happen as target user is determined by getPreviousUserId()
|
||||
return UserManager.USER_OPERATION_ERROR_UNKNOWN;
|
||||
}
|
||||
setLogoutUserId(UserHandle.USER_CURRENT);
|
||||
} catch (RemoteException e) {
|
||||
// Same process, should not happen.
|
||||
return UserManager.USER_OPERATION_ERROR_UNKNOWN;
|
||||
@@ -10888,7 +10957,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
return stopUserUnchecked(callingUserId);
|
||||
}
|
||||
|
||||
private int stopUserUnchecked(int userId) {
|
||||
private int stopUserUnchecked(@UserIdInt int userId) {
|
||||
Slogf.i(LOG_TAG, "Stopping user %d", userId);
|
||||
final long id = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
switch (mInjector.getIActivityManager().stopUser(userId, true /*force*/, null)) {
|
||||
|
||||
Reference in New Issue
Block a user