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

Commit 2ae6ed59 authored by Jeremy Meyer's avatar Jeremy Meyer
Browse files

Make resource multilocale depend on default attribute

Change-Id: I8ea32c3eee94435c4e2b6e6e1e09d30db50f268a
Test: Manual and automatic
Fixes: 117306409
parent 1d9c8003
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -668,6 +668,7 @@ package android {
    field public static final int debuggable = 16842767; // 0x101000f
    field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
    field public static final int defaultHeight = 16844021; // 0x10104f5
    field @FlaggedApi("android.content.res.default_locale") public static final int defaultLocale;
    field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
    field public static final int defaultValue = 16843245; // 0x10101ed
    field public static final int defaultWidth = 16844020; // 0x10104f4
@@ -6188,6 +6189,7 @@ package android.app {
    ctor public LocaleConfig(@NonNull android.os.LocaleList);
    method public int describeContents();
    method @NonNull public static android.app.LocaleConfig fromContextIgnoringOverride(@NonNull android.content.Context);
    method @FlaggedApi("android.content.res.default_locale") @Nullable public java.util.Locale getDefaultLocale();
    method public int getStatus();
    method @Nullable public android.os.LocaleList getSupportedLocales();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
+4 −6
Original line number Diff line number Diff line
@@ -3483,12 +3483,10 @@ class ContextImpl extends Context {

        // only do this if the user already has more than one preferred locale
        if (r.getConfiguration().getLocales().size() > 1) {
            LocaleConfig lc = LocaleConfig.fromContextIgnoringOverride(this);
            mResourcesManager.setLocaleList(lc != null
                    && lc.getSupportedLocales() != null
                    && !lc.getSupportedLocales().isEmpty()
                    ? lc.getSupportedLocales()
                    : null);
            LocaleConfig lc = getUserId() < 0
                    ? LocaleConfig.fromContextIgnoringOverride(this)
                    : new LocaleConfig(this);
            mResourcesManager.setLocaleConfig(lc);
        }
    }

+37 −3
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@

package android.app;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
@@ -31,6 +33,7 @@ import android.util.AttributeSet;
import android.util.Slog;
import android.util.Xml;

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

import org.xmlpull.v1.XmlPullParserException;
@@ -40,7 +43,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -67,6 +70,8 @@ public class LocaleConfig implements Parcelable {
    public static final String TAG_LOCALE_CONFIG = "locale-config";
    public static final String TAG_LOCALE = "locale";
    private LocaleList mLocales;

    private Locale mDefaultLocale;
    private int mStatus = STATUS_NOT_SPECIFIED;

    /**
@@ -195,8 +200,17 @@ public class LocaleConfig implements Parcelable {
        XmlUtils.beginDocument(parser, TAG_LOCALE_CONFIG);
        int outerDepth = parser.getDepth();
        AttributeSet attrs = Xml.asAttributeSet(parser);
        // LinkedHashSet to preserve insertion order
        Set<String> localeNames = new LinkedHashSet<>();

        String defaultLocale = null;
        if (android.content.res.Flags.defaultLocale()) {
            TypedArray att = res.obtainAttributes(
                    attrs, com.android.internal.R.styleable.LocaleConfig);
            defaultLocale = att.getString(
                    R.styleable.LocaleConfig_defaultLocale);
            att.recycle();
        }

        Set<String> localeNames = new HashSet<>();
        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
            if (TAG_LOCALE.equals(parser.getName())) {
                final TypedArray attributes = res.obtainAttributes(
@@ -211,6 +225,15 @@ public class LocaleConfig implements Parcelable {
        }
        mStatus = STATUS_SUCCESS;
        mLocales = LocaleList.forLanguageTags(String.join(",", localeNames));
        if (defaultLocale != null) {
            if (localeNames.contains(defaultLocale)) {
                mDefaultLocale = Locale.forLanguageTag(defaultLocale);
            } else {
                Slog.w(TAG, "Default locale specified that is not contained in the list: "
                        + defaultLocale);
                mStatus = STATUS_PARSING_FAILED;
            }
        }
    }

    /**
@@ -225,6 +248,17 @@ public class LocaleConfig implements Parcelable {
        return mLocales;
    }

    /**
     * Returns the default locale if specified, otherwise null
     *
     * @return The default Locale or null
     */
    @SuppressLint("UseIcu")
    @FlaggedApi(android.content.res.Flags.FLAG_DEFAULT_LOCALE)
    public @Nullable Locale getDefaultLocale() {
        return mDefaultLocale;
    }

    /**
     * Get the status of reading the resource file where the LocaleConfig was stored.
     *
+10 −9
Original line number Diff line number Diff line
@@ -120,9 +120,9 @@ public class ResourcesManager {
    private final ReferenceQueue<Resources> mResourcesReferencesQueue = new ReferenceQueue<>();

    /**
     * The list of locales the app declares it supports.
     * The localeConfig of the app.
     */
    private LocaleList mLocaleList = LocaleList.getEmptyLocaleList();
    private LocaleConfig mLocaleConfig = new LocaleConfig(LocaleList.getEmptyLocaleList());

    private static class ApkKey {
        public final String path;
@@ -1612,18 +1612,19 @@ public class ResourcesManager {
    }

    /**
     * Returns the LocaleList current set
     * Returns the LocaleConfig current set
     */
    public LocaleList getLocaleList() {
        return mLocaleList;
    public LocaleConfig getLocaleConfig() {
        return mLocaleConfig;
    }

    /**
     * Sets the LocaleList of app's supported locales
     * Sets the LocaleConfig of the app
     */
    public void setLocaleList(LocaleList localeList) {
        if ((localeList != null) && !localeList.isEmpty()) {
            mLocaleList = localeList;
    public void setLocaleConfig(LocaleConfig localeConfig) {
        if ((localeConfig != null) && (localeConfig.getSupportedLocales() != null)
                && !localeConfig.getSupportedLocales().isEmpty()) {
            mLocaleConfig = localeConfig;
        }
    }

+44 −21
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ import android.annotation.PluralsRes;
import android.annotation.RawRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
import android.app.LocaleConfig;
import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
@@ -426,8 +428,21 @@ public class ResourcesImpl {

                String[] selectedLocales = null;
                String defaultLocale = null;
                LocaleConfig lc = ResourcesManager.getInstance().getLocaleConfig();
                if ((configChanges & ActivityInfo.CONFIG_LOCALE) != 0) {
                    if (locales.size() > 1) {
                        if (Flags.defaultLocale() && (lc.getDefaultLocale() != null)) {
                            Locale[] intersection =
                                    locales.getIntersection(lc.getSupportedLocales());
                            mConfiguration.setLocales(new LocaleList(intersection));
                            selectedLocales = new String[intersection.length];
                            for (int i = 0; i < intersection.length; i++) {
                                selectedLocales[i] =
                                        adjustLanguageTag(intersection[i].toLanguageTag());
                            }
                            defaultLocale =
                                    adjustLanguageTag(lc.getDefaultLocale().toLanguageTag());
                        } else {
                            String[] availableLocales;
                            // The LocaleList has changed. We must query the AssetManager's
                            // available Locales and figure out the best matching Locale in the new
@@ -455,10 +470,18 @@ public class ResourcesImpl {
                            }
                        }
                    }
                }
                if (selectedLocales == null) {
                    if (Flags.defaultLocale() && (lc.getDefaultLocale() != null)) {
                        selectedLocales = new String[locales.size()];
                        for (int i = 0; i < locales.size(); i++) {
                            selectedLocales[i] = adjustLanguageTag(locales.get(i).toLanguageTag());
                        }
                    } else {
                        selectedLocales = new String[]{
                                adjustLanguageTag(locales.get(0).toLanguageTag())};
                    }
                }

                if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
                    mMetrics.densityDpi = mConfiguration.densityDpi;
Loading