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

Commit 5ccf6c38 authored by Clara Thomas's avatar Clara Thomas Committed by Android (Google) Code Review
Browse files

Merge "Allow IMMS to switch to an "always visible" user profile" into main

parents c0d0ae4f 80a44eb8
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -3799,8 +3799,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
                            scheduleSwitchUserTaskLocked(userId, cs.mClient);
                            return InputBindResult.USER_SWITCHING;
                        }
                        final int[] profileIdsWithDisabled = mUserManagerInternal.getProfileIds(
                                mCurrentImeUserId, false /* enabledOnly */);
                        final int[] profileIdsWithDisabled = getProfileIds(mCurrentImeUserId);
                        for (int profileId : profileIdsWithDisabled) {
                            if (profileId == userId) {
                                scheduleSwitchUserTaskLocked(userId, cs.mClient);
@@ -3847,9 +3846,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.

                    // Verify if caller is a background user.
                    if (!mConcurrentMultiUserModeEnabled && userId != mCurrentImeUserId) {
                        if (ArrayUtils.contains(
                                mUserManagerInternal.getProfileIds(mCurrentImeUserId, false),
                                userId)) {
                        if (ArrayUtils.contains(getProfileIds(mCurrentImeUserId), userId)) {
                            // cross-profile access is always allowed here to allow
                            // profile-switching.
                            scheduleSwitchUserTaskLocked(userId, cs.mClient);
@@ -4023,6 +4020,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
        return res;
    }

    @NonNull
    private int[] getProfileIds(@UserIdInt int userId) {
        if (android.multiuser.Flags.allowSupervisingProfile()) {
            return mUserManagerInternal.getProfileIds(userId, /* enabledOnly */ false,
                    /* includeAlwaysVisible */ true);
        }
        return mUserManagerInternal.getProfileIds(userId, /* enabledOnly */ false);
    }

    @GuardedBy("ImfLock.class")
    private boolean canInteractWithImeLocked(int uid, IInputMethodClient client, String methodName,
            @Nullable ImeTracker.Token statsToken, @UserIdInt int userId) {
+16 −0
Original line number Diff line number Diff line
@@ -328,6 +328,22 @@ public abstract class UserManagerInternal {
     */
    public abstract @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly);

    /**
     * Returns an array of ids for profiles associated with the specified user including the user
     * itself.
     * <p>Note that this includes all profile types (not including Restricted profiles), and,
     * optionally, any {@link UserProperties#getAlwaysVisible() always visible} profiles.
     *
     * @param userId      id of the user to return profiles for
     * @param enabledOnly whether return only {@link UserInfo#isEnabled() enabled} profiles
     * @param includeAlwaysVisible whether to also include {@link UserProperties#getAlwaysVisible()
     *        visible} profiles, even if userId is not their parent
     * @return A non-empty array of ids of profiles associated with the specified user if the user
     *         exists. Otherwise, an empty array.
     */
    public abstract @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly,
            boolean includeAlwaysVisible);

    /**
     * Returns a list of the users that are associated with the specified user, including the user
     * itself. This includes the user, its profiles, its parent, and its parent's other profiles,
+35 −3
Original line number Diff line number Diff line
@@ -1652,6 +1652,13 @@ public class UserManagerService extends IUserManager.Stub {
        return users;
    }

    @GuardedBy("mUsersLock")
    private IntArray getProfileIdsLU(@UserIdInt int userId, @Nullable String userType,
            boolean enabledOnly, boolean excludeHidden) {
        return getProfileIdsLU(userId, userType, enabledOnly, excludeHidden,
                /* includeAlwaysVisible */ false);
    }

    /**
     *  Assume permissions already checked and caller's identity cleared
     *  <p>If userType is {@code null}, returns all profiles for user; else, only returns
@@ -1659,7 +1666,7 @@ public class UserManagerService extends IUserManager.Stub {
     */
    @GuardedBy("mUsersLock")
    private IntArray getProfileIdsLU(@UserIdInt int userId, @Nullable String userType,
            boolean enabledOnly, boolean excludeHidden) {
            boolean enabledOnly, boolean excludeHidden, boolean includeAlwaysVisible) {
        UserInfo user = getUserInfoLU(userId);
        IntArray result = new IntArray(mUsers.size());
        if (user == null) {
@@ -1669,7 +1676,10 @@ public class UserManagerService extends IUserManager.Stub {
        final int userSize = mUsers.size();
        for (int i = 0; i < userSize; i++) {
            UserInfo profile = mUsers.valueAt(i).info;
            if (!isSameProfileGroup(user, profile)) {
            if (!includeAlwaysVisible && !isSameProfileGroup(user, profile)) {
                continue;
            }
            if (includeAlwaysVisible && !isSameProfileGroupOrIsAlwaysVisible(user, profile)) {
                continue;
            }
            if (enabledOnly && !profile.isEnabled()) {
@@ -1741,6 +1751,22 @@ public class UserManagerService extends IUserManager.Stub {
        return isSameProfileGroupNoChecks(userId, otherUserId);
    }

    /**
     * Returns whether the users are in the same profile group, or if either the asker or the
     * target is an always visible profile.
     */
    @GuardedBy("mUsersLock")
    private boolean isSameProfileGroupOrIsAlwaysVisible(UserInfo asker, UserInfo target) {
        if (asker.id == target.id) return true;
        UserData askerData = getUserDataLU(asker.id);
        if (askerData != null && askerData.userProperties.getAlwaysVisible()) {
            return true;
        }
        UserData targetData = getUserDataLU(target.id);
        return (targetData != null && targetData.userProperties.getAlwaysVisible())
                || isSameProfileGroup(asker, target);
    }

    /** Returns whether users are in the same profile group. */
    private boolean isSameProfileGroupNoChecks(@UserIdInt int userId, int otherUserId) {
        synchronized (mUsersLock) {
@@ -8046,9 +8072,15 @@ public class UserManagerService extends IUserManager.Stub {

        @Override
        public @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
            return getProfileIds(userId, enabledOnly, /* includeAlwaysVisible */ false);
        }

        @Override
        public @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly,
                boolean includeAlwaysVisible) {
            synchronized (mUsersLock) {
                return getProfileIdsLU(userId, null /* userType */, enabledOnly, /* excludeHidden */
                        false).toArray();
                        false, includeAlwaysVisible).toArray();
            }
        }

+2 −0
Original line number Diff line number Diff line
@@ -225,6 +225,8 @@ public class InputMethodManagerServiceTestBase {
        when(mMockUserManagerInternal.isUserRunning(anyInt())).thenReturn(true);
        when(mMockUserManagerInternal.getProfileIds(anyInt(), anyBoolean()))
                .thenReturn(new int[] {0});
        when(mMockUserManagerInternal.getProfileIds(anyInt(), anyBoolean(), anyBoolean()))
                .thenReturn(new int[] {0});
        when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[] {0});
        when(mMockActivityManagerInternal.isSystemReady()).thenReturn(true);
        when(mMockActivityManagerInternal.getCurrentUserId()).thenReturn(mUserId);
+17 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.os.UserManager.DISALLOW_SMS;
import static android.os.UserManager.DISALLOW_USER_SWITCH;
import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
import static android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -828,6 +829,22 @@ public final class UserManagerServiceMockedTest {
        }
    }

    @Test
    @EnableFlags({android.multiuser.Flags.FLAG_ALLOW_SUPERVISING_PROFILE})
    public void testGetProfileIdsIncludingAlwaysVisible_supervisingProfile() {
        UserInfo supervisingProfile = mUms.createUserWithThrow("Supervising",
                USER_TYPE_PROFILE_SUPERVISING, 0);
        int mainUserId = mUms.getMainUserId();
        assertThat(mUmi.getProfileIds(mainUserId, /* enabledOnly */ true,
                /* includeAlwaysVisible */ true)).asList().containsExactly(
                        mainUserId, supervisingProfile.id);
        assertThat(mUmi.getProfileIds(mainUserId, /* enabledOnly */ true,
                /* includeAlwaysVisible */ false)).asList().containsExactly(mainUserId);
        assertThat(mUmi.getProfileIds(supervisingProfile.id, /* enabledOnly */ true,
                /* includeAlwaysVisible */ true)).asList().containsExactly(
                        mainUserId, supervisingProfile.id);
    }

    @Test
    @RequiresFlagsEnabled({
        FLAG_ALLOW_PRIVATE_PROFILE,