/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Class holding the properties of a user that derive mostly from its user type. * * @hide */ @SystemApi public final class UserProperties implements Parcelable { private static final String LOG_TAG = UserProperties.class.getSimpleName(); // Attribute strings for reading/writing properties to/from XML. 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_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 = "updateCrossProfileIntentFiltersOnOTA"; private static final String ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = "crossProfileIntentFilterAccessControl"; private static final String ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = "crossProfileIntentResolutionStrategy"; private static final String ATTR_MEDIA_SHARED_WITH_PARENT = "mediaSharedWithParent"; private static final String ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT = "credentialShareableWithParent"; private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { INDEX_SHOW_IN_LAUNCHER, INDEX_START_WITH_PARENT, INDEX_SHOW_IN_SETTINGS, INDEX_INHERIT_DEVICE_POLICY, INDEX_USE_PARENTS_CONTACTS, INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA, INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY, INDEX_MEDIA_SHARED_WITH_PARENT, INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT, INDEX_DELETE_APP_WITH_PARENT, }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { } private static final int INDEX_SHOW_IN_LAUNCHER = 0; private static final int INDEX_START_WITH_PARENT = 1; private static final int INDEX_SHOW_IN_SETTINGS = 2; private static final int INDEX_INHERIT_DEVICE_POLICY = 3; private static final int INDEX_USE_PARENTS_CONTACTS = 4; private static final int INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA = 5; private static final int INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = 6; private static final int INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = 7; private static final int INDEX_MEDIA_SHARED_WITH_PARENT = 8; private static final int INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT = 9; private static final int INDEX_DELETE_APP_WITH_PARENT = 10; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; /** * Possible values for whether or how to show this user in the Launcher. * @hide */ @IntDef(prefix = "SHOW_IN_LAUNCHER_", value = { SHOW_IN_LAUNCHER_WITH_PARENT, SHOW_IN_LAUNCHER_SEPARATE, SHOW_IN_LAUNCHER_NO, }) @Retention(RetentionPolicy.SOURCE) public @interface ShowInLauncher { } /** * Suggests that the launcher should show this user's apps in the main tab. * That is, either this user is a full user, so its apps should be presented accordingly, or, if * this user is a profile, then its apps should be shown alongside its parent's apps. * @hide */ @TestApi public static final int SHOW_IN_LAUNCHER_WITH_PARENT = 0; /** * Suggests that the launcher should show this user's apps, but separately from the apps of this * user's parent. * @hide */ @TestApi public static final int SHOW_IN_LAUNCHER_SEPARATE = 1; /** * Suggests that the launcher should not show this user. * @hide */ @TestApi public static final int SHOW_IN_LAUNCHER_NO = 2; /** * Possible values for whether or how to show this user in the Settings app. * @hide */ @IntDef(prefix = "SHOW_IN_SETTINGS_", value = { SHOW_IN_SETTINGS_WITH_PARENT, SHOW_IN_SETTINGS_SEPARATE, SHOW_IN_SETTINGS_NO, }) @Retention(RetentionPolicy.SOURCE) public @interface ShowInSettings { } /** * Suggests that the Settings app should show this user's apps in the main tab. * That is, either this user is a full user, so its apps should be presented accordingly, or, if * this user is a profile, then its apps should be shown alongside its parent's apps. * @hide */ public static final int SHOW_IN_SETTINGS_WITH_PARENT = 0; /** * Suggests that the Settings app should show this user's apps, but separately from the apps of * this user's parent. * @hide */ public static final int SHOW_IN_SETTINGS_SEPARATE = 1; /** * Suggests that the Settings app should not show this user. * @hide */ public static final int SHOW_IN_SETTINGS_NO = 2; /** * Possible values for whether (and from whom) to inherit select user restrictions * or device policies. * * @hide */ @IntDef(prefix = "INHERIT_DEVICE_POLICY", value = { INHERIT_DEVICE_POLICY_NO, INHERIT_DEVICE_POLICY_FROM_PARENT, }) @Retention(RetentionPolicy.SOURCE) public @interface InheritDevicePolicy { } /** * Suggests that the given user profile should not inherit user restriction or device policy * from any other user. This is the default value for any new user type. * @hide */ public static final int INHERIT_DEVICE_POLICY_NO = 0; /** * Suggests that the given user profile should inherit select user restrictions or * device policies from its parent profile. * *

All the user restrictions and device policies would be not propagated to the profile * with this property value. The {@link com.android.server.devicepolicy.DevicePolicyEngine} * uses this property to determine and propagate only select ones to the given profile. * * @hide */ public static final int INHERIT_DEVICE_POLICY_FROM_PARENT = 1; /** * Reference to the default user properties for this user's user type. *

  • If non-null, then any absent property will use the default property from here instead. *
  • If null, then any absent property indicates that the caller lacks permission to see it, * so attempting to get that property will trigger a SecurityException. */ private final @Nullable UserProperties mDefaultProperties; /** * CrossProfileIntentFilterAccessControlLevel provides level of access for user to create/modify * {@link CrossProfileIntentFilter}. Each level have value assigned, the higher the value * implies higher restriction for creation/modification. * CrossProfileIntentFilterAccessControlLevel allows us to protect against malicious changes in * user's {@link CrossProfileIntentFilter}s, which might add/remove * {@link CrossProfileIntentFilter} leading to unprecedented results. * * @hide */ @IntDef(prefix = {"CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_"}, value = { CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL, CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM, CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM_ADD_ONLY, }) @Retention(RetentionPolicy.SOURCE) public @interface CrossProfileIntentFilterAccessControlLevel { } /** * CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL signifies that irrespective of user we would * allow access (addition/modification/removal) for CrossProfileIntentFilter. * This is the default access control level. * * @hide */ public static final int CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL = 0; /** * CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM signifies that only system/root user would * be able to access (addition/modification/removal) CrossProfileIntentFilter. * * @hide */ public static final int CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM = 10; /** * CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM_ADD_ONLY signifies that only system/root * user would be able to add CrossProfileIntentFilter but not modify/remove. Once added, it * cannot be modified or removed. * * @hide */ public static final int CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM_ADD_ONLY = 20; /** * Possible values for cross profile intent resolution strategy. * * @hide */ @IntDef(prefix = {"CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_"}, value = { CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT, CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING }) @Retention(RetentionPolicy.SOURCE) public @interface CrossProfileIntentResolutionStrategy { } /** * Signifies to use {@link DefaultCrossProfileResolver} strategy, which * check if it needs to skip the initiating profile, resolves intent in target profile. * {@link DefaultCrossProfileResolver} also filters the {@link ResolveInfo} after intent * resolution based on their domain approval level * * @hide */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT = 0; /** * Signifies that there is no need to filter {@link ResolveInfo} after cross profile intent * resolution across. This strategy is for profile acting transparent to end-user and resolves * all allowed intent without giving any profile priority. * * @hide */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING = 1; /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given * default properties, which it uses for any property not subsequently set. * @hide */ public UserProperties(@NonNull UserProperties defaultProperties) { mDefaultProperties = defaultProperties; mPropertiesPresent = 0; } /** * Copies the given UserProperties, excluding any information that doesn't satisfy the specified * permissions. * Can only be used on the original version (one that won't throw on permission errors). * Note that, internally, this does not perform an exact copy. * @hide */ public UserProperties(UserProperties orig, boolean exposeAllFields, boolean hasManagePermission, boolean hasQueryOrManagePermission) { if (orig.mDefaultProperties == null) { throw new IllegalArgumentException("Attempting to copy a non-original UserProperties."); } this.mDefaultProperties = null; // Insert each setter into the following hierarchy based on its permission requirements. // NOTE: Copy each property using getters to ensure default values are copied if needed. if (exposeAllFields) { // Add items that require exposeAllFields to be true (strictest permission level). setStartWithParent(orig.getStartWithParent()); setInheritDevicePolicy(orig.getInheritDevicePolicy()); setUpdateCrossProfileIntentFiltersOnOTA(orig.getUpdateCrossProfileIntentFiltersOnOTA()); setCrossProfileIntentFilterAccessControl( orig.getCrossProfileIntentFilterAccessControl()); setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy()); setDeleteAppWithParent(orig.getDeleteAppWithParent()); } if (hasManagePermission) { // Add items that require MANAGE_USERS or stronger. setShowInSettings(orig.getShowInSettings()); setUseParentsContacts(orig.getUseParentsContacts()); } if (hasQueryOrManagePermission) { // Add items that require QUERY_USERS or stronger. } // Add items that have no permission requirements at all. setShowInLauncher(orig.getShowInLauncher()); setMediaSharedWithParent(orig.isMediaSharedWithParent()); setCredentialShareableWithParent(orig.isCredentialShareableWithParent()); } /** * Indicates that the given property is being stored explicitly in this object. * If false, it means that either *
  • the default property for the user type should be used instead (for SystemServer callers) *
  • the caller lacks permission to see this property (for all other callers) */ private boolean isPresent(@PropertyIndex long index) { return (mPropertiesPresent & (1L << index)) != 0; } /** Indicates that the given property is henceforth being explicitly stored in this object. */ private void setPresent(@PropertyIndex long index) { mPropertiesPresent |= (1L << index); } /** @hide Returns the internal mPropertiesPresent value. Only for testing purposes. */ @VisibleForTesting public long getPropertiesPresent() { return mPropertiesPresent; } /** * Returns whether, and how, a user should be shown in the Launcher. * This is generally inapplicable for non-profile users. * * Possible return values include * {@link #SHOW_IN_LAUNCHER_WITH_PARENT}}, * {@link #SHOW_IN_LAUNCHER_SEPARATE}, * and {@link #SHOW_IN_LAUNCHER_NO}. * * @return whether, and how, a profile should be shown in the Launcher. * @hide */ @TestApi public @ShowInLauncher int getShowInLauncher() { if (isPresent(INDEX_SHOW_IN_LAUNCHER)) return mShowInLauncher; if (mDefaultProperties != null) return mDefaultProperties.mShowInLauncher; throw new SecurityException("You don't have permission to query showInLauncher"); } /** @hide */ public void setShowInLauncher(@ShowInLauncher int val) { this.mShowInLauncher = val; setPresent(INDEX_SHOW_IN_LAUNCHER); } private @ShowInLauncher int mShowInLauncher; /** * Returns whether, and how, a user should be shown in the Settings app. * This is generally inapplicable for non-profile users. * * Possible return values include * {@link #SHOW_IN_SETTINGS_WITH_PARENT}}, * {@link #SHOW_IN_SETTINGS_SEPARATE}, * and {@link #SHOW_IN_SETTINGS_NO}. * *

    The caller must have {@link android.Manifest.permission#MANAGE_USERS} to query this * property. * * @return whether, and how, a profile should be shown in the Settings. * @hide */ public @ShowInSettings int getShowInSettings() { if (isPresent(INDEX_SHOW_IN_SETTINGS)) return mShowInSettings; if (mDefaultProperties != null) return mDefaultProperties.mShowInSettings; throw new SecurityException("You don't have permission to query mShowInSettings"); } /** @hide */ public void setShowInSettings(@ShowInSettings int val) { this.mShowInSettings = val; setPresent(INDEX_SHOW_IN_SETTINGS); } private @ShowInSettings int mShowInSettings; /** * Returns whether a profile should be started when its parent starts (unless in quiet mode). * This only applies for users that have parents (i.e. for profiles). * @hide */ public boolean getStartWithParent() { if (isPresent(INDEX_START_WITH_PARENT)) return mStartWithParent; if (mDefaultProperties != null) return mDefaultProperties.mStartWithParent; throw new SecurityException("You don't have permission to query startWithParent"); } /** @hide */ public void setStartWithParent(boolean val) { this.mStartWithParent = val; setPresent(INDEX_START_WITH_PARENT); } private boolean mStartWithParent; /** * Returns whether an app in the profile should be deleted when the same package in * the parent user is being deleted. * This only applies for users that have parents (i.e. for profiles). * @hide */ public boolean getDeleteAppWithParent() { if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) return mDeleteAppWithParent; if (mDefaultProperties != null) return mDefaultProperties.mDeleteAppWithParent; throw new SecurityException("You don't have permission to query deleteAppWithParent"); } /** @hide */ public void setDeleteAppWithParent(boolean val) { this.mDeleteAppWithParent = val; setPresent(INDEX_DELETE_APP_WITH_PARENT); } private boolean mDeleteAppWithParent; /** * Return whether, and how, select user restrictions or device policies should be inherited * from other user. * * Possible return values include * {@link #INHERIT_DEVICE_POLICY_FROM_PARENT} or {@link #INHERIT_DEVICE_POLICY_NO} * * @hide */ public @InheritDevicePolicy int getInheritDevicePolicy() { if (isPresent(INDEX_INHERIT_DEVICE_POLICY)) return mInheritDevicePolicy; if (mDefaultProperties != null) return mDefaultProperties.mInheritDevicePolicy; throw new SecurityException("You don't have permission to query inheritDevicePolicy"); } /** @hide */ public void setInheritDevicePolicy(@InheritDevicePolicy int val) { this.mInheritDevicePolicy = val; setPresent(INDEX_INHERIT_DEVICE_POLICY); } private @InheritDevicePolicy int mInheritDevicePolicy; /** * Returns whether the current user must use parent user's contacts. If true, writes to the * ContactsProvider corresponding to the current user will be disabled and reads will be * redirected to the parent. * * This only applies to users that have parents (i.e. profiles) and is used to ensure * they can access contacts from the parent profile. This will be generally inapplicable for * non-profile users. * * Please note that in case of the clone profiles, only the allow-listed apps would be allowed * to access contacts across profiles and other apps will not see any contacts. * TODO(b/256126819) Add link to the method returning apps allow-listed for app-cloning * * @return whether contacts access from an associated profile is enabled for the user * @hide */ public boolean getUseParentsContacts() { if (isPresent(INDEX_USE_PARENTS_CONTACTS)) return mUseParentsContacts; if (mDefaultProperties != null) return mDefaultProperties.mUseParentsContacts; throw new SecurityException("You don't have permission to query useParentsContacts"); } /** @hide */ public void setUseParentsContacts(boolean val) { this.mUseParentsContacts = val; setPresent(INDEX_USE_PARENTS_CONTACTS); } /** * Indicates whether the current user should use parent user's contacts. * If this property is set true, the user will be blocked from storing any contacts in its * own contacts database and will serve all read contacts calls through the parent's contacts. */ private boolean mUseParentsContacts; /** * Returns true if user needs to update default * {@link com.android.server.pm.CrossProfileIntentFilter} with its parents during an OTA update * @hide */ public boolean getUpdateCrossProfileIntentFiltersOnOTA() { if (isPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA)) { return mUpdateCrossProfileIntentFiltersOnOTA; } if (mDefaultProperties != null) { return mDefaultProperties.mUpdateCrossProfileIntentFiltersOnOTA; } throw new SecurityException("You don't have permission to query " + "updateCrossProfileIntentFiltersOnOTA"); } /** @hide */ public void setUpdateCrossProfileIntentFiltersOnOTA(boolean val) { this.mUpdateCrossProfileIntentFiltersOnOTA = val; setPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA); } /** * Returns whether a profile shares media with its parent user. * This only applies for users that have parents (i.e. for profiles). */ public boolean isMediaSharedWithParent() { if (isPresent(INDEX_MEDIA_SHARED_WITH_PARENT)) return mMediaSharedWithParent; if (mDefaultProperties != null) return mDefaultProperties.mMediaSharedWithParent; throw new SecurityException("You don't have permission to query mediaSharedWithParent"); } /** @hide */ public void setMediaSharedWithParent(boolean val) { this.mMediaSharedWithParent = val; setPresent(INDEX_MEDIA_SHARED_WITH_PARENT); } private boolean mMediaSharedWithParent; /** * Returns whether a profile can have shared lockscreen credential with its parent user. * This only applies for users that have parents (i.e. for profiles). */ public boolean isCredentialShareableWithParent() { if (isPresent(INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT)) { return mCredentialShareableWithParent; } if (mDefaultProperties != null) return mDefaultProperties.mCredentialShareableWithParent; throw new SecurityException( "You don't have permission to query credentialShareableWithParent"); } /** @hide */ public void setCredentialShareableWithParent(boolean val) { this.mCredentialShareableWithParent = val; setPresent(INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT); } private boolean mCredentialShareableWithParent; /* Indicate if {@link com.android.server.pm.CrossProfileIntentFilter}s need to be updated during OTA update between user-parent */ private boolean mUpdateCrossProfileIntentFiltersOnOTA; /** * Returns the user's {@link CrossProfileIntentFilterAccessControlLevel}. * @hide */ public @CrossProfileIntentFilterAccessControlLevel int getCrossProfileIntentFilterAccessControl() { if (isPresent(INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL)) { return mCrossProfileIntentFilterAccessControl; } if (mDefaultProperties != null) { return mDefaultProperties.mCrossProfileIntentFilterAccessControl; } throw new SecurityException("You don't have permission to query " + "crossProfileIntentFilterAccessControl"); } /** * Sets {@link CrossProfileIntentFilterAccessControlLevel} for the user. * @param val access control for user * @hide */ public void setCrossProfileIntentFilterAccessControl( @CrossProfileIntentFilterAccessControlLevel int val) { this.mCrossProfileIntentFilterAccessControl = val; setPresent(INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL); } private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl; /** * Returns the user's {@link CrossProfileIntentResolutionStrategy}. If not explicitly * configured, default value is {@link #CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT}. * @return user's {@link CrossProfileIntentResolutionStrategy}. * * @hide */ public @CrossProfileIntentResolutionStrategy int getCrossProfileIntentResolutionStrategy() { if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) { return mCrossProfileIntentResolutionStrategy; } if (mDefaultProperties != null) { return mDefaultProperties.mCrossProfileIntentResolutionStrategy; } throw new SecurityException("You don't have permission to query " + "crossProfileIntentResolutionStrategy"); } /** * Sets {@link CrossProfileIntentResolutionStrategy} for the user. * @param val resolution strategy for user * @hide */ public void setCrossProfileIntentResolutionStrategy( @CrossProfileIntentResolutionStrategy int val) { this.mCrossProfileIntentResolutionStrategy = val; setPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY); } private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy; @Override public String toString() { // Please print in increasing order of PropertyIndex. return "UserProperties{" + "mPropertiesPresent=" + Long.toBinaryString(mPropertiesPresent) + ", mShowInLauncher=" + getShowInLauncher() + ", mStartWithParent=" + getStartWithParent() + ", mShowInSettings=" + getShowInSettings() + ", mInheritDevicePolicy=" + getInheritDevicePolicy() + ", mUseParentsContacts=" + getUseParentsContacts() + ", mUpdateCrossProfileIntentFiltersOnOTA=" + getUpdateCrossProfileIntentFiltersOnOTA() + ", mCrossProfileIntentFilterAccessControl=" + getCrossProfileIntentFilterAccessControl() + ", mCrossProfileIntentResolutionStrategy=" + getCrossProfileIntentResolutionStrategy() + ", mMediaSharedWithParent=" + isMediaSharedWithParent() + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent() + ", mDeleteAppWithParent=" + getDeleteAppWithParent() + "}"; } /** * Print the UserProperties to the given PrintWriter. * @hide */ public void println(PrintWriter pw, String prefix) { // Please print in increasing order of PropertyIndex. pw.println(prefix + "UserProperties:"); pw.println(prefix + " mPropertiesPresent=" + Long.toBinaryString(mPropertiesPresent)); pw.println(prefix + " mShowInLauncher=" + getShowInLauncher()); pw.println(prefix + " mStartWithParent=" + getStartWithParent()); pw.println(prefix + " mShowInSettings=" + getShowInSettings()); pw.println(prefix + " mInheritDevicePolicy=" + getInheritDevicePolicy()); pw.println(prefix + " mUseParentsContacts=" + getUseParentsContacts()); pw.println(prefix + " mUpdateCrossProfileIntentFiltersOnOTA=" + getUpdateCrossProfileIntentFiltersOnOTA()); pw.println(prefix + " mCrossProfileIntentFilterAccessControl=" + getCrossProfileIntentFilterAccessControl()); pw.println(prefix + " mCrossProfileIntentResolutionStrategy=" + getCrossProfileIntentResolutionStrategy()); pw.println(prefix + " mMediaSharedWithParent=" + isMediaSharedWithParent()); pw.println(prefix + " mCredentialShareableWithParent=" + isCredentialShareableWithParent()); pw.println(prefix + " mDeleteAppWithParent=" + getDeleteAppWithParent()); } /** * Reads in a UserProperties from an xml file, for use by the SystemServer. * * The serializer should already be inside a tag from which to read the user properties. * * @param defaultUserPropertiesReference the default UserProperties to use for this user type. * @see #writeToXml * @hide */ public UserProperties( TypedXmlPullParser parser, @NonNull UserProperties defaultUserPropertiesReference) throws IOException, XmlPullParserException { this(defaultUserPropertiesReference); updateFromXml(parser); } /** * Parses the given xml file and updates this UserProperties with its data. * I.e., if a piece of data is present in the xml, it will overwrite whatever was * previously stored in this UserProperties. * @hide */ public void updateFromXml(TypedXmlPullParser parser) throws IOException, XmlPullParserException { final int attributeCount = parser.getAttributeCount(); for (int i = 0; i < attributeCount; i++) { final String attributeName = parser.getAttributeName(i); switch(attributeName) { case ATTR_SHOW_IN_LAUNCHER: setShowInLauncher(parser.getAttributeInt(i)); break; case ATTR_START_WITH_PARENT: setStartWithParent(parser.getAttributeBoolean(i)); break; case ATTR_SHOW_IN_SETTINGS: setShowInSettings(parser.getAttributeInt(i)); break; case ATTR_INHERIT_DEVICE_POLICY: setInheritDevicePolicy(parser.getAttributeInt(i)); break; case ATTR_USE_PARENTS_CONTACTS: setUseParentsContacts(parser.getAttributeBoolean(i)); break; case ATTR_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA: setUpdateCrossProfileIntentFiltersOnOTA(parser.getAttributeBoolean(i)); break; case ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL: setCrossProfileIntentFilterAccessControl(parser.getAttributeInt(i)); break; case ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY: setCrossProfileIntentResolutionStrategy(parser.getAttributeInt(i)); break; case ATTR_MEDIA_SHARED_WITH_PARENT: setMediaSharedWithParent(parser.getAttributeBoolean(i)); break; case ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT: setCredentialShareableWithParent(parser.getAttributeBoolean(i)); break; case ATTR_DELETE_APP_WITH_PARENT: setDeleteAppWithParent(parser.getAttributeBoolean(i)); break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } } } /** * Writes the UserProperties, as used by the SystemServer, to the xml file. * * The serializer should already be inside a tag in which to write the user properties. * * @see #UserProperties(TypedXmlPullParser, UserProperties) * @hide */ public void writeToXml(TypedXmlSerializer serializer) throws IOException, XmlPullParserException { if (isPresent(INDEX_SHOW_IN_LAUNCHER)) { serializer.attributeInt(null, ATTR_SHOW_IN_LAUNCHER, mShowInLauncher); } if (isPresent(INDEX_START_WITH_PARENT)) { serializer.attributeBoolean(null, ATTR_START_WITH_PARENT, mStartWithParent); } if (isPresent(INDEX_SHOW_IN_SETTINGS)) { serializer.attributeInt(null, ATTR_SHOW_IN_SETTINGS, mShowInSettings); } if (isPresent(INDEX_INHERIT_DEVICE_POLICY)) { serializer.attributeInt(null, ATTR_INHERIT_DEVICE_POLICY, mInheritDevicePolicy); } if (isPresent(INDEX_USE_PARENTS_CONTACTS)) { serializer.attributeBoolean(null, ATTR_USE_PARENTS_CONTACTS, mUseParentsContacts); } if (isPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA)) { serializer.attributeBoolean(null, ATTR_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA, mUpdateCrossProfileIntentFiltersOnOTA); } if (isPresent(INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL)) { serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, mCrossProfileIntentFilterAccessControl); } if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) { serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY, mCrossProfileIntentResolutionStrategy); } if (isPresent(INDEX_MEDIA_SHARED_WITH_PARENT)) { serializer.attributeBoolean(null, ATTR_MEDIA_SHARED_WITH_PARENT, mMediaSharedWithParent); } if (isPresent(INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT)) { serializer.attributeBoolean(null, ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT, mCredentialShareableWithParent); } if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) { serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT, mDeleteAppWithParent); } } // For use only with an object that has already had any permission-lacking fields stripped out. @Override public void writeToParcel(@NonNull Parcel dest, int parcelableFlags) { dest.writeLong(mPropertiesPresent); dest.writeInt(mShowInLauncher); dest.writeBoolean(mStartWithParent); dest.writeInt(mShowInSettings); dest.writeInt(mInheritDevicePolicy); dest.writeBoolean(mUseParentsContacts); dest.writeBoolean(mUpdateCrossProfileIntentFiltersOnOTA); dest.writeInt(mCrossProfileIntentFilterAccessControl); dest.writeInt(mCrossProfileIntentResolutionStrategy); dest.writeBoolean(mMediaSharedWithParent); dest.writeBoolean(mCredentialShareableWithParent); dest.writeBoolean(mDeleteAppWithParent); } /** * Reads a UserProperties object from the parcel. * Not suitable for the canonical SystemServer version since it lacks mDefaultProperties. */ private UserProperties(@NonNull Parcel source) { mDefaultProperties = null; mPropertiesPresent = source.readLong(); mShowInLauncher = source.readInt(); mStartWithParent = source.readBoolean(); mShowInSettings = source.readInt(); mInheritDevicePolicy = source.readInt(); mUseParentsContacts = source.readBoolean(); mUpdateCrossProfileIntentFiltersOnOTA = source.readBoolean(); mCrossProfileIntentFilterAccessControl = source.readInt(); mCrossProfileIntentResolutionStrategy = source.readInt(); mMediaSharedWithParent = source.readBoolean(); mCredentialShareableWithParent = source.readBoolean(); mDeleteAppWithParent = source.readBoolean(); } @Override public int describeContents() { return 0; } public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public UserProperties createFromParcel(Parcel source) { return new UserProperties(source); } public UserProperties[] newArray(int size) { return new UserProperties[size]; } }; /** * Builder for the SystemServer's {@link UserProperties}; see that class for documentation. * Intended for building default values (and so all properties are present in the built object). * @hide */ public static final class Builder { // UserProperties fields and their default values. private @ShowInLauncher int mShowInLauncher = SHOW_IN_LAUNCHER_WITH_PARENT; private boolean mStartWithParent = false; private @ShowInSettings int mShowInSettings = SHOW_IN_SETTINGS_WITH_PARENT; private @InheritDevicePolicy int mInheritDevicePolicy = INHERIT_DEVICE_POLICY_NO; private boolean mUseParentsContacts = false; private boolean mUpdateCrossProfileIntentFiltersOnOTA = false; private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl = CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL; private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy = CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT; private boolean mMediaSharedWithParent = false; private boolean mCredentialShareableWithParent = false; private boolean mDeleteAppWithParent = false; public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) { mShowInLauncher = showInLauncher; return this; } public Builder setStartWithParent(boolean startWithParent) { mStartWithParent = startWithParent; return this; } /** Sets the value for {@link #mShowInSettings} */ public Builder setShowInSettings(@ShowInSettings int showInSettings) { mShowInSettings = showInSettings; return this; } /** Sets the value for {@link #mInheritDevicePolicy}*/ public Builder setInheritDevicePolicy( @InheritDevicePolicy int inheritRestrictionsDevicePolicy) { mInheritDevicePolicy = inheritRestrictionsDevicePolicy; return this; } public Builder setUseParentsContacts(boolean useParentsContacts) { mUseParentsContacts = useParentsContacts; return this; } /** Sets the value for {@link #mUpdateCrossProfileIntentFiltersOnOTA} */ public Builder setUpdateCrossProfileIntentFiltersOnOTA(boolean updateCrossProfileIntentFiltersOnOTA) { mUpdateCrossProfileIntentFiltersOnOTA = updateCrossProfileIntentFiltersOnOTA; return this; } /** Sets the value for {@link #mCrossProfileIntentFilterAccessControl} */ public Builder setCrossProfileIntentFilterAccessControl( @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl) { mCrossProfileIntentFilterAccessControl = crossProfileIntentFilterAccessControl; return this; } /** Sets the value for {@link #mCrossProfileIntentResolutionStrategy} */ public Builder setCrossProfileIntentResolutionStrategy(@CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy) { mCrossProfileIntentResolutionStrategy = crossProfileIntentResolutionStrategy; return this; } public Builder setMediaSharedWithParent(boolean mediaSharedWithParent) { mMediaSharedWithParent = mediaSharedWithParent; return this; } public Builder setCredentialShareableWithParent(boolean credentialShareableWithParent) { mCredentialShareableWithParent = credentialShareableWithParent; return this; } /** Sets the value for {@link #mDeleteAppWithParent}*/ public Builder setDeleteAppWithParent(boolean deleteAppWithParent) { mDeleteAppWithParent = deleteAppWithParent; return this; } /** Builds a UserProperties object with *all* values populated. */ public UserProperties build() { return new UserProperties( mShowInLauncher, mStartWithParent, mShowInSettings, mInheritDevicePolicy, mUseParentsContacts, mUpdateCrossProfileIntentFiltersOnOTA, mCrossProfileIntentFilterAccessControl, mCrossProfileIntentResolutionStrategy, mMediaSharedWithParent, mCredentialShareableWithParent, mDeleteAppWithParent); } } // end Builder /** Creates a UserProperties with the given properties. Intended for building default values. */ private UserProperties( @ShowInLauncher int showInLauncher, boolean startWithParent, @ShowInSettings int showInSettings, @InheritDevicePolicy int inheritDevicePolicy, boolean useParentsContacts, boolean updateCrossProfileIntentFiltersOnOTA, @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl, @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy, boolean mediaSharedWithParent, boolean credentialShareableWithParent, boolean deleteAppWithParent) { mDefaultProperties = null; setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); setShowInSettings(showInSettings); setInheritDevicePolicy(inheritDevicePolicy); setUseParentsContacts(useParentsContacts); setUpdateCrossProfileIntentFiltersOnOTA(updateCrossProfileIntentFiltersOnOTA); setCrossProfileIntentFilterAccessControl(crossProfileIntentFilterAccessControl); setCrossProfileIntentResolutionStrategy(crossProfileIntentResolutionStrategy); setMediaSharedWithParent(mediaSharedWithParent); setCredentialShareableWithParent(credentialShareableWithParent); setDeleteAppWithParent(deleteAppWithParent); } }