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

Commit 3ff48355 authored by Felipe Leme's avatar Felipe Leme Committed by Automerger Merge Worker
Browse files

Merge "Fixed DPM.logoutUser() for headless system user mode." into sc-v2-dev am: f1f95597

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16145450

Change-Id: I8a327d7bb4659b67d2ed3365b3640d88d9aee103
parents 1bba9291 f1f95597
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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:
+76 −6
Original line number Diff line number Diff line
@@ -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()) {
@@ -10783,6 +10792,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 {
@@ -10790,16 +10802,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");
@@ -10821,10 +10872,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) {
@@ -10872,13 +10924,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;
@@ -10889,7 +10958,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)) {