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

Commit f2170ca5 authored by Felipe Leme's avatar Felipe Leme
Browse files

Allow profiles on any full user.

Profiles used to be restricted just to the SYSTEM_USER (and later to
the main user), but from the framework point of view there is no need
for such restriction, hence this CL lifts it.

Test: atest FrameworksCoreTests:UserInfoTest
Test: adb shell aflags enable android.multiuser.profiles_for_all && adb reboot && adb shell pm create-user Homer && adb shell pm create-user --profileOf 11 --managed Bart
Bug: 374832167
Flag: android.multiuser.profiles_for_all

Change-Id: I5b4f89e24bb67656ccbd4447fee40f5078d39024
parent 6278f30a
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -494,10 +494,14 @@ public class UserInfo implements Parcelable {
    // TODO(b/142482943): Make this logic more specific and customizable. (canHaveProfile(userType))
    /* @hide */
    public boolean canHaveProfile() {
        if (isProfile() || isGuest() || isRestricted()) {
        if (!isFull() || isProfile() || isGuest() || isRestricted() || isDemo()) {
            return false;
        }
        return isMain();
        // NOTE: profiles used to be restricted just to the system user (and later to the main
        // user), but from the framework point of view there is no need for such restriction, hence
        // it's lifted
        // TODO(b/374832167): check value of config_supportProfilesOnNonMainUser
        return isMain() || android.multiuser.Flags.profilesForAll();
    }

    // TODO(b/142482943): Get rid of this (after removing it from all tests) if feasible.
+7 −0
Original line number Diff line number Diff line
@@ -646,3 +646,10 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
     name: "profiles_for_all"
     namespace: "multiuser"
     description: "Allows any regular user to have profiles"
     bug: "374832167"
}
+86 −4
Original line number Diff line number Diff line
@@ -16,19 +16,44 @@

package android.content.pm;

import static android.content.pm.UserInfo.FLAG_DEMO;
import static android.content.pm.UserInfo.FLAG_FULL;
import static android.content.pm.UserInfo.FLAG_GUEST;
import static android.content.pm.UserInfo.FLAG_MAIN;
import static android.content.pm.UserInfo.FLAG_PROFILE;
import static android.content.pm.UserInfo.FLAG_SYSTEM;
import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED;
import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;

import static com.google.common.truth.Truth.assertThat;

import android.content.pm.UserInfo.UserInfoFlag;
import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.google.common.truth.Expect;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;


@RunWith(AndroidJUnit4.class)
@SmallTest
public class UserInfoTest {
public final class UserInfoTest {

    @Rule
    public final SetFlagsRule flags =
            new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);

    @Rule public final Expect expect = Expect.create();

    @Test
    public void testSimple() throws Exception {
        final UserInfo ui = new UserInfo(10, "Test", UserInfo.FLAG_GUEST);
@@ -56,9 +81,6 @@ public class UserInfoTest {
        assertThat(ui.isInitialized()).isEqualTo(false);
        assertThat(ui.isFull()).isEqualTo(false);
        assertThat(ui.isMain()).isEqualTo(false);

        // Derived dynamically
        assertThat(ui.canHaveProfile()).isEqualTo(false);
    }

    @Test
@@ -68,4 +90,64 @@ public class UserInfoTest {
        assertThat(ui.toString()).isNotEmpty();
        assertThat(ui.toFullString()).isNotEmpty();
    }

    @Test
    @DisableFlags(android.multiuser.Flags.FLAG_PROFILES_FOR_ALL)
    public void testCanHaveProfile_flagProfilesForAllDisabled() {
        expectCannotHaveProfile("non-full user", createTestUserInfo(/* flags= */ 0));
        expectCannotHaveProfile("guest user", createTestUserInfo(FLAG_FULL | FLAG_GUEST));
        expectCanHaveProfile("main user", createTestUserInfo(FLAG_FULL | FLAG_MAIN));
        expectCannotHaveProfile("non-main user", createTestUserInfo(FLAG_FULL));
        expectCannotHaveProfile("demo user", createTestUserInfo(FLAG_FULL | FLAG_DEMO));
        expectCannotHaveProfile("restricted user",
                createTestUserInfo(USER_TYPE_FULL_RESTRICTED, FLAG_FULL));
        expectCannotHaveProfile("profile user", createTestUserInfo(FLAG_PROFILE));
        expectCanHaveProfile("(full) system user that's also main user",
                createTestUserInfo(USER_TYPE_FULL_SYSTEM, FLAG_FULL | FLAG_SYSTEM | FLAG_MAIN));
        expectCannotHaveProfile("headless system user that's not main user",
                createTestUserInfo(USER_TYPE_SYSTEM_HEADLESS, FLAG_SYSTEM));
    }

    @Test
    @EnableFlags(android.multiuser.Flags.FLAG_PROFILES_FOR_ALL)
    public void testCanHaveProfile_flagProfilesForAllEnabled() {
        expectCannotHaveProfile("non-full user", createTestUserInfo(/* flags= */ 0));
        expectCannotHaveProfile("guest user", createTestUserInfo(FLAG_FULL | FLAG_GUEST));
        expectCanHaveProfile("main user", createTestUserInfo(FLAG_FULL | FLAG_MAIN));
        expectCanHaveProfile("non-main user", createTestUserInfo(FLAG_FULL));
        expectCannotHaveProfile("demo user", createTestUserInfo(FLAG_FULL | FLAG_DEMO));
        expectCannotHaveProfile("restricted user",
                createTestUserInfo(USER_TYPE_FULL_RESTRICTED, FLAG_FULL));
        expectCannotHaveProfile("profile user", createTestUserInfo(FLAG_PROFILE));
        expectCanHaveProfile("(full) system user that's also main user",
                createTestUserInfo(USER_TYPE_FULL_SYSTEM, FLAG_FULL | FLAG_SYSTEM | FLAG_MAIN));
        expectCannotHaveProfile("headless system user that's not main user",
                createTestUserInfo(USER_TYPE_SYSTEM_HEADLESS, FLAG_SYSTEM));
    }

    /**
     * Creates a new {@link UserInfo} with id {@code 10}, name {@code Test}, and the given
     * {@code flags}.
     */
    private UserInfo createTestUserInfo(@UserInfoFlag int flags) {
        return new UserInfo(10, "Test", flags);
    }

    /**
     * Creates a new {@link UserInfo} with id {@code 10}, name {@code Test}, and the given
     * {@code userType} and {@code flags}.
     */
    private UserInfo createTestUserInfo(String userType, @UserInfoFlag int flags) {
        return new UserInfo(10, "Test", /* iconPath= */ null, flags, userType);
    }

    private void expectCanHaveProfile(String description, UserInfo user) {
        expect.withMessage("canHaveProfile() on %s (%s)", description, user)
                .that(user.canHaveProfile()).isTrue();
    }

    private void expectCannotHaveProfile(String description, UserInfo user) {
        expect.withMessage("canHaveProfile() on %s (%s)", description, user)
                .that(user.canHaveProfile()).isFalse();
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -7724,6 +7724,7 @@ public class UserManagerService extends IUserManager.Stub {

        pw.print("    Has profile owner: ");
        pw.println(mIsUserManaged.get(userId));

        pw.println("    Restrictions:");
        synchronized (mRestrictionsLock) {
            UserRestrictionsUtils.dumpRestrictions(
@@ -7756,6 +7757,9 @@ public class UserManagerService extends IUserManager.Stub {
            }
        }

        pw.print("    Can have profile: ");
        pw.println(userInfo.canHaveProfile());

        if (userData.userProperties != null) {
            userData.userProperties.println(pw, "    ");
        }
+1 −1
Original line number Diff line number Diff line
@@ -274,7 +274,7 @@ public class UserManagerServiceUserInfoTest {
    /** Test UserInfo.canHaveProfile for main user */
    @Test
    public void testCanHaveProfile() throws Exception {
        UserInfo userInfo = createUser(100, FLAG_MAIN, null);
        UserInfo userInfo = createUser(100, FLAG_FULL | FLAG_MAIN, null);
        assertTrue("Main users can have profile", userInfo.canHaveProfile());
    }