/*
 * Copyright (C) 2019 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 com.android.server.pm;

import static android.content.pm.UserInfo.FLAG_ADMIN;
import static android.content.pm.UserInfo.FLAG_DEMO;
import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
import static android.content.pm.UserInfo.FLAG_FULL;
import static android.content.pm.UserInfo.FLAG_GUEST;
import static android.content.pm.UserInfo.FLAG_MAIN;
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static android.content.pm.UserInfo.FLAG_PRIMARY;
import static android.content.pm.UserInfo.FLAG_PROFILE;
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
import static android.content.pm.UserInfo.FLAG_SYSTEM;
import static android.os.UserManager.USER_TYPE_FULL_DEMO;
import static android.os.UserManager.USER_TYPE_FULL_GUEST;
import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED;
import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
import static android.os.UserManager.USER_TYPE_PROFILE_COMMUNAL;
import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
import static android.os.UserManager.USER_TYPE_PROFILE_TEST;
import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;

import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS;

import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Build;
import android.os.Bundle;
import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Class for creating all {@link UserTypeDetails} on the device.
 *
 * This class is responsible both for defining the AOSP use types, as well as reading in customized
 * user types from {@link com.android.internal.R.xml#config_user_types}.
 *
 * Tests are located in {@link UserManagerServiceUserTypeTest}.
 * @hide
 */
public final class UserTypeFactory {

    private static final String LOG_TAG = "UserTypeFactory";

    /** This is a utility class, so no instantiable constructor. */
    private UserTypeFactory() {}

    /**
     * Obtains the user types (built-in and customized) for this device.
     *
     * @return mapping from the name of each user type to its {@link UserTypeDetails} object
     */
    public static ArrayMap<String, UserTypeDetails> getUserTypes() {
        final ArrayMap<String, UserTypeDetails.Builder> builders = getDefaultBuilders();

        try (XmlResourceParser parser =
                     Resources.getSystem().getXml(com.android.internal.R.xml.config_user_types)) {
            customizeBuilders(builders, parser);
        }

        final ArrayMap<String, UserTypeDetails> types = new ArrayMap<>(builders.size());
        for (int i = 0; i < builders.size(); i++) {
            types.put(builders.keyAt(i), builders.valueAt(i).createUserTypeDetails());
        }
        return types;
    }

