Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52660ae7 authored by Felipe Leme's avatar Felipe Leme
Browse files

Replaces DPM.clearLogoutUser() by logoutUser()

Prior to this change, internal components like Settings or
CarUserManager would need to call 3 APIs to logout a managed user:

1. previousUserId = getLogoutUser();
2. switchUser(previousUserId);
3. clearLogoutUser();

This CL encapsulates the whole process into a new DPM.logoutUser(),
but it keeps the getLogoutUser() (as Car need to know which user it
will be switched to in advance, due to the Vehicle HAL integration).

Test: m update-api
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Test: atest com.android.cts.devicepolicy.DeviceOwnerTest#testCreateAndManageUser_LogoutUser_system

Fixes: 214336184

Change-Id: Ifffc229ecede5d086338e9c7fa08dce0e0de884c
parent 278967f2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -63,8 +63,8 @@ package android.app.admin {

  public class DevicePolicyManager {
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void acknowledgeNewUserDisclaimer();
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearLogoutUser();
    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getLogoutUser();
    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getLogoutUser();
    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public int logoutUser();
    field public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = "android.app.action.SHOW_NEW_USER_DISCLAIMER";
  }

+12 −13
Original line number Diff line number Diff line
@@ -10018,36 +10018,35 @@ public class DevicePolicyManager {
    }
    /**
     * Gets the user a {@link #logoutUser(ComponentName)} call would switch to,
     * or {@code null} if the current user is not in a session.
     * Same as {@link #logoutUser(ComponentName)}, but called by system (like Settings), not admin.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
            android.Manifest.permission.CREATE_USERS})
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    public @Nullable UserHandle getLogoutUser() {
    public @UserOperationResult int logoutUser() {
        // TODO(b/214336184): add CTS test
        try {
            int userId = mService.getLogoutUserId();
            return userId == UserHandle.USER_NULL ? null : UserHandle.of(userId);
            return mService.logoutUserInternal();
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }
    /**
     * Clears the user that {@link #logoutUser(ComponentName)} would switch to.
     *
     * <p>Typically used by system UI after it logout a session.
     * Gets the user a {@link #logoutUser(ComponentName)} call would switch to,
     * or {@code null} if the current user is not in a session.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
            android.Manifest.permission.INTERACT_ACROSS_USERS})
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    public void clearLogoutUser() {
    public @Nullable UserHandle getLogoutUser() {
        // TODO(b/214336184): add CTS test
        try {
            mService.clearLogoutUser();
            int userId = mService.getLogoutUserId();
            return userId == UserHandle.USER_NULL ? null : UserHandle.of(userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
+1 −1
Original line number Diff line number Diff line
@@ -264,8 +264,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 logoutUserInternal(); // AIDL doesn't allow overloading name (logoutUser())
    int getLogoutUserId();
    void clearLogoutUser();
    List<UserHandle> getSecondaryUsers(in ComponentName who);
    void acknowledgeNewUserDisclaimer();

+20 −13
Original line number Diff line number Diff line
@@ -10977,7 +10977,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    @Override
    public int getLogoutUserId() {
        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
                || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS));
        return getLogoutUserIdUnchecked();
    }
@@ -10992,16 +10993,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
    }
    @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() {
    private void clearLogoutUser() {
        if (!mInjector.userManagerIsHeadlessSystemUserMode()) return; // ignore
        synchronized (getLockObject()) {
@@ -11102,6 +11094,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            return stopUserUnchecked(callingUserId);
        }
        return logoutUserUnchecked(/* userIdToStop= */ callingUserId);
    }
    @Override
    public int logoutUserInternal() {
        CallerIdentity caller = getCallerIdentity();
        Preconditions.checkCallAuthorization(
                canManageUsers(caller) || hasCallingOrSelfPermission(permission.CREATE_USERS));
        int result = logoutUserUnchecked(getCurrentForegroundUserId());
        Slogf.d(LOG_TAG, "logout called by uid %d. Result: %d", caller.getUid(), result);
        return result;
    }
    private int logoutUserUnchecked(@UserIdInt int userIdToStop) {
        int logoutUserId = getLogoutUserIdUnchecked();
        if (logoutUserId == UserHandle.USER_NULL) {
            // Could happen on devices using headless system user mode when called before calling
@@ -11117,7 +11124,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                // This should never happen as target user is determined by getPreviousUserId()
                return UserManager.USER_OPERATION_ERROR_UNKNOWN;
            }
            clearLogoutUserUnchecked();
            clearLogoutUser();
        } catch (RemoteException e) {
            // Same process, should not happen.
            return UserManager.USER_OPERATION_ERROR_UNKNOWN;
@@ -11125,7 +11132,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            mInjector.binderRestoreCallingIdentity(id);
        }
        return stopUserUnchecked(callingUserId);
        return stopUserUnchecked(userIdToStop);
    }
    private int stopUserUnchecked(@UserIdInt int userId) {