From 670c8895beaae6303ff6414b4ee97d29f0451fcb Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 11 Nov 2021 14:54:07 -0800 Subject: [PATCH] New hidden DPM methods: getLogoutUserId() and clearLogoutUser(). Also fixed how the logout user was cleared after a successful switch. They will be used by CarSystemUi to end a session. Test: Manual verification with CtsVerifier and TestDpc on automotive Bug: 205185521 Bug: 204483021 Change-Id: Ieda0a22625ef705fcd705aedfc2dbf2cf570bf81 --- .../app/admin/DevicePolicyManager.java | 31 +++++++++++++++++++ .../app/admin/IDevicePolicyManager.aidl | 2 ++ .../GlobalActionsDialogLite.java | 3 ++ .../DevicePolicyManagerService.java | 30 +++++++++++++----- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9c352dfa76cd2..556dfc7a96b3b 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -9609,6 +9609,37 @@ public class DevicePolicyManager { } } + /** + * Gets the user a {@link #logoutUser(ComponentName)} call would switch to, + * or {@link UserHandle#USER_NULL} if the current user is not in a session. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public @UserIdInt int getLogoutUserId() { + try { + return mService.getLogoutUserId(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * Clears the user that {@link #logoutUser(ComponentName)} would switch to. + * + *

Typically used by system UI after it logout a session. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public void clearLogoutUser() { + try { + mService.clearLogoutUser(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + /** * Called by a device owner to list all secondary users on the device. Managed profiles are not * considered as secondary users. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 1c9187d8d22cb..7c7478bdb41fb 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -261,6 +261,8 @@ interface IDevicePolicyManager { int startUserInBackground(in ComponentName who, in UserHandle userHandle); int stopUser(in ComponentName who, in UserHandle userHandle); int logoutUser(in ComponentName who); + int getLogoutUserId(); + void clearLogoutUser(); List getSecondaryUsers(in ComponentName who); void resetNewUserDisclaimer(); diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index b06b024a63a46..ad472326555ec 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -607,6 +607,9 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } else if (GLOBAL_ACTION_KEY_SCREENSHOT.equals(actionKey)) { addIfShouldShowAction(tempActions, new ScreenshotAction()); } else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) { + // TODO(b/206032495): should call mDevicePolicyManager.getLogoutUserId() instead of + // hardcode it to USER_SYSTEM so it properly supports headless system user mode + // (and then call mDevicePolicyManager.clearLogoutUser() after switched) if (mDevicePolicyManager.isLogoutEnabled() && currentUser.get() != null && currentUser.get().id != UserHandle.USER_SYSTEM) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index db13ae2759651..55c434a09853c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -9692,7 +9692,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mStatLogger.dump(pw); pw.println(); pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus())); - pw.println("Logout user: " + getLogoutUserId()); + pw.println("Logout user: " + getLogoutUserIdUnchecked()); pw.println(); if (mPendingUserCreatedCallbackTokens.isEmpty()) { @@ -10804,7 +10804,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { boolean switched = false; // Save previous logout user id in case of failure - int logoutUserId = getLogoutUserId(); + int logoutUserId = getLogoutUserIdUnchecked(); synchronized (getLockObject()) { long id = mInjector.binderClearCallingIdentity(); try { @@ -10831,7 +10831,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private @UserIdInt int getLogoutUserId() { + @Override + public int getLogoutUserId() { + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())); + + return getLogoutUserIdUnchecked(); + } + + private @UserIdInt int getLogoutUserIdUnchecked() { if (!mInjector.userManagerIsHeadlessSystemUserMode()) { // mLogoutUserId is USER_SYSTEM as well, but there's no need to acquire the lock return UserHandle.USER_SYSTEM; @@ -10841,11 +10848,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private void setLogoutUserId(@UserIdInt int userId) { + @Override + public void clearLogoutUser() { + CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization(canManageUsers(caller)); + + Slogf.i(LOG_TAG, "Clearing logout user as requested by %s", caller); + clearLogoutUserUnchecked(); + } + + private void clearLogoutUserUnchecked() { if (!mInjector.userManagerIsHeadlessSystemUserMode()) return; // ignore synchronized (getLockObject()) { - setLogoutUserIdLocked(userId); + setLogoutUserIdLocked(UserHandle.USER_NULL); } } @@ -10942,7 +10958,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return stopUserUnchecked(callingUserId); } - int logoutUserId = getLogoutUserId(); + int logoutUserId = getLogoutUserIdUnchecked(); if (logoutUserId == UserHandle.USER_NULL) { // Could happen on devices using headless system user mode when called before calling // switchUser() or startUserInBackground() first @@ -10957,7 +10973,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // This should never happen as target user is determined by getPreviousUserId() return UserManager.USER_OPERATION_ERROR_UNKNOWN; } - setLogoutUserId(UserHandle.USER_CURRENT); + clearLogoutUserUnchecked(); } catch (RemoteException e) { // Same process, should not happen. return UserManager.USER_OPERATION_ERROR_UNKNOWN;