    private static ArrayMap<String, UserTypeDetails.Builder> getDefaultBuilders() {
        final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();

        builders.put(USER_TYPE_PROFILE_MANAGED, getDefaultTypeProfileManaged());
        builders.put(USER_TYPE_FULL_SYSTEM, getDefaultTypeFullSystem());
        builders.put(USER_TYPE_FULL_SECONDARY, getDefaultTypeFullSecondary());
        builders.put(USER_TYPE_FULL_GUEST, getDefaultTypeFullGuest());
        builders.put(USER_TYPE_FULL_DEMO, getDefaultTypeFullDemo());
        builders.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted());
        builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless());
        builders.put(USER_TYPE_PROFILE_CLONE, getDefaultTypeProfileClone());
        builders.put(USER_TYPE_PROFILE_COMMUNAL, getDefaultTypeProfileCommunal());
        builders.put(USER_TYPE_PROFILE_PRIVATE, getDefaultTypeProfilePrivate());
        if (Build.IS_DEBUGGABLE) {
            builders.put(USER_TYPE_PROFILE_TEST, getDefaultTypeProfileTest());
        }

        return builders;
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_CLONE}
     * configuration.
     */
    // TODO(b/182396009): Add default restrictions, if needed for clone user type.
    private static UserTypeDetails.Builder getDefaultTypeProfileClone() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_PROFILE_CLONE)
                .setBaseType(FLAG_PROFILE)
                .setMaxAllowedPerParent(1)
                .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.
                .setBadgeNoBackground(com.android.internal.R.drawable.ic_clone_badge)
                .setStatusBarIcon(Resources.ID_NULL)
                .setBadgeLabels(
                        com.android.internal.R.string.clone_profile_label_badge)
                .setBadgeColors(
                        com.android.internal.R.color.system_neutral2_800)
                .setDarkThemeBadgeColors(
                        com.android.internal.R.color.system_neutral2_900)
                .setDefaultRestrictions(null)
                .setDefaultCrossProfileIntentFilters(getDefaultCloneCrossProfileIntentFilter())
                .setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings())
                .setDefaultUserProperties(new UserProperties.Builder()
                        .setStartWithParent(true)
                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_WITH_PARENT)
                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_WITH_PARENT)
                        .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT)
                        .setUseParentsContacts(true)
                        .setUpdateCrossProfileIntentFiltersOnOTA(true)
                        .setCrossProfileIntentFilterAccessControl(
                                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)
                        .setCrossProfileContentSharingStrategy(UserProperties
                                .CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT));
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_MANAGED}
     * configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeProfileManaged() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_PROFILE_MANAGED)
                .setBaseType(FLAG_PROFILE)
                .setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE)
                .setMaxAllowedPerParent(1)
                .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)
                .setStatusBarIcon(com.android.internal.R.drawable.stat_sys_managed_profile_status)
                .setBadgeLabels(
                        com.android.internal.R.string.managed_profile_label_badge,
                        com.android.internal.R.string.managed_profile_label_badge_2,
                        com.android.internal.R.string.managed_profile_label_badge_3)
                .setBadgeColors(
                        com.android.internal.R.color.profile_badge_1,
                        com.android.internal.R.color.profile_badge_2,
                        com.android.internal.R.color.profile_badge_3)
                .setDarkThemeBadgeColors(
                        com.android.internal.R.color.profile_badge_1_dark,
                        com.android.internal.R.color.profile_badge_2_dark,
                        com.android.internal.R.color.profile_badge_3_dark)
                .setDefaultRestrictions(getDefaultProfileRestrictions())
                .setDefaultSecureSettings(getDefaultManagedProfileSecureSettings())
                .setDefaultCrossProfileIntentFilters(getDefaultManagedCrossProfileIntentFilter())
                .setDefaultUserProperties(new UserProperties.Builder()
                        .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));
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_TEST}
     * configuration (for userdebug builds). For now it just uses managed profile badges.
     */
    private static UserTypeDetails.Builder getDefaultTypeProfileTest() {
        final Bundle restrictions = getDefaultProfileRestrictions();
        restrictions.putBoolean(UserManager.DISALLOW_FUN, true);

        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_PROFILE_TEST)
                .setBaseType(FLAG_PROFILE)
                .setMaxAllowedPerParent(2)
                .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)
                .setStatusBarIcon(com.android.internal.R.drawable.ic_test_badge_experiment)
                .setBadgeLabels(
                        com.android.internal.R.string.managed_profile_label_badge,
                        com.android.internal.R.string.managed_profile_label_badge_2,
                        com.android.internal.R.string.managed_profile_label_badge_3)
                .setBadgeColors(
                        com.android.internal.R.color.profile_badge_1,
                        com.android.internal.R.color.profile_badge_2,
                        com.android.internal.R.color.profile_badge_3)
                .setDarkThemeBadgeColors(
                        com.android.internal.R.color.profile_badge_1_dark,
                        com.android.internal.R.color.profile_badge_2_dark,
                        com.android.internal.R.color.profile_badge_3_dark)
                .setDefaultRestrictions(restrictions)
                .setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings());
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_COMMUNAL}
     * configuration. For now it just uses managed profile badges.
     */
    private static UserTypeDetails.Builder getDefaultTypeProfileCommunal() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_PROFILE_COMMUNAL)
                .setBaseType(FLAG_PROFILE)
                .setMaxAllowed(1)
                .setEnabled(UserManager.isCommunalProfileEnabled() ? 1 : 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)
                .setStatusBarIcon(com.android.internal.R.drawable.ic_test_badge_experiment)
                .setBadgeLabels(
                        com.android.internal.R.string.managed_profile_label_badge,
                        com.android.internal.R.string.managed_profile_label_badge_2,
                        com.android.internal.R.string.managed_profile_label_badge_3)
                .setBadgeColors(
                        com.android.internal.R.color.profile_badge_1,
                        com.android.internal.R.color.profile_badge_2,
                        com.android.internal.R.color.profile_badge_3)
                .setDarkThemeBadgeColors(
                        com.android.internal.R.color.profile_badge_1_dark,
                        com.android.internal.R.color.profile_badge_2_dark,
                        com.android.internal.R.color.profile_badge_3_dark)
                .setDefaultRestrictions(getDefaultProfileRestrictions())
                .setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings())
                .setDefaultUserProperties(new UserProperties.Builder()
                        .setStartWithParent(false)
                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE)
                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE)
                        .setCredentialShareableWithParent(false)
                        .setAlwaysVisible(true));
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_PRIVATE}
     * configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeProfilePrivate() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_PROFILE_PRIVATE)
                .setBaseType(FLAG_PROFILE)
                .setMaxAllowedPerParent(1)
                .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
                // as a placeholder.
                .setBadgeNoBackground(com.android.internal.R.drawable.ic_private_profile_badge)
                .setStatusBarIcon(com.android.internal.R.drawable.stat_sys_private_profile_status)
                .setBadgeLabels(
                        com.android.internal.R.string.private_profile_label_badge)
                .setBadgeColors(
                        R.color.black)
                .setDarkThemeBadgeColors(
                        R.color.white)
                .setDefaultRestrictions(getDefaultProfileRestrictions())
                .setDefaultUserProperties(new UserProperties.Builder()
                        .setStartWithParent(true)
                        .setCredentialShareableWithParent(true)
                        .setAuthAlwaysRequiredToDisableQuietMode(true)
                        .setAllowStoppingUserWithDelayedLocking(true)
                        .setMediaSharedWithParent(false)
                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE)
                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE)
                        .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)
                        .setCrossProfileContentSharingStrategy(
                                UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT));
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SECONDARY}
     * configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeFullSecondary() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_FULL_SECONDARY)
                .setBaseType(FLAG_FULL)
                .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS)
                .setDefaultRestrictions(getDefaultSecondaryUserRestrictions());
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_GUEST} configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeFullGuest() {
        final boolean ephemeralGuests = Resources.getSystem()
                .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
        final int flags = FLAG_GUEST | (ephemeralGuests ? FLAG_EPHEMERAL : 0);

        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_FULL_GUEST)
                .setBaseType(FLAG_FULL)
                .setDefaultUserInfoPropertyFlags(flags)
                .setMaxAllowed(1)
                .setDefaultRestrictions(getDefaultGuestUserRestrictions());
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_DEMO} configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeFullDemo() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_FULL_DEMO)
                .setBaseType(FLAG_FULL)
                .setDefaultUserInfoPropertyFlags(FLAG_DEMO)
                .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS)
                .setDefaultRestrictions(null);
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_RESTRICTED}
     * configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeFullRestricted() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_FULL_RESTRICTED)
                .setBaseType(FLAG_FULL)
                .setDefaultUserInfoPropertyFlags(FLAG_RESTRICTED)
                .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS)
                // NB: UserManagerService.createRestrictedProfile() applies hardcoded restrictions.
                .setDefaultRestrictions(null);
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SYSTEM} configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeFullSystem() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_FULL_SYSTEM)
                .setBaseType(FLAG_SYSTEM | FLAG_FULL)
                .setDefaultUserInfoPropertyFlags(FLAG_PRIMARY | FLAG_ADMIN | FLAG_MAIN)
                .setMaxAllowed(1);
    }

    /**
     * Returns the Builder for the default {@link UserManager#USER_TYPE_SYSTEM_HEADLESS}
     * configuration.
     */
    private static UserTypeDetails.Builder getDefaultTypeSystemHeadless() {
        return new UserTypeDetails.Builder()
                .setName(USER_TYPE_SYSTEM_HEADLESS)
                .setBaseType(FLAG_SYSTEM)
                .setDefaultUserInfoPropertyFlags(FLAG_PRIMARY | FLAG_ADMIN)
                .setMaxAllowed(1);
    }

    private static Bundle getDefaultSecondaryUserRestrictions() {
        final Bundle restrictions = new Bundle();
        restrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
        restrictions.putBoolean(UserManager.DISALLOW_SMS, true);
        return restrictions;
    }

    private static Bundle getDefaultGuestUserRestrictions() {
        // Guest inherits the secondary user's restrictions, plus has some extra ones.
        final Bundle restrictions = getDefaultSecondaryUserRestrictions();
        restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true);
        restrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
        restrictions.putBoolean(UserManager.DISALLOW_CONFIG_CREDENTIALS, true);
        return restrictions;
    }

    private static Bundle getDefaultProfileRestrictions() {
        final Bundle restrictions = new Bundle();
        restrictions.putBoolean(UserManager.DISALLOW_WALLPAPER, true);
        return restrictions;
    }

    private static Bundle getDefaultManagedProfileSecureSettings() {
        // Only add String values to the bundle, settings are written as Strings eventually
        final Bundle settings = new Bundle();
        settings.putString(
                android.provider.Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH, "1");
        settings.putString(
                android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED, "1");
        return settings;
    }

    private static List<DefaultCrossProfileIntentFilter>
            getDefaultManagedCrossProfileIntentFilter() {
        return DefaultCrossProfileIntentFiltersUtils.getDefaultManagedProfileFilters();
    }

    private static List<DefaultCrossProfileIntentFilter> getDefaultCloneCrossProfileIntentFilter() {
        return DefaultCrossProfileIntentFiltersUtils.getDefaultCloneProfileFilters();
    }

    /** Gets a default bundle, keyed by Settings.Secure String names, for non-managed profiles. */
    private static Bundle getDefaultNonManagedProfileSecureSettings() {
        final Bundle settings = new Bundle();
        // Non-managed profiles go through neither SetupWizard nor DPC flows, so we automatically
        // mark them as setup.
        settings.putString(android.provider.Settings.Secure.USER_SETUP_COMPLETE, "1");
        return settings;
    }

    /**
     * Reads the given xml parser to obtain device user-type customization, and updates the given
     * map of {@link UserTypeDetails.Builder}s accordingly.
     * <p>
     * The xml file can specify the attributes according to the set... methods below.
     */
    // TODO(b/176973369): Add parsing logic to support custom settings/filters
    //  in config_user_types.xml
    @VisibleForTesting
    static void customizeBuilders(ArrayMap<String, UserTypeDetails.Builder> builders,
            XmlResourceParser parser) {
        try {
            XmlUtils.beginDocument(parser, "user-types");
            for (XmlUtils.nextElement(parser);
                    parser.getEventType() != XmlResourceParser.END_DOCUMENT;
                    XmlUtils.nextElement(parser)) {
                final boolean isProfile;
                final String elementName = parser.getName();
                if ("profile-type".equals(elementName)) {
                    isProfile = true;
                } else if ("full-type".equals(elementName)) {
                    isProfile = false;
                } else if ("change-user-type".equals(elementName)) {
                    // parsed in parseUserUpgrades
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                } else {
                    Slog.w(LOG_TAG, "Skipping unknown element " + elementName + " in "
                                + parser.getPositionDescription());
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }

                String typeName = parser.getAttributeValue(null, "name");
                if (typeName == null || typeName.equals("")) {
                    Slog.w(LOG_TAG, "Skipping user type with no name in "
                            + parser.getPositionDescription());
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
                typeName = typeName.intern();

                UserTypeDetails.Builder builder;
                if (typeName.startsWith("android.")) {
                    // typeName refers to a AOSP-defined type which we are modifying.
                    Slog.i(LOG_TAG, "Customizing user type " + typeName);
                    builder = builders.get(typeName);
                    if (builder == null) {
                        throw new IllegalArgumentException("Illegal custom user type name "
                                + typeName + ": Non-AOSP user types cannot start with 'android.'");
                    }
                    final boolean isValid =
                            (isProfile && builder.getBaseType() == UserInfo.FLAG_PROFILE)
                            || (!isProfile && builder.getBaseType() == UserInfo.FLAG_FULL);
                    if (!isValid) {
                        throw new IllegalArgumentException("Wrong base type to customize user type "
                                + "(" + typeName + "), which is type "
                                + UserInfo.flagsToString(builder.getBaseType()));
                    }
                } else if (isProfile) {
                    // typeName refers to a new OEM-defined profile type which we are defining.
                    Slog.i(LOG_TAG, "Creating custom user type " + typeName);
                    builder = new UserTypeDetails.Builder();
                    builder.setName(typeName);
                    builder.setBaseType(FLAG_PROFILE);
                    builders.put(typeName, builder);
                } else {
                    throw new IllegalArgumentException("Creation of non-profile user type "
                            + "(" + typeName + ") is not currently supported.");
                }

                // Process the attributes (other than name).
                if (isProfile) {
                    setIntAttribute(parser, "max-allowed-per-parent",
                            builder::setMaxAllowedPerParent);
                    setResAttribute(parser, "icon-badge", builder::setIconBadge);
                    setResAttribute(parser, "badge-plain", builder::setBadgePlain);
                    setResAttribute(parser, "badge-no-background", builder::setBadgeNoBackground);
                    setResAttribute(parser, "status-bar-icon", builder::setStatusBarIcon);
                }

                setIntAttribute(parser, "enabled", builder::setEnabled);
                setIntAttribute(parser, "max-allowed", builder::setMaxAllowed);

                // Process child elements.
                final int depth = parser.getDepth();
                while (XmlUtils.nextElementWithin(parser, depth)) {
                    final String childName = parser.getName();
                    if ("default-restrictions".equals(childName)) {
                        final Bundle restrictions = UserRestrictionsUtils
                                .readRestrictions(XmlUtils.makeTyped(parser));
                        builder.setDefaultRestrictions(restrictions);
                    } else if (isProfile && "badge-labels".equals(childName)) {
                        setResAttributeArray(parser, builder::setBadgeLabels);
                    } else if (isProfile && "badge-colors".equals(childName)) {
                        setResAttributeArray(parser, builder::setBadgeColors);
                    } else if (isProfile && "badge-colors-dark".equals(childName)) {
                        setResAttributeArray(parser, builder::setDarkThemeBadgeColors);
                    } else if ("user-properties".equals(childName)) {
                        builder.getDefaultUserProperties()
                                .updateFromXml(XmlUtils.makeTyped(parser));
                    } else {
                        Slog.w(LOG_TAG, "Unrecognized tag " + childName + " in "
                                + parser.getPositionDescription());
                    }
                }
            }
        } catch (XmlPullParserException | IOException e) {
            Slog.w(LOG_TAG, "Cannot read user type configuration file.", e);
        }
    }

    /**
     * If the given attribute exists, gets the int stored in it and performs the given fcn using it.
     * The stored value must be an int or NumberFormatException will be thrown.
     *
     * @param parser xml parser from which to read the attribute
     * @param attributeName name of the attribute
     * @param fcn one-int-argument function,
     *            like {@link UserTypeDetails.Builder#setMaxAllowedPerParent(int)}
     */
    private static void setIntAttribute(XmlResourceParser parser, String attributeName,
            Consumer<Integer> fcn) {
        final String intValue = parser.getAttributeValue(null, attributeName);
        if (intValue == null) {
            return;
        }
        try {
            fcn.accept(Integer.parseInt(intValue));
        } catch (NumberFormatException e) {
            Slog.e(LOG_TAG, "Cannot parse value of '" + intValue + "' for " + attributeName
                    + " in " + parser.getPositionDescription(), e);
            throw e;
        }
    }

    /**
     * If the given attribute exists, gets the resId stored in it (or 0 if it is not a valid resId)
     * and performs the given fcn using it.
     *
     * @param parser xml parser from which to read the attribute
     * @param attributeName name of the attribute
     * @param fcn one-argument function, like {@link UserTypeDetails.Builder#setIconBadge(int)}
     */
    private static void setResAttribute(XmlResourceParser parser, String attributeName,
            Consumer<Integer> fcn) {
        if (parser.getAttributeValue(null, attributeName) == null) {
            // Attribute is not present, i.e. use the default value.
            return;
        }
        final int resId = parser.getAttributeResourceValue(null, attributeName, Resources.ID_NULL);
        fcn.accept(resId);
    }

    /**
     * Gets the resIds stored in "item" elements (in their "res" attribute) at the current depth.
     * Then performs the given fcn using the int[] array of these resIds.
     * <p>
     * Each xml element is expected to be of the form {@code <item res="someResValue" />}.
     *
     * @param parser xml parser from which to read the elements and their attributes
     * @param fcn function, like {@link UserTypeDetails.Builder#setBadgeColors(int...)}
     */
    private static void setResAttributeArray(XmlResourceParser parser, Consumer<int[]> fcn)
            throws IOException, XmlPullParserException {

        ArrayList<Integer> resList = new ArrayList<>();
        final int depth = parser.getDepth();
        while (XmlUtils.nextElementWithin(parser, depth)) {
            final String elementName = parser.getName();
            if (!"item".equals(elementName)) {
                Slog.w(LOG_TAG, "Skipping unknown child element " + elementName + " in "
                        + parser.getPositionDescription());
                XmlUtils.skipCurrentTag(parser);
                continue;
            }
            final int resId = parser.getAttributeResourceValue(null, "res", -1);
            if (resId == -1) {
                continue;
            }
            resList.add(resId);
        }

        int[] result = new int[resList.size()];
        for (int i = 0; i < resList.size(); i++) {
            result[i] = resList.get(i);
        }
        fcn.accept(result);
    }

    /**
     * Returns the user type version of the config XML file.
     * @return user type version defined in XML file, 0 if none.
     */
    public static int getUserTypeVersion() {
        try (XmlResourceParser parser =
                     Resources.getSystem().getXml(com.android.internal.R.xml.config_user_types)) {
            return getUserTypeVersion(parser);
        }
    }

    @VisibleForTesting
    static int getUserTypeVersion(XmlResourceParser parser) {
        int version = 0;

        try {
            XmlUtils.beginDocument(parser, "user-types");
            String versionValue = parser.getAttributeValue(null, "version");
            if (versionValue != null) {
                try {
                    version = Integer.parseInt(versionValue);
                } catch (NumberFormatException e) {
                    Slog.e(LOG_TAG, "Cannot parse value of '" + versionValue + "' for version in "
                            + parser.getPositionDescription(), e);
                    throw e;
                }
            }
        } catch (XmlPullParserException | IOException e) {
            Slog.w(LOG_TAG, "Cannot read user type configuration file.", e);
        }

        return version;
    }

    /**
     * Obtains the user type upgrades for this device.
     * @return The list of user type upgrades.
     */
    public static List<UserTypeUpgrade> getUserTypeUpgrades() {
        final List<UserTypeUpgrade> userUpgrades;
        try (XmlResourceParser parser =
                     Resources.getSystem().getXml(com.android.internal.R.xml.config_user_types)) {
            userUpgrades = parseUserUpgrades(getDefaultBuilders(), parser);
        }
        return userUpgrades;
    }

    @VisibleForTesting
    static List<UserTypeUpgrade> parseUserUpgrades(
            ArrayMap<String, UserTypeDetails.Builder> builders, XmlResourceParser parser) {
        final List<UserTypeUpgrade> userUpgrades = new ArrayList<>();

        try {
            XmlUtils.beginDocument(parser, "user-types");
            for (XmlUtils.nextElement(parser);
                    parser.getEventType() != XmlResourceParser.END_DOCUMENT;
                    XmlUtils.nextElement(parser)) {
                final String elementName = parser.getName();
                if ("change-user-type".equals(elementName)) {
                    final String fromType = parser.getAttributeValue(null, "from");
                    final String toType = parser.getAttributeValue(null, "to");
                    // Check that the base type doesn't change.
                    // Currently, only the base type of PROFILE is supported.
                    validateUserTypeIsProfile(fromType, builders);
                    validateUserTypeIsProfile(toType, builders);

                    final int maxVersionToConvert;
                    try {
                        maxVersionToConvert = Integer.parseInt(
                                parser.getAttributeValue(null, "whenVersionLeq"));
                    } catch (NumberFormatException e) {
                        Slog.e(LOG_TAG, "Cannot parse value of whenVersionLeq in "
                                + parser.getPositionDescription(), e);
                        throw e;
                    }

                    UserTypeUpgrade userTypeUpgrade = new UserTypeUpgrade(fromType, toType,
                            maxVersionToConvert);
                    userUpgrades.add(userTypeUpgrade);
                    continue;
                } else {
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
            }
        } catch (XmlPullParserException | IOException e) {
            Slog.w(LOG_TAG, "Cannot read user type configuration file.", e);
        }

        return userUpgrades;
    }

    private static void validateUserTypeIsProfile(String userType,
            ArrayMap<String, UserTypeDetails.Builder> builders) {
        UserTypeDetails.Builder builder = builders.get(userType);
        if (builder != null && builder.getBaseType() != FLAG_PROFILE) {
            throw new IllegalArgumentException("Illegal upgrade of user type " + userType
                    + " : Can only upgrade profiles user types");
        }
    }

    /**
     * Contains details required for an upgrade operation for {@link UserTypeDetails};
     */
    public static class UserTypeUpgrade {
        private final String mFromType;
        private final String mToType;
        private final int mUpToVersion;

        public UserTypeUpgrade(String fromType, String toType, int upToVersion) {
            mFromType = fromType;
            mToType = toType;
            mUpToVersion = upToVersion;
        }

        public String getFromType() {
            return mFromType;
        }

        public String getToType() {
            return mToType;
        }

        public int getUpToVersion() {
            return mUpToVersion;
        }
    }
}
