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

Commit d7ff6fe9 authored by Manish Singh's avatar Manish Singh
Browse files

Support private profile in spinner adapters

Screenshot - https://screenshot.googleplex.com/35czwQHeevX75pj
Video - https://drive.google.com/file/d/1LkYPJ3i8llArnQBE3ieLPYMctEOw3xdp/view?usp=sharing&resourcekey=0-j-3-VV4OyXJKBPXwAqJvKg

Bug: 328565911
Bug: 313610609
Bug: 302082696
Test: manual
Test: atest UserAdapterTest
Test: atest StylusDevicesControllerTest
Change-Id: If8395eba5cc73809ab4abc95bc13067451c38b8f
parent 7dee0538
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1364,6 +1364,16 @@ public final class Utils extends com.android.settingslib.Utils {
        }
    }

    /**
     * Returns true if the user should be hidden in Settings when it's in quiet mode.
     */
    public static boolean shouldHideUser(
            @NonNull UserHandle userHandle, @NonNull UserManager userManager) {
        UserProperties userProperties = userManager.getUserProperties(userHandle);
        return userProperties.getShowInQuietMode() == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN
                && userManager.isQuietModeEnabled(userHandle);
    }

    private static FaceManager.RemovalCallback faceManagerRemovalCallback(int userId) {
        return new FaceManager.RemovalCallback() {
            @Override
+14 −13
Original line number Diff line number Diff line
@@ -214,7 +214,7 @@ public class StylusDevicesController extends AbstractPreferenceController implem
                Intent intent = new Intent(Intent.ACTION_MANAGE_DEFAULT_APP).setPackage(
                        packageName).putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_NOTES);

                List<UserHandle> users = getUserAndManagedProfiles();
                List<UserHandle> users = getUserProfiles();
                if (users.size() <= 1) {
                    mContext.startActivity(intent);
                } else {
@@ -311,22 +311,23 @@ public class StylusDevicesController extends AbstractPreferenceController implem
        return inputMethod != null && inputMethod.supportsStylusHandwriting();
    }

    private List<UserHandle> getUserAndManagedProfiles() {
    private List<UserHandle> getUserProfiles() {
        UserManager um = mContext.getSystemService(UserManager.class);
        final List<UserHandle> userManagedProfiles = new ArrayList<>();
        // Add the current user, then add all the associated managed profiles.
        final UserHandle currentUser = Process.myUserHandle();
        userManagedProfiles.add(currentUser);
        final List<UserHandle> userProfiles = new ArrayList<>();
        userProfiles.add(currentUser);

        final List<UserInfo> userInfos = um.getUsers();
        for (UserInfo info : userInfos) {
            int userId = info.id;
            if (um.isManagedProfile(userId)
                    && um.getProfileParent(userId).id == currentUser.getIdentifier()) {
                userManagedProfiles.add(UserHandle.of(userId));
        final List<UserInfo> userInfos = um.getProfiles(currentUser.getIdentifier());
        for (UserInfo userInfo : userInfos) {
            if (userInfo.isManagedProfile()
                    || (android.os.Flags.allowPrivateProfile()
                        && android.multiuser.Flags.enablePrivateSpaceFeatures()
                        && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
                        && userInfo.isPrivateProfile())) {
                userProfiles.add(userInfo.getUserHandle());
            }
        }
        return userManagedProfiles;
        return userProfiles;
    }

    private UserHandle getDefaultNoteTaskProfile() {
+3 −10
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.content.DialogInterface.OnDismissListener;
import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -42,6 +41,7 @@ import com.android.internal.widget.DialogTitle;
import com.android.internal.widget.LinearLayoutManager;
import com.android.internal.widget.RecyclerView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.drawer.Tile;

@@ -186,7 +186,7 @@ public class ProfileSelectDialog extends DialogFragment implements UserAdapter.O
            UserInfo userInfo = userManager.getUserInfo(userHandles.get(i).getIdentifier());
            if (userInfo == null
                    || userInfo.isCloneProfile()
                    || shouldHideUserInQuietMode(userHandles.get(i), userManager)) {
                    || Utils.shouldHideUser(userHandles.get(i), userManager)) {
                if (DEBUG) {
                    Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
                }
@@ -219,7 +219,7 @@ public class ProfileSelectDialog extends DialogFragment implements UserAdapter.O
            UserInfo userInfo = userManager.getUserInfo(userHandle.getIdentifier());
            if (userInfo == null
                    || userInfo.isCloneProfile()
                    || shouldHideUserInQuietMode(userHandle, userManager)) {
                    || Utils.shouldHideUser(userHandle, userManager)) {
                if (DEBUG) {
                    Log.d(TAG, "Delete the user: " + userHandle.getIdentifier());
                }
@@ -228,11 +228,4 @@ public class ProfileSelectDialog extends DialogFragment implements UserAdapter.O
            }
        }
    }

    private static boolean shouldHideUserInQuietMode(
            UserHandle userHandle, UserManager userManager) {
        UserProperties userProperties = userManager.getUserProperties(userHandle);
        return userProperties.getShowInQuietMode() == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN
                && userManager.isQuietModeEnabled(userHandle);
    }
}
+16 −1
Original line number Diff line number Diff line
@@ -64,7 +64,11 @@ public class UserAdapter extends BaseAdapter {
            UserInfo userInfo = um.getUserInfo(mUserHandle.getIdentifier());
            int tintColor = Utils.getColorAttrDefaultColor(context,
                    com.android.internal.R.attr.materialColorPrimary);
            if (userInfo.isManagedProfile()) {
            if (userInfo.isManagedProfile()
                    || (android.os.Flags.allowPrivateProfile()
                        && android.multiuser.Flags.enablePrivateSpaceFeatures()
                        && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
                        && userInfo.isPrivateProfile())) {
                mIcon = context.getPackageManager().getUserBadgeForDensityNoBackground(
                        userHandle, /* density= */ 0);
                mIcon.setTint(tintColor);
@@ -88,6 +92,7 @@ public class UserAdapter extends BaseAdapter {
                        () -> context.getString(com.android.settingslib.R.string.category_work));
            } else if (android.os.Flags.allowPrivateProfile()
                    && android.multiuser.Flags.enablePrivateSpaceFeatures()
                    && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
                    && mUserManager.getUserInfo(userId).isPrivateProfile()) {
                return resources.getString(PRIVATE_CATEGORY_HEADER,
                        () -> context.getString(com.android.settingslib.R.string.category_private));
@@ -209,6 +214,7 @@ public class UserAdapter extends BaseAdapter {

    private static UserAdapter createUserAdapter(
            UserManager userManager, Context context, List<UserHandle> userProfiles) {
        updateUserHandlesIfNeeded(userManager, userProfiles);
        ArrayList<UserDetails> userDetails = new ArrayList<>(userProfiles.size());
        for (UserHandle userProfile : userProfiles) {
            userDetails.add(new UserDetails(userProfile, userManager, context));
@@ -216,6 +222,15 @@ public class UserAdapter extends BaseAdapter {
        return new UserAdapter(context, userDetails);
    }

    private static void updateUserHandlesIfNeeded(
            UserManager userManager, List<UserHandle> userProfiles) {
        for (int i = userProfiles.size() - 1; i >= 0; --i) {
            if (com.android.settings.Utils.shouldHideUser(userProfiles.get(i), userManager)) {
                userProfiles.remove(i);
            }
        }
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        private final ImageView mIconView;
        private final TextView mTitleView;
+86 −9
Original line number Diff line number Diff line
@@ -41,9 +41,12 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.graphics.drawable.Drawable;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.view.InputDevice;
@@ -64,6 +67,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.Lifecycle;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -77,8 +81,12 @@ import java.util.List;

@RunWith(RobolectricTestRunner.class)
public class StylusDevicesControllerTest {
    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    private static final String NOTES_PACKAGE_NAME = "notes.package";
    private static final CharSequence NOTES_APP_LABEL = "App Label";
    private static final int WORK_USER_ID = 1;
    private static final int PRIVATE_USER_ID = 2;

    private Context mContext;
    private StylusDevicesController mController;
@@ -95,6 +103,12 @@ public class StylusDevicesControllerTest {
    @Mock
    private UserManager mUserManager;
    @Mock
    UserInfo mPersonalUserInfo;
    @Mock
    UserInfo mWorkUserInfo;
    @Mock
    UserInfo mPrivateUserInfo;
    @Mock
    private RoleManager mRm;
    @Mock
    private Lifecycle mLifecycle;
@@ -102,6 +116,8 @@ public class StylusDevicesControllerTest {
    private CachedBluetoothDevice mCachedBluetoothDevice;
    @Mock
    private BluetoothDevice mBluetoothDevice;
    @Mock
    private Drawable mIcon;

    @Before
    public void setUp() throws Exception {
@@ -134,6 +150,7 @@ public class StylusDevicesControllerTest {
        when(mPm.getApplicationInfo(eq(NOTES_PACKAGE_NAME),
                any(PackageManager.ApplicationInfoFlags.class))).thenReturn(new ApplicationInfo());
        when(mPm.getApplicationLabel(any(ApplicationInfo.class))).thenReturn(NOTES_APP_LABEL);
        when(mPm.getUserBadgeForDensityNoBackground(any(), anyInt())).thenReturn(mIcon);
        when(mUserManager.getUsers()).thenReturn(Arrays.asList(new UserInfo(0, "default", 0)));
        when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);

@@ -371,14 +388,74 @@ public class StylusDevicesControllerTest {
        final String permissionPackageName = "permissions.package";
        final UserHandle currentUser = Process.myUserHandle();
        List<UserInfo> userInfos = Arrays.asList(
                new UserInfo(currentUser.getIdentifier(), "current", 0),
                new UserInfo(1, "profile", UserInfo.FLAG_PROFILE)
                mPersonalUserInfo,
                mWorkUserInfo
        );
        when(mUserManager.getUsers()).thenReturn(userInfos);
        when(mUserManager.isManagedProfile(1)).thenReturn(true);
        when(mUserManager.getUserInfo(currentUser.getIdentifier())).thenReturn(userInfos.get(0));
        when(mUserManager.getUserInfo(1)).thenReturn(userInfos.get(1));
        when(mUserManager.getProfileParent(1)).thenReturn(userInfos.get(0));
        UserProperties personalUserProperties =
                new UserProperties.Builder()
                        .setShowInQuietMode(UserProperties.SHOW_IN_QUIET_MODE_DEFAULT)
                        .build();
        UserProperties workUserProperties =
                new UserProperties.Builder()
                        .setShowInQuietMode(UserProperties.SHOW_IN_QUIET_MODE_PAUSED)
                        .build();
        when(mWorkUserInfo.isManagedProfile()).thenReturn(true);
        when(mWorkUserInfo.getUserHandle()).thenReturn(UserHandle.of(WORK_USER_ID));
        when(mUserManager.getProfiles(currentUser.getIdentifier())).thenReturn(userInfos);
        when(mUserManager.getUserInfo(currentUser.getIdentifier())).thenReturn(mPersonalUserInfo);
        when(mUserManager.getUserInfo(WORK_USER_ID)).thenReturn(mWorkUserInfo);
        when(mUserManager.getProfileParent(WORK_USER_ID)).thenReturn(mPersonalUserInfo);
        when(mUserManager.getUserProperties(currentUser)).thenReturn(personalUserProperties);
        when(mUserManager.getUserProperties(UserHandle.of(WORK_USER_ID)))
                .thenReturn(workUserProperties);
        when(mPm.getPermissionControllerPackageName()).thenReturn(permissionPackageName);

        showScreen(mController);
        Preference defaultNotesPref = mPreferenceContainer.getPreference(0);
        mController.onPreferenceClick(defaultNotesPref);

        assertTrue(mController.mDialog.isShowing());
    }

    @Test
    public void defaultNotesPreferenceClick_multiUsers_showsProfileSelectorDialog() {
        mSetFlagsRule.enableFlags(
                android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES,
                android.multiuser.Flags.FLAG_HANDLE_INTERLEAVED_SETTINGS_FOR_PRIVATE_SPACE);
        mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
        final String permissionPackageName = "permissions.package";
        final UserHandle currentUser = Process.myUserHandle();
        List<UserInfo> userInfos = Arrays.asList(
                mPersonalUserInfo,
                mPrivateUserInfo,
                mWorkUserInfo
        );
        UserProperties personalUserProperties =
                new UserProperties.Builder()
                        .setShowInQuietMode(UserProperties.SHOW_IN_QUIET_MODE_DEFAULT)
                        .build();
        UserProperties workUserProperties =
                new UserProperties.Builder()
                        .setShowInQuietMode(UserProperties.SHOW_IN_QUIET_MODE_PAUSED)
                        .build();
        UserProperties privateUserProperties =
                new UserProperties.Builder()
                        .setShowInQuietMode(UserProperties.SHOW_IN_QUIET_MODE_HIDDEN)
                        .build();
        when(mWorkUserInfo.isManagedProfile()).thenReturn(true);
        when(mWorkUserInfo.getUserHandle()).thenReturn(UserHandle.of(WORK_USER_ID));
        when(mPrivateUserInfo.isPrivateProfile()).thenReturn(true);
        when(mPrivateUserInfo.getUserHandle()).thenReturn(UserHandle.of(PRIVATE_USER_ID));
        when(mUserManager.getProfiles(currentUser.getIdentifier())).thenReturn(userInfos);
        when(mUserManager.getUserInfo(currentUser.getIdentifier())).thenReturn(mPersonalUserInfo);
        when(mUserManager.getUserInfo(WORK_USER_ID)).thenReturn(mWorkUserInfo);
        when(mUserManager.getUserInfo(PRIVATE_USER_ID)).thenReturn(mPrivateUserInfo);
        when(mUserManager.getUserProperties(currentUser)).thenReturn(personalUserProperties);
        when(mUserManager.getUserProperties(UserHandle.of(PRIVATE_USER_ID)))
                .thenReturn(privateUserProperties);
        when(mUserManager.getUserProperties(UserHandle.of(WORK_USER_ID)))
                .thenReturn(workUserProperties);
        when(mPm.getPermissionControllerPackageName()).thenReturn(permissionPackageName);

        showScreen(mController);
@@ -389,7 +466,7 @@ public class StylusDevicesControllerTest {
    }

    @Test
    public void defaultNotesPreferenceClick_noManagedProfile_sendsManageDefaultRoleIntent() {
    public void defaultNotesPreferenceClick_noProfiles_sendsManageDefaultRoleIntent() {
        final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
        final String permissionPackageName = "permissions.package";
@@ -398,7 +475,7 @@ public class StylusDevicesControllerTest {
                new UserInfo(currentUser.getIdentifier(), "current", 0),
                new UserInfo(1, "other", UserInfo.FLAG_FULL)
        );
        when(mUserManager.getUsers()).thenReturn(userInfos);
        when(mUserManager.getProfiles(currentUser.getIdentifier())).thenReturn(userInfos);
        when(mUserManager.isManagedProfile(1)).thenReturn(false);
        when(mUserManager.getUserInfo(currentUser.getIdentifier())).thenReturn(userInfos.get(0));
        when(mUserManager.getUserInfo(1)).thenReturn(userInfos.get(1));
Loading