diff options
| author | 2023-11-23 15:53:20 +0000 | |
|---|---|---|
| committer | 2023-11-23 15:53:20 +0000 | |
| commit | dd99c7647fd0495d7d78f6eee9047d1d8d7bb3d3 (patch) | |
| tree | a091796e1f15af25d41b5f28b92b0f7795724b16 | |
| parent | a2303b4dd6845670c459b14ffa7bd2601938782d (diff) | |
| parent | 68b05f700ef3487eb683a6c560bc56c2f57d9b27 (diff) | |
Merge "Add more user properties & details to the profile creation" into main
13 files changed, 333 insertions, 78 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 01ca6d924605..ce5752fdbd8b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -4211,10 +4211,18 @@ package android.content.pm { public final class UserProperties implements android.os.Parcelable { method public int describeContents(); + method public int getShowInQuietMode(); + method public int getShowInSharingSurfaces(); method public boolean isCredentialShareableWithParent(); method public boolean isMediaSharedWithParent(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.UserProperties> CREATOR; + field public static final int SHOW_IN_QUIET_MODE_DEFAULT = 2; // 0x2 + field public static final int SHOW_IN_QUIET_MODE_HIDDEN = 1; // 0x1 + field public static final int SHOW_IN_QUIET_MODE_PAUSED = 0; // 0x0 + field public static final int SHOW_IN_SHARING_SURFACES_NO = 2; // 0x2 + field public static final int SHOW_IN_SHARING_SURFACES_SEPARATE = 1; // 0x1 + field public static final int SHOW_IN_SHARING_SURFACES_WITH_PARENT = 0; // 0x0 } } @@ -10560,6 +10568,7 @@ package android.os { method @NonNull public java.util.List<android.os.UserHandle> getEnabledProfiles(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public android.os.UserHandle getMainUser(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public android.os.UserHandle getPreviousForegroundUser(); + method @NonNull public String getProfileLabel(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public int getRemainingCreatableProfileCount(@NonNull String); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public int getRemainingCreatableUserCount(@NonNull String); diff --git a/core/java/android/content/pm/UserProperties.java b/core/java/android/content/pm/UserProperties.java index f532c4cffcc4..445ca0c98416 100644 --- a/core/java/android/content/pm/UserProperties.java +++ b/core/java/android/content/pm/UserProperties.java @@ -19,6 +19,7 @@ package android.content.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -49,7 +50,8 @@ public final class UserProperties implements Parcelable { private static final String ATTR_SHOW_IN_LAUNCHER = "showInLauncher"; private static final String ATTR_START_WITH_PARENT = "startWithParent"; private static final String ATTR_SHOW_IN_SETTINGS = "showInSettings"; - private static final String ATTR_HIDE_IN_SETTINGS_IN_QUIET_MODE = "hideInSettingsInQuietMode"; + private static final String ATTR_SHOW_IN_QUIET_MODE = "showInQuietMode"; + private static final String ATTR_SHOW_IN_SHARING_SURFACES = "showInSharingSurfaces"; private static final String ATTR_INHERIT_DEVICE_POLICY = "inheritDevicePolicy"; private static final String ATTR_USE_PARENTS_CONTACTS = "useParentsContacts"; private static final String ATTR_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA = @@ -81,7 +83,8 @@ public final class UserProperties implements Parcelable { INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT, INDEX_DELETE_APP_WITH_PARENT, INDEX_ALWAYS_VISIBLE, - INDEX_HIDE_IN_SETTINGS_IN_QUIET_MODE, + INDEX_SHOW_IN_QUIET_MODE, + INDEX_SHOW_IN_SHARING_SURFACES, INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE, }) @Retention(RetentionPolicy.SOURCE) @@ -99,8 +102,9 @@ public final class UserProperties implements Parcelable { private static final int INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT = 9; private static final int INDEX_DELETE_APP_WITH_PARENT = 10; private static final int INDEX_ALWAYS_VISIBLE = 11; - private static final int INDEX_HIDE_IN_SETTINGS_IN_QUIET_MODE = 12; + private static final int INDEX_SHOW_IN_QUIET_MODE = 12; private static final int INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE = 13; + private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; @@ -286,6 +290,81 @@ public final class UserProperties implements Parcelable { */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING = 1; + /** + * Possible values for the profile visibility when in quiet mode. This affects the profile data + * and apps surfacing in Settings, sharing surfaces, and file picker surfaces. It signifies + * whether the profile data and apps will be shown or not. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "SHOW_IN_QUIET_MODE_", + value = { + SHOW_IN_QUIET_MODE_PAUSED, + SHOW_IN_QUIET_MODE_HIDDEN, + SHOW_IN_QUIET_MODE_DEFAULT, + } + ) + public @interface ShowInQuietMode { + } + + /** + * Indicates that the profile should still be visible in quiet mode but should be shown as + * paused (e.g. by greying out its icons). + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int SHOW_IN_QUIET_MODE_PAUSED = 0; + /** + * Indicates that the profile should not be visible when the profile is in quiet mode. + * For example, the profile should not be shown in tabbed views in Settings, files sharing + * surfaces etc when in quiet mode. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int SHOW_IN_QUIET_MODE_HIDDEN = 1; + /** + * Indicates that quiet mode should not have any effect on the profile visibility. If the + * profile is meant to be visible, it will remain visible and vice versa. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int SHOW_IN_QUIET_MODE_DEFAULT = 2; + + /** + * Possible values for the profile apps visibility in sharing surfaces. This indicates the + * profile data and apps should be shown in separate tabs or mixed with its parent user's data + * and apps in sharing surfaces and file picker surfaces. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "SHOW_IN_SHARING_SURFACES_", + value = { + SHOW_IN_SHARING_SURFACES_SEPARATE, + SHOW_IN_SHARING_SURFACES_WITH_PARENT, + SHOW_IN_SHARING_SURFACES_NO, + } + ) + public @interface ShowInSharingSurfaces { + } + + /** + * Indicates that the profile data and apps should be shown in sharing surfaces intermixed with + * parent user's data and apps. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int SHOW_IN_SHARING_SURFACES_WITH_PARENT = SHOW_IN_LAUNCHER_WITH_PARENT; + + /** + * Indicates that the profile data and apps should be shown in sharing surfaces separate from + * parent user's data and apps. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int SHOW_IN_SHARING_SURFACES_SEPARATE = SHOW_IN_LAUNCHER_SEPARATE; + + /** + * Indicates that the profile data and apps should not be shown in sharing surfaces at all. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int SHOW_IN_SHARING_SURFACES_NO = SHOW_IN_LAUNCHER_NO; /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given @@ -331,7 +410,6 @@ public final class UserProperties implements Parcelable { if (hasManagePermission) { // Add items that require MANAGE_USERS or stronger. setShowInSettings(orig.getShowInSettings()); - setHideInSettingsInQuietMode(orig.getHideInSettingsInQuietMode()); setUseParentsContacts(orig.getUseParentsContacts()); setAuthAlwaysRequiredToDisableQuietMode( orig.isAuthAlwaysRequiredToDisableQuietMode()); @@ -343,6 +421,8 @@ public final class UserProperties implements Parcelable { setShowInLauncher(orig.getShowInLauncher()); setMediaSharedWithParent(orig.isMediaSharedWithParent()); setCredentialShareableWithParent(orig.isCredentialShareableWithParent()); + setShowInQuietMode(orig.getShowInQuietMode()); + setShowInSharingSurfaces(orig.getShowInSharingSurfaces()); } /** @@ -419,40 +499,59 @@ public final class UserProperties implements Parcelable { private @ShowInSettings int mShowInSettings; /** - * Returns whether a user should be shown in the Settings app depending on the quiet mode. - * This is generally inapplicable for non-profile users. - * - * <p> {@link #getShowInSettings()} returns whether / how a user should be shown in Settings. - * However, if this behaviour should be changed based on the quiet mode of the user, then this - * property can be used. If the property is not set then the user is shown in the Settings app - * irrespective of whether the user is in quiet mode or not. If the property is set, then the - * user is shown in the Settings app only if the user is not in the quiet mode. Please note that - * this property takes effect only if {@link #getShowInSettings()} does not return - * {@link #SHOW_IN_SETTINGS_NO}. - * - * <p> The caller must have {@link android.Manifest.permission#MANAGE_USERS} to query this - * property. + * Returns whether a user should be shown in the Settings and sharing surfaces depending on the + * {@link android.os.UserManager#requestQuietModeEnabled(boolean, android.os.UserHandle) + * quiet mode}. This is only applicable to profile users since the quiet mode concept is only + * applicable to profile users. * - * @return true if a profile should be shown in the Settings only when the user is not in the - * quiet mode. + * <p> Please note that, in Settings, this property takes effect only if + * {@link #getShowInSettings()} does not return {@link #SHOW_IN_SETTINGS_NO}. + * Also note that in Sharing surfaces this property takes effect only if + * {@link #getShowInSharingSurfaces()} does not return {@link #SHOW_IN_SHARING_SURFACES_NO}. * - * See also {@link #getShowInSettings()}, {@link #setShowInSettings(int)}, - * {@link ShowInSettings} + * @return One of {@link #SHOW_IN_QUIET_MODE_HIDDEN}, + * {@link #SHOW_IN_QUIET_MODE_PAUSED}, or + * {@link #SHOW_IN_QUIET_MODE_DEFAULT} depending on whether the profile should be + * shown in quiet mode or not. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public @ShowInQuietMode int getShowInQuietMode() { + // NOTE: Launcher currently does not make use of this property. + if (isPresent(INDEX_SHOW_IN_QUIET_MODE)) return mShowInQuietMode; + if (mDefaultProperties != null) return mDefaultProperties.mShowInQuietMode; + throw new SecurityException( + "You don't have permission to query ShowInQuietMode"); + } + /** @hide */ + public void setShowInQuietMode(@ShowInQuietMode int showInQuietMode) { + this.mShowInQuietMode = showInQuietMode; + setPresent(INDEX_SHOW_IN_QUIET_MODE); + } + private int mShowInQuietMode; + + /** + * Returns whether a user's data and apps should be shown in sharing surfaces in a separate tab + * or mixed with the parent user's data/apps. This is only applicable to profile users. * - * @hide + * @return One of {@link #SHOW_IN_SHARING_SURFACES_NO}, + * {@link #SHOW_IN_SHARING_SURFACES_SEPARATE}, or + * {@link #SHOW_IN_SHARING_SURFACES_WITH_PARENT} depending on whether the profile + * should be shown separate from its parent's data, mixed with the parent's data, or + * not shown at all. */ - public boolean getHideInSettingsInQuietMode() { - if (isPresent(INDEX_HIDE_IN_SETTINGS_IN_QUIET_MODE)) return mHideInSettingsInQuietMode; - if (mDefaultProperties != null) return mDefaultProperties.mHideInSettingsInQuietMode; + @SuppressLint("UnflaggedApi") // b/306636213 + public @ShowInSharingSurfaces int getShowInSharingSurfaces() { + if (isPresent(INDEX_SHOW_IN_SHARING_SURFACES)) return mShowInSharingSurfaces; + if (mDefaultProperties != null) return mDefaultProperties.mShowInSharingSurfaces; throw new SecurityException( - "You don't have permission to query HideInSettingsInQuietMode"); + "You don't have permission to query ShowInSharingSurfaces"); } /** @hide */ - public void setHideInSettingsInQuietMode(boolean hideInSettingsInQuietMode) { - this.mHideInSettingsInQuietMode = hideInSettingsInQuietMode; - setPresent(INDEX_HIDE_IN_SETTINGS_IN_QUIET_MODE); + public void setShowInSharingSurfaces(@ShowInSharingSurfaces int showInSharingSurfaces) { + this.mShowInSharingSurfaces = showInSharingSurfaces; + setPresent(INDEX_SHOW_IN_SHARING_SURFACES); } - private boolean mHideInSettingsInQuietMode; + private int mShowInSharingSurfaces; /** * Returns whether a profile should be started when its parent starts (unless in quiet mode). @@ -799,8 +898,11 @@ public final class UserProperties implements Parcelable { case ATTR_SHOW_IN_SETTINGS: setShowInSettings(parser.getAttributeInt(i)); break; - case ATTR_HIDE_IN_SETTINGS_IN_QUIET_MODE: - setHideInSettingsInQuietMode(parser.getAttributeBoolean(i)); + case ATTR_SHOW_IN_QUIET_MODE: + setShowInQuietMode(parser.getAttributeInt(i)); + break; + case ATTR_SHOW_IN_SHARING_SURFACES: + setShowInSharingSurfaces(parser.getAttributeInt(i)); break; case ATTR_INHERIT_DEVICE_POLICY: setInheritDevicePolicy(parser.getAttributeInt(i)); @@ -858,9 +960,12 @@ public final class UserProperties implements Parcelable { if (isPresent(INDEX_SHOW_IN_SETTINGS)) { serializer.attributeInt(null, ATTR_SHOW_IN_SETTINGS, mShowInSettings); } - if (isPresent(INDEX_HIDE_IN_SETTINGS_IN_QUIET_MODE)) { - serializer.attributeBoolean(null, ATTR_HIDE_IN_SETTINGS_IN_QUIET_MODE, - mHideInSettingsInQuietMode); + if (isPresent(INDEX_SHOW_IN_QUIET_MODE)) { + serializer.attributeInt(null, ATTR_SHOW_IN_QUIET_MODE, + mShowInQuietMode); + } + if (isPresent(INDEX_SHOW_IN_SHARING_SURFACES)) { + serializer.attributeInt(null, ATTR_SHOW_IN_SHARING_SURFACES, mShowInSharingSurfaces); } if (isPresent(INDEX_INHERIT_DEVICE_POLICY)) { serializer.attributeInt(null, ATTR_INHERIT_DEVICE_POLICY, @@ -912,7 +1017,8 @@ public final class UserProperties implements Parcelable { dest.writeInt(mShowInLauncher); dest.writeBoolean(mStartWithParent); dest.writeInt(mShowInSettings); - dest.writeBoolean(mHideInSettingsInQuietMode); + dest.writeInt(mShowInQuietMode); + dest.writeInt(mShowInSharingSurfaces); dest.writeInt(mInheritDevicePolicy); dest.writeBoolean(mUseParentsContacts); dest.writeBoolean(mUpdateCrossProfileIntentFiltersOnOTA); @@ -936,7 +1042,8 @@ public final class UserProperties implements Parcelable { mShowInLauncher = source.readInt(); mStartWithParent = source.readBoolean(); mShowInSettings = source.readInt(); - mHideInSettingsInQuietMode = source.readBoolean(); + mShowInQuietMode = source.readInt(); + mShowInSharingSurfaces = source.readInt(); mInheritDevicePolicy = source.readInt(); mUseParentsContacts = source.readBoolean(); mUpdateCrossProfileIntentFiltersOnOTA = source.readBoolean(); @@ -974,7 +1081,10 @@ public final class UserProperties implements Parcelable { private @ShowInLauncher int mShowInLauncher = SHOW_IN_LAUNCHER_WITH_PARENT; private boolean mStartWithParent = false; private @ShowInSettings int mShowInSettings = SHOW_IN_SETTINGS_WITH_PARENT; - private boolean mHideInSettingsInQuietMode = false; + private @ShowInQuietMode int mShowInQuietMode = + SHOW_IN_QUIET_MODE_PAUSED; + private @ShowInSharingSurfaces int mShowInSharingSurfaces = + SHOW_IN_SHARING_SURFACES_SEPARATE; private @InheritDevicePolicy int mInheritDevicePolicy = INHERIT_DEVICE_POLICY_NO; private boolean mUseParentsContacts = false; private boolean mUpdateCrossProfileIntentFiltersOnOTA = false; @@ -1005,9 +1115,15 @@ public final class UserProperties implements Parcelable { return this; } - /** Sets the value for {@link #mHideInSettingsInQuietMode} */ - public Builder setHideInSettingsInQuietMode(boolean hideInSettingsInQuietMode) { - mHideInSettingsInQuietMode = hideInSettingsInQuietMode; + /** Sets the value for {@link #mShowInQuietMode} */ + public Builder setShowInQuietMode(@ShowInQuietMode int showInQuietMode) { + mShowInQuietMode = showInQuietMode; + return this; + } + + /** Sets the value for {@link #mShowInSharingSurfaces}. */ + public Builder setShowInSharingSurfaces(@ShowInSharingSurfaces int showInSharingSurfaces) { + mShowInSharingSurfaces = showInSharingSurfaces; return this; } @@ -1081,7 +1197,8 @@ public final class UserProperties implements Parcelable { mShowInLauncher, mStartWithParent, mShowInSettings, - mHideInSettingsInQuietMode, + mShowInQuietMode, + mShowInSharingSurfaces, mInheritDevicePolicy, mUseParentsContacts, mUpdateCrossProfileIntentFiltersOnOTA, @@ -1100,7 +1217,8 @@ public final class UserProperties implements Parcelable { @ShowInLauncher int showInLauncher, boolean startWithParent, @ShowInSettings int showInSettings, - boolean hideInSettingsInQuietMode, + @ShowInQuietMode int showInQuietMode, + @ShowInSharingSurfaces int showInSharingSurfaces, @InheritDevicePolicy int inheritDevicePolicy, boolean useParentsContacts, boolean updateCrossProfileIntentFiltersOnOTA, @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl, @@ -1114,7 +1232,8 @@ public final class UserProperties implements Parcelable { setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); setShowInSettings(showInSettings); - setHideInSettingsInQuietMode(hideInSettingsInQuietMode); + setShowInQuietMode(showInQuietMode); + setShowInSharingSurfaces(showInSharingSurfaces); setInheritDevicePolicy(inheritDevicePolicy); setUseParentsContacts(useParentsContacts); setUpdateCrossProfileIntentFiltersOnOTA(updateCrossProfileIntentFiltersOnOTA); diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 330b992ef308..c0d1fb9c6a88 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -131,6 +131,7 @@ interface IUserManager { int getUserBadgeDarkColorResId(int userId); int getUserStatusBarIconResId(int userId); boolean hasBadge(int userId); + int getProfileLabelResId(int userId); boolean isUserUnlocked(int userId); boolean isUserRunning(int userId); boolean isUserForeground(int userId); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 08d6e028f08c..ec6d20fbc0f5 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -5693,6 +5693,44 @@ public class UserManager { } /** + * Returns the string/label that should be used to represent the context user. For example, + * this string can represent a profile in tabbed views. This is only applicable to + * {@link #isProfile() profile users}. This string is translated to the device default language. + * + * @return String representing the label for the context user. + * + * @throws android.content.res.Resources.NotFoundException if the user does not have a label + * defined. + * + * @hide + */ + @SystemApi + @SuppressLint("UnflaggedApi") // b/306636213 + @UserHandleAware( + requiresAnyOfPermissionsIfNotCallerProfileGroup = { + Manifest.permission.MANAGE_USERS, + Manifest.permission.QUERY_USERS, + Manifest.permission.INTERACT_ACROSS_USERS}) + public @NonNull String getProfileLabel() { + if (isManagedProfile(mUserId)) { + DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); + return dpm.getResources().getString( + android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_WORK_TAB, + () -> getDefaultProfileLabel(mUserId)); + } + return getDefaultProfileLabel(mUserId); + } + + private String getDefaultProfileLabel(int userId) { + try { + final int resourceId = mService.getProfileLabelResId(userId); + return Resources.getSystem().getString(resourceId); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * If the user is a {@link UserManager#isProfile profile}, checks if the user * shares media with its parent user (the user that created this profile). * Returns false for any other type of user. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index eed186ad3702..73a7e4296a57 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -6350,4 +6350,20 @@ ul.</string> <string name="keyboard_layout_notification_multiple_selected_title">Physical keyboards configured</string> <!-- Notification message when multiple keyboards with selected layouts have been connected the first time simultaneously [CHAR LIMIT=NOTIF_BODY] --> <string name="keyboard_layout_notification_multiple_selected_message">Tap to view keyboards</string> + + <!-- Private profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_private">Private</string> + <!-- Clone profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_clone">Clone</string> + <!-- Work profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_work">Work</string> + <!-- 2nd Work profile label on a screen in case a device has more than one work profiles. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_work_2">Work 2</string> + <!-- 3rd Work profile label on a screen in case a device has more than two work profiles. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_work_3">Work 3</string> + <!-- Test profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_test">Test</string> + <!-- Communal profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] --> + <string name="profile_label_communal">Communal</string> + </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 24b39bc1225e..38f1f6756d17 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1086,6 +1086,13 @@ <java-symbol type="string" name="managed_profile_label_badge_3" /> <java-symbol type="string" name="clone_profile_label_badge" /> <java-symbol type="string" name="private_profile_label_badge" /> + <java-symbol type="string" name="profile_label_private" /> + <java-symbol type="string" name="profile_label_clone" /> + <java-symbol type="string" name="profile_label_work" /> + <java-symbol type="string" name="profile_label_work_2" /> + <java-symbol type="string" name="profile_label_work_3" /> + <java-symbol type="string" name="profile_label_test" /> + <java-symbol type="string" name="profile_label_communal" /> <java-symbol type="string" name="mediasize_unknown_portrait" /> <java-symbol type="string" name="mediasize_unknown_landscape" /> <java-symbol type="string" name="mediasize_iso_a0" /> diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/UserProfilePager.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/UserProfilePager.kt index 223e99e61204..56796945f015 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/UserProfilePager.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/common/UserProfilePager.kt @@ -72,7 +72,8 @@ private fun UserManager.getUserGroups(): List<UserGroup> { private fun UserManager.showInSettings(userInfo: UserInfo): Int { val userProperties = getUserProperties(userInfo.userHandle) - return if (userInfo.isQuietModeEnabled && userProperties.hideInSettingsInQuietMode) { + return if (userInfo.isQuietModeEnabled && userProperties.showInQuietMode + == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) { UserProperties.SHOW_IN_SETTINGS_NO } else { userProperties.showInSettings diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 85563172cf05..f90bf4b47644 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1957,6 +1957,19 @@ public class UserManagerService extends IUserManager.Stub { return userTypeDetails.getStatusBarIcon(); } + @Override + public @StringRes int getProfileLabelResId(@UserIdInt int userId) { + checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId, + "getProfileLabelResId"); + final UserInfo userInfo = getUserInfoNoChecks(userId); + final UserTypeDetails userTypeDetails = getUserTypeDetails(userInfo); + if (userInfo == null || userTypeDetails == null) { + return Resources.ID_NULL; + } + final int userIndex = userInfo.profileBadge; + return userTypeDetails.getLabel(userIndex); + } + public boolean isProfile(@UserIdInt int userId) { checkQueryOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isProfile"); return isProfileUnchecked(userId); diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java index 7bdcd685a2e9..56c400a0caf8 100644 --- a/services/core/java/com/android/server/pm/UserTypeDetails.java +++ b/services/core/java/com/android/server/pm/UserTypeDetails.java @@ -54,8 +54,15 @@ public final class UserTypeDetails { /** Whether users of this type can be created. */ private final boolean mEnabled; - // TODO(b/142482943): Currently unused and not set. Hook this up. - private final int mLabel; + /** + * Resource IDs ({@link StringRes}) of the user's labels. This might be used to label a + * user/profile in tabbed views, etc. + * The values are resource IDs referring to the strings not the strings themselves. + * + * <p>This is an array because, in general, there may be multiple users of the same user type. + * In this case, the user is indexed according to its {@link UserInfo#profileBadge}. + */ + private final @Nullable int[] mLabels; /** * Maximum number of this user type allowed on the device. @@ -160,8 +167,8 @@ public final class UserTypeDetails { private final @NonNull UserProperties mDefaultUserProperties; private UserTypeDetails(@NonNull String name, boolean enabled, int maxAllowed, - @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, int label, - int maxAllowedPerParent, + @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, + @Nullable int[] labels, int maxAllowedPerParent, int iconBadge, int badgePlain, int badgeNoBackground, int statusBarIcon, @Nullable int[] badgeLabels, @Nullable int[] badgeColors, @@ -181,12 +188,11 @@ public final class UserTypeDetails { this.mDefaultSystemSettings = defaultSystemSettings; this.mDefaultSecureSettings = defaultSecureSettings; this.mDefaultCrossProfileIntentFilters = defaultCrossProfileIntentFilters; - this.mIconBadge = iconBadge; this.mBadgePlain = badgePlain; this.mBadgeNoBackground = badgeNoBackground; this.mStatusBarIcon = statusBarIcon; - this.mLabel = label; + this.mLabels = labels; this.mBadgeLabels = badgeLabels; this.mBadgeColors = badgeColors; this.mDarkThemeBadgeColors = darkThemeBadgeColors; @@ -234,9 +240,16 @@ public final class UserTypeDetails { return mDefaultUserInfoPropertyFlags | mBaseType; } - // TODO(b/142482943) Hook this up; it is currently unused. - public int getLabel() { - return mLabel; + /** + * Returns the resource ID corresponding to the badgeIndexth label name where the badgeIndex is + * expected to be the {@link UserInfo#profileBadge} of the user. If badgeIndex exceeds the + * number of labels, returns the label for the highest index. + */ + public @StringRes int getLabel(int badgeIndex) { + if (mLabels == null || mLabels.length == 0 || badgeIndex < 0) { + return Resources.ID_NULL; + } + return mLabels[Math.min(badgeIndex, mLabels.length - 1)]; } /** Returns whether users of this user type should be badged. */ @@ -358,7 +371,6 @@ public final class UserTypeDetails { pw.print(prefix); pw.print("mMaxAllowedPerParent: "); pw.println(mMaxAllowedPerParent); pw.print(prefix); pw.print("mDefaultUserInfoFlags: "); pw.println(UserInfo.flagsToString(mDefaultUserInfoPropertyFlags)); - pw.print(prefix); pw.print("mLabel: "); pw.println(mLabel); mDefaultUserProperties.println(pw, prefix); final String restrictionsPrefix = prefix + " "; @@ -392,6 +404,8 @@ public final class UserTypeDetails { pw.println(mBadgeColors != null ? mBadgeColors.length : "0(null)"); pw.print(prefix); pw.print("mDarkThemeBadgeColors.length: "); pw.println(mDarkThemeBadgeColors != null ? mDarkThemeBadgeColors.length : "0(null)"); + pw.print(prefix); pw.print("mLabels.length: "); + pw.println(mLabels != null ? mLabels.length : "0(null)"); } /** Builder for a {@link UserTypeDetails}; see that class for documentation. */ @@ -408,7 +422,7 @@ public final class UserTypeDetails { private @Nullable List<DefaultCrossProfileIntentFilter> mDefaultCrossProfileIntentFilters = null; private int mEnabled = 1; - private int mLabel = Resources.ID_NULL; + private @Nullable int[] mLabels = null; private @Nullable int[] mBadgeLabels = null; private @Nullable int[] mBadgeColors = null; private @Nullable int[] mDarkThemeBadgeColors = null; @@ -488,8 +502,8 @@ public final class UserTypeDetails { return this; } - public Builder setLabel(int label) { - mLabel = label; + public Builder setLabels(@StringRes int ... labels) { + mLabels = labels; return this; } @@ -562,7 +576,7 @@ public final class UserTypeDetails { mMaxAllowed, mBaseType, mDefaultUserInfoPropertyFlags, - mLabel, + mLabels, mMaxAllowedPerParent, mIconBadge, mBadgePlain, diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 7da76c18216e..4ef8cb780734 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -128,7 +128,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_CLONE) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(1) - .setLabel(0) + .setLabels(R.string.profile_label_clone) .setIconBadge(com.android.internal.R.drawable.ic_clone_icon_badge) .setBadgePlain(com.android.internal.R.drawable.ic_clone_badge) // Clone doesn't use BadgeNoBackground, so just set to BadgePlain as a placeholder. @@ -154,6 +154,10 @@ public final class UserTypeFactory { UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setCrossProfileIntentResolutionStrategy(UserProperties .CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING) + .setShowInQuietMode( + UserProperties.SHOW_IN_QUIET_MODE_DEFAULT) + .setShowInSharingSurfaces( + UserProperties.SHOW_IN_SHARING_SURFACES_WITH_PARENT) .setMediaSharedWithParent(true) .setCredentialShareableWithParent(true) .setDeleteAppWithParent(true)); @@ -169,7 +173,10 @@ public final class UserTypeFactory { .setBaseType(FLAG_PROFILE) .setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE) .setMaxAllowedPerParent(1) - .setLabel(0) + .setLabels( + R.string.profile_label_work, + R.string.profile_label_work_2, + R.string.profile_label_work_3) .setIconBadge(com.android.internal.R.drawable.ic_corp_icon_badge_case) .setBadgePlain(com.android.internal.R.drawable.ic_corp_badge_case) .setBadgeNoBackground(com.android.internal.R.drawable.ic_corp_badge_no_background) @@ -193,6 +200,10 @@ public final class UserTypeFactory { .setStartWithParent(true) .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE) + .setShowInQuietMode( + UserProperties.SHOW_IN_QUIET_MODE_PAUSED) + .setShowInSharingSurfaces( + UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setAuthAlwaysRequiredToDisableQuietMode(false) .setCredentialShareableWithParent(true)); } @@ -209,7 +220,10 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_TEST) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(2) - .setLabel(0) + .setLabels( + R.string.profile_label_test, + R.string.profile_label_test, + R.string.profile_label_test) .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment) .setBadgePlain(com.android.internal.R.drawable.ic_test_badge_experiment) .setBadgeNoBackground(com.android.internal.R.drawable.ic_test_badge_no_background) @@ -240,7 +254,7 @@ public final class UserTypeFactory { .setBaseType(FLAG_PROFILE) .setMaxAllowed(1) .setEnabled(UserManager.isCommunalProfileEnabled() ? 1 : 0) - .setLabel(0) + .setLabels(R.string.profile_label_communal) .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment) .setBadgePlain(com.android.internal.R.drawable.ic_test_badge_experiment) .setBadgeNoBackground(com.android.internal.R.drawable.ic_test_badge_no_background) @@ -276,7 +290,7 @@ public final class UserTypeFactory { .setName(USER_TYPE_PROFILE_PRIVATE) .setBaseType(FLAG_PROFILE) .setMaxAllowedPerParent(1) - .setLabel(0) + .setLabels(R.string.profile_label_private) .setIconBadge(com.android.internal.R.drawable.ic_private_profile_icon_badge) .setBadgePlain(com.android.internal.R.drawable.ic_private_profile_badge) // Private Profile doesn't use BadgeNoBackground, so just set to BadgePlain @@ -298,7 +312,10 @@ public final class UserTypeFactory { .setMediaSharedWithParent(false) .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE) - .setHideInSettingsInQuietMode(true) + .setShowInQuietMode( + UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) + .setShowInSharingSurfaces( + UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT)); diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java index 57b12251c207..d70a4fd555ec 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java @@ -60,7 +60,8 @@ public class UserManagerServiceUserPropertiesTest { .setShowInLauncher(21) .setStartWithParent(false) .setShowInSettings(45) - .setHideInSettingsInQuietMode(false) + .setShowInSharingSurfaces(78) + .setShowInQuietMode(12) .setInheritDevicePolicy(67) .setUseParentsContacts(false) .setCrossProfileIntentFilterAccessControl(10) @@ -74,7 +75,8 @@ public class UserManagerServiceUserPropertiesTest { final UserProperties actualProps = new UserProperties(defaultProps); actualProps.setShowInLauncher(14); actualProps.setShowInSettings(32); - actualProps.setHideInSettingsInQuietMode(true); + actualProps.setShowInSharingSurfaces(46); + actualProps.setShowInQuietMode(27); actualProps.setInheritDevicePolicy(51); actualProps.setUseParentsContacts(true); actualProps.setCrossProfileIntentFilterAccessControl(20); @@ -236,8 +238,10 @@ public class UserManagerServiceUserPropertiesTest { assertThat(expected.getShowInLauncher()).isEqualTo(actual.getShowInLauncher()); assertThat(expected.getStartWithParent()).isEqualTo(actual.getStartWithParent()); assertThat(expected.getShowInSettings()).isEqualTo(actual.getShowInSettings()); - assertThat(expected.getHideInSettingsInQuietMode()) - .isEqualTo(actual.getHideInSettingsInQuietMode()); + assertThat(expected.getShowInSharingSurfaces()).isEqualTo( + actual.getShowInSharingSurfaces()); + assertThat(expected.getShowInQuietMode()) + .isEqualTo(actual.getShowInQuietMode()); assertThat(expected.getInheritDevicePolicy()).isEqualTo(actual.getInheritDevicePolicy()); assertThat(expected.getUseParentsContacts()).isEqualTo(actual.getUseParentsContacts()); assertThat(expected.getCrossProfileIntentFilterAccessControl()) diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java index 48eb5c64f3d1..77f693917574 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java @@ -29,6 +29,7 @@ import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; @@ -91,7 +92,8 @@ public class UserManagerServiceUserTypeTest { .setCredentialShareableWithParent(false) .setAuthAlwaysRequiredToDisableQuietMode(true) .setShowInSettings(900) - .setHideInSettingsInQuietMode(true) + .setShowInSharingSurfaces(20) + .setShowInQuietMode(30) .setInheritDevicePolicy(340) .setDeleteAppWithParent(true) .setAlwaysVisible(true); @@ -107,9 +109,9 @@ public class UserManagerServiceUserTypeTest { .setIconBadge(28) .setBadgePlain(29) .setBadgeNoBackground(30) - .setLabel(31) .setMaxAllowedPerParent(32) .setStatusBarIcon(33) + .setLabels(34, 35, 36) .setDefaultRestrictions(restrictions) .setDefaultSystemSettings(systemSettings) .setDefaultSecureSettings(secureSettings) @@ -124,9 +126,11 @@ public class UserManagerServiceUserTypeTest { assertEquals(28, type.getIconBadge()); assertEquals(29, type.getBadgePlain()); assertEquals(30, type.getBadgeNoBackground()); - assertEquals(31, type.getLabel()); assertEquals(32, type.getMaxAllowedPerParent()); assertEquals(33, type.getStatusBarIcon()); + assertEquals(34, type.getLabel(0)); + assertEquals(35, type.getLabel(1)); + assertEquals(36, type.getLabel(2)); assertTrue(UserRestrictionsUtils.areEqual(restrictions, type.getDefaultRestrictions())); assertNotSame(restrictions, type.getDefaultRestrictions()); @@ -164,7 +168,9 @@ public class UserManagerServiceUserTypeTest { assertTrue(type.getDefaultUserPropertiesReference() .isAuthAlwaysRequiredToDisableQuietMode()); assertEquals(900, type.getDefaultUserPropertiesReference().getShowInSettings()); - assertTrue(type.getDefaultUserPropertiesReference().getHideInSettingsInQuietMode()); + assertEquals(20, type.getDefaultUserPropertiesReference().getShowInSharingSurfaces()); + assertEquals(30, + type.getDefaultUserPropertiesReference().getShowInQuietMode()); assertEquals(340, type.getDefaultUserPropertiesReference() .getInheritDevicePolicy()); assertTrue(type.getDefaultUserPropertiesReference().getDeleteAppWithParent()); @@ -203,7 +209,7 @@ public class UserManagerServiceUserTypeTest { assertEquals(Resources.ID_NULL, type.getStatusBarIcon()); assertEquals(Resources.ID_NULL, type.getBadgeLabel(0)); assertEquals(Resources.ID_NULL, type.getBadgeColor(0)); - assertEquals(Resources.ID_NULL, type.getLabel()); + assertEquals(Resources.ID_NULL, type.getLabel(0)); assertTrue(type.getDefaultRestrictions().isEmpty()); assertTrue(type.getDefaultSystemSettings().isEmpty()); assertTrue(type.getDefaultSecureSettings().isEmpty()); @@ -222,7 +228,9 @@ public class UserManagerServiceUserTypeTest { assertFalse(props.isCredentialShareableWithParent()); assertFalse(props.getDeleteAppWithParent()); assertFalse(props.getAlwaysVisible()); - assertFalse(props.getHideInSettingsInQuietMode()); + assertEquals(UserProperties.SHOW_IN_LAUNCHER_SEPARATE, props.getShowInSharingSurfaces()); + assertEquals(UserProperties.SHOW_IN_QUIET_MODE_PAUSED, + props.getShowInQuietMode()); assertFalse(type.hasBadge()); } @@ -311,8 +319,9 @@ public class UserManagerServiceUserTypeTest { .setCredentialShareableWithParent(true) .setAuthAlwaysRequiredToDisableQuietMode(false) .setShowInSettings(20) - .setHideInSettingsInQuietMode(false) .setInheritDevicePolicy(21) + .setShowInSharingSurfaces(22) + .setShowInQuietMode(24) .setDeleteAppWithParent(true) .setAlwaysVisible(false); @@ -354,9 +363,11 @@ public class UserManagerServiceUserTypeTest { assertFalse(aospType.getDefaultUserPropertiesReference() .isAuthAlwaysRequiredToDisableQuietMode()); assertEquals(20, aospType.getDefaultUserPropertiesReference().getShowInSettings()); - assertFalse(aospType.getDefaultUserPropertiesReference().getHideInSettingsInQuietMode()); assertEquals(21, aospType.getDefaultUserPropertiesReference() .getInheritDevicePolicy()); + assertEquals(22, aospType.getDefaultUserPropertiesReference().getShowInSharingSurfaces()); + assertEquals(24, + aospType.getDefaultUserPropertiesReference().getShowInQuietMode()); assertTrue(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent()); assertFalse(aospType.getDefaultUserPropertiesReference().getAlwaysVisible()); @@ -403,7 +414,10 @@ public class UserManagerServiceUserTypeTest { assertTrue(aospType.getDefaultUserPropertiesReference() .isAuthAlwaysRequiredToDisableQuietMode()); assertEquals(23, aospType.getDefaultUserPropertiesReference().getShowInSettings()); - assertTrue(aospType.getDefaultUserPropertiesReference().getHideInSettingsInQuietMode()); + assertEquals(22, + aospType.getDefaultUserPropertiesReference().getShowInSharingSurfaces()); + assertEquals(24, + aospType.getDefaultUserPropertiesReference().getShowInQuietMode()); assertEquals(450, aospType.getDefaultUserPropertiesReference() .getInheritDevicePolicy()); assertFalse(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent()); diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 2b6d8eda6bb0..c7d80edc9c2d 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -343,6 +343,8 @@ public final class UserManagerTest { assertThat(mainUserId).isEqualTo(parentProfileInfo.id); removeUser(userInfo.id); assertThat(mUserManager.getProfileParent(mainUserId)).isNull(); + assertThat(mUserManager.getProfileLabel()).isEqualTo( + Resources.getSystem().getString(userTypeDetails.getLabel(0))); } @MediumTest |