Loading api/current.txt +7 −1 Original line number Diff line number Diff line Loading @@ -9663,12 +9663,14 @@ package android.content.res { method public int diff(android.content.res.Configuration); method public boolean equals(android.content.res.Configuration); method public int getLayoutDirection(); method public android.util.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); method public boolean isScreenRound(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); method public void setLocale(java.util.Locale); method public void setLocales(android.util.LocaleList); method public void setTo(android.content.res.Configuration); method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); Loading Loading @@ -9742,7 +9744,7 @@ package android.content.res { field public int hardKeyboardHidden; field public int keyboard; field public int keyboardHidden; field public java.util.Locale locale; field public deprecated java.util.Locale locale; field public int mcc; field public int mnc; field public int navigation; Loading Loading @@ -34201,11 +34203,15 @@ package android.util { public final class LocaleList { ctor public LocaleList(); ctor public LocaleList(java.util.Locale); ctor public LocaleList(java.util.Locale[]); method public static android.util.LocaleList forLanguageTags(java.lang.String); method public java.util.Locale get(int); method public static android.util.LocaleList getEmptyLocaleList(); method public java.util.Locale getPrimary(); method public boolean isEmpty(); method public int size(); method public java.lang.String toLanguageTags(); } public final class Log { api/system-current.txt +7 −1 Original line number Diff line number Diff line Loading @@ -10000,12 +10000,14 @@ package android.content.res { method public int diff(android.content.res.Configuration); method public boolean equals(android.content.res.Configuration); method public int getLayoutDirection(); method public android.util.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); method public boolean isScreenRound(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); method public void setLocale(java.util.Locale); method public void setLocales(android.util.LocaleList); method public void setTo(android.content.res.Configuration); method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); Loading Loading @@ -10079,7 +10081,7 @@ package android.content.res { field public int hardKeyboardHidden; field public int keyboard; field public int keyboardHidden; field public java.util.Locale locale; field public deprecated java.util.Locale locale; field public int mcc; field public int mnc; field public int navigation; Loading Loading @@ -36495,11 +36497,15 @@ package android.util { public final class LocaleList { ctor public LocaleList(); ctor public LocaleList(java.util.Locale); ctor public LocaleList(java.util.Locale[]); method public static android.util.LocaleList forLanguageTags(java.lang.String); method public java.util.Locale get(int); method public static android.util.LocaleList getEmptyLocaleList(); method public java.util.Locale getPrimary(); method public boolean isEmpty(); method public int size(); method public java.lang.String toLanguageTags(); } public final class Log { core/java/android/content/res/Configuration.java +146 −64 Original line number Diff line number Diff line Loading @@ -22,11 +22,13 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.annotation.Nullable; import android.content.pm.ActivityInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.LocaleList; import android.view.View; import java.io.IOException; Loading @@ -36,7 +38,7 @@ import java.util.Locale; /** * This class describes all device configuration information that can * impact the resources the application retrieves. This includes both * user-specified configuration options (locale and scaling) as well * user-specified configuration options (locale list and scaling) as well * as device configurations (such as input modes, screen size and screen orientation). * <p>You can acquire this object from {@link Resources}, using {@link * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request Loading Loading @@ -78,8 +80,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration * Current user preference for the locale, corresponding to * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a> * resource qualifier. * * @deprecated Do not set or read this directly. Use {@link #getLocales()} and * {@link #setLocales(LocaleList)}. */ public Locale locale; @Deprecated public Locale locale; private LocaleList mLocaleList; /** * Locale should persist on setting. This is hidden because it is really Loading Loading @@ -648,6 +655,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration setTo(o); } /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know * about setLocales() has changed locale directly. */ private void fixUpLocaleList() { if ((locale == null && !mLocaleList.isEmpty()) || (locale != null && !locale.equals(mLocaleList.getPrimary()))) { mLocaleList = new LocaleList(locale); } } public void setTo(Configuration o) { fontScale = o.fontScale; mcc = o.mcc; Loading @@ -655,6 +671,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (o.locale != null) { locale = (Locale) o.locale.clone(); } o.fixUpLocaleList(); mLocaleList = o.mLocaleList; userSetLocale = o.userSetLocale; touchscreen = o.touchscreen; keyboard = o.keyboard; Loading Loading @@ -692,11 +710,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration } else { sb.append("?mnc"); } if (locale != null) { fixUpLocaleList(); if (!mLocaleList.isEmpty()) { sb.append(" "); sb.append(locale); sb.append(mLocaleList); } else { sb.append(" ?locale"); sb.append(" ?localeList"); } int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK); switch (layoutDir) { Loading Loading @@ -819,6 +838,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration public void setToDefaults() { fontScale = 1; mcc = mnc = 0; mLocaleList = LocaleList.getEmptyLocaleList(); locale = null; userSetLocale = false; touchscreen = TOUCHSCREEN_UNDEFINED; Loading Loading @@ -864,17 +884,21 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_MNC; mnc = delta.mnc; } if (delta.locale != null && (locale == null || !locale.equals(delta.locale))) { fixUpLocaleList(); delta.fixUpLocaleList(); if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) { changed |= ActivityInfo.CONFIG_LOCALE; locale = delta.locale != null ? (Locale) delta.locale.clone() : null; mLocaleList = delta.mLocaleList; // delta.locale can't be null, since delta.mLocaleList is not empty. if (!delta.locale.equals(locale)) { locale = (Locale) delta.locale.clone(); // If locale has changed, then layout direction is also changed ... changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; // ... and we need to update the layout direction (represented by the first // 2 most significant bits in screenLayout). setLayoutDirection(locale); } } final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { Loading Loading @@ -1023,8 +1047,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (delta.mnc != 0 && mnc != delta.mnc) { changed |= ActivityInfo.CONFIG_MNC; } if (delta.locale != null && (locale == null || !locale.equals(delta.locale))) { fixUpLocaleList(); delta.fixUpLocaleList(); if (!mLocaleList.equals(delta.mLocaleList)) { changed |= ActivityInfo.CONFIG_LOCALE; changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; } Loading Loading @@ -1146,14 +1171,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeFloat(fontScale); dest.writeInt(mcc); dest.writeInt(mnc); if (locale == null) { dest.writeInt(0); } else { dest.writeInt(1); dest.writeString(locale.getLanguage()); dest.writeString(locale.getCountry()); dest.writeString(locale.getVariant()); fixUpLocaleList(); final int localeListSize = mLocaleList.size(); dest.writeInt(localeListSize); for (int i = 0; i < localeListSize; ++i) { final Locale l = mLocaleList.get(i); dest.writeString(l.toLanguageTag()); } if(userSetLocale) { dest.writeInt(1); } else { Loading Loading @@ -1182,10 +1208,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration fontScale = source.readFloat(); mcc = source.readInt(); mnc = source.readInt(); if (source.readInt() != 0) { locale = new Locale(source.readString(), source.readString(), source.readString()); final int localeListSize = source.readInt(); final Locale[] localeArray = new Locale[localeListSize]; for (int i = 0; i < localeListSize; ++i) { localeArray[i] = Locale.forLanguageTag(source.readString()); } mLocaleList = new LocaleList(localeArray); locale = mLocaleList.getPrimary(); userSetLocale = (source.readInt()==1); touchscreen = source.readInt(); keyboard = source.readInt(); Loading Loading @@ -1234,18 +1265,33 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (n != 0) return n; n = this.mnc - that.mnc; if (n != 0) return n; if (this.locale == null) { if (that.locale != null) return 1; } else if (that.locale == null) { fixUpLocaleList(); that.fixUpLocaleList(); // for backward compatibility, we consider an empty locale list to be greater // than any non-empty locale list. if (this.mLocaleList.isEmpty()) { if (!that.mLocaleList.isEmpty()) return 1; } else if (that.mLocaleList.isEmpty()) { return -1; } else { n = this.locale.getLanguage().compareTo(that.locale.getLanguage()); final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size()); for (int i = 0; i < minSize; ++i) { final Locale thisLocale = this.mLocaleList.get(i); final Locale thatLocale = that.mLocaleList.get(i); n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage()); if (n != 0) return n; n = this.locale.getCountry().compareTo(that.locale.getCountry()); n = thisLocale.getCountry().compareTo(thatLocale.getCountry()); if (n != 0) return n; n = this.locale.getVariant().compareTo(that.locale.getVariant()); n = thisLocale.getVariant().compareTo(thatLocale.getVariant()); if (n != 0) return n; n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag()); if (n != 0) return n; } n = this.mLocaleList.size() - that.mLocaleList.size(); if (n != 0) return n; } n = this.touchscreen - that.touchscreen; if (n != 0) return n; n = this.keyboard - that.keyboard; Loading Loading @@ -1294,7 +1340,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration result = 31 * result + Float.floatToIntBits(fontScale); result = 31 * result + mcc; result = 31 * result + mnc; result = 31 * result + (locale != null ? locale.hashCode() : 0); result = 31 * result + mLocaleList.hashCode(); result = 31 * result + touchscreen; result = 31 * result + keyboard; result = 31 * result + keyboardHidden; Loading @@ -1312,16 +1358,49 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** * Set the locale. This is the preferred way for setting up the locale (instead of using the * direct accessor). This will also set the layout direction according to the locale. * Get the locale list. This is the preferred way for getting the locales (instead of using * the direct accessor to {@link #locale}, which would only provide the primary locale). * * @param loc The locale. Can be null. * @return The locale list. */ public void setLocale(Locale loc) { locale = loc; public LocaleList getLocales() { fixUpLocaleList(); return mLocaleList; } /** * Set the locale list. This is the preferred way for setting up the locales (instead of using * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction * according to the first locale in the list. * * Note that the layout direction will always come from the first locale in the locale list, * even if the locale is not supported by the resources (the resources may only support * another locale further down the list which has a different direction). * * @param locales The locale list. If null, an empty LocaleList will be assigned. */ public void setLocales(@Nullable LocaleList locales) { mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales; locale = mLocaleList.getPrimary(); setLayoutDirection(locale); } /** * Set the locale list to a list of just one locale. This will also set the layout direction * according to the locale. * * Note that after this is run, calling <code>.equals()</code> on the input locale and the * {@link #locale} attribute would return <code>true</code> if they are not null, but there is * no guarantee that they would be the same object. * * See also the note about layout direction in {@link #setLocales(LocaleList)}. * * @param loc The locale. Can be null. */ public void setLocale(@Nullable Locale loc) { setLocales(new LocaleList(loc)); } /** * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or * {@link View#LAYOUT_DIRECTION_RTL}. Loading @@ -1335,19 +1414,19 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** * Set the layout direction from the Locale. * Set the layout direction from a Locale. * * @param locale The Locale. If null will set the layout direction to * @param loc The Locale. If null will set the layout direction to * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction * corresponding to the Locale. * * @see View#LAYOUT_DIRECTION_LTR * @see View#LAYOUT_DIRECTION_RTL */ public void setLayoutDirection(Locale locale) { public void setLayoutDirection(Locale loc) { // There is a "1" difference between the configuration values for // layout direction and View constants for layout direction, just add "1". final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(locale); final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc); screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)| (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT); } Loading @@ -1370,21 +1449,21 @@ public final class Configuration implements Parcelable, Comparable<Configuration * * @hide */ public static String localeToResourceQualifier(Locale locale) { public static String localeToResourceQualifier(Locale loc) { StringBuilder sb = new StringBuilder(); boolean l = (locale.getLanguage().length() != 0); boolean c = (locale.getCountry().length() != 0); boolean s = (locale.getScript().length() != 0); boolean v = (locale.getVariant().length() != 0); boolean l = (loc.getLanguage().length() != 0); boolean c = (loc.getCountry().length() != 0); boolean s = (loc.getScript().length() != 0); boolean v = (loc.getVariant().length() != 0); // TODO: take script and extensions into account if (l) { sb.append(locale.getLanguage()); sb.append(loc.getLanguage()); if (c) { sb.append("-r").append(locale.getCountry()); sb.append("-r").append(loc.getCountry()); if (s) { sb.append("-s").append(locale.getScript()); sb.append("-s").append(loc.getScript()); if (v) { sb.append("-v").append(locale.getVariant()); sb.append("-v").append(loc.getVariant()); } } } Loading @@ -1409,6 +1488,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration } } // TODO: send the whole locale list if (config.locale != null && !config.locale.getLanguage().isEmpty()) { parts.add(localeToResourceQualifier(config.locale)); } Loading Loading @@ -1646,8 +1726,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration delta.mnc = change.mnc; } if ((base.locale == null && change.locale != null) || (base.locale != null && !base.locale.equals(change.locale))) { base.fixUpLocaleList(); change.fixUpLocaleList(); if (!base.mLocaleList.equals(change.mLocaleList)) { delta.mLocaleList = change.mLocaleList; delta.locale = change.locale; } Loading Loading @@ -1724,7 +1806,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration private static final String XML_ATTR_FONT_SCALE = "fs"; private static final String XML_ATTR_MCC = "mcc"; private static final String XML_ATTR_MNC = "mnc"; private static final String XML_ATTR_LOCALE = "locale"; private static final String XML_ATTR_LOCALES = "locales"; private static final String XML_ATTR_TOUCHSCREEN = "touch"; private static final String XML_ATTR_KEYBOARD = "key"; private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid"; Loading Loading @@ -1754,10 +1836,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0); configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0); final String localeStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALE); if (localeStr != null) { configOut.locale = Locale.forLanguageTag(localeStr); } final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES); configOut.mLocaleList = LocaleList.forLanguageTags(localesStr); configOut.locale = configOut.mLocaleList.getPrimary(); configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN, TOUCHSCREEN_UNDEFINED); Loading Loading @@ -1807,8 +1888,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (config.mnc != 0) { XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc); } if (config.locale != null) { XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALE, config.locale.toLanguageTag()); config.fixUpLocaleList(); if (!config.mLocaleList.isEmpty()) { XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags()); } if (config.touchscreen != TOUCHSCREEN_UNDEFINED) { XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen); Loading core/java/android/util/LocaleList.java +87 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ import java.util.Locale; // TODO: We don't except too many LocaleLists to exist at the same time, and // we need access to the data at native level, so we should pass the data // down to the native level, create a mapt of every list seen there, take a // pointer back, and just keep that pointed in the Java-level object, so // down to the native level, create a map of every list seen there, take a // pointer back, and just keep that pointer in the Java-level object, so // things could be copied very quickly. /** Loading @@ -34,6 +34,7 @@ import java.util.Locale; public final class LocaleList { private final Locale[] mList; private static final Locale[] sEmptyList = new Locale[0]; private static final LocaleList sEmptyLocaleList = new LocaleList(); public Locale get(int location) { return location < mList.length ? mList[location] : null; Loading @@ -51,10 +52,77 @@ public final class LocaleList { return mList.length; } @Override public boolean equals(Object other) { if (other == this) return true; if (!(other instanceof LocaleList)) return false; final Locale[] otherList = ((LocaleList) other).mList; if (mList.length != otherList.length) return false; for (int i = 0; i < mList.length; ++i) { if (!mList[i].equals(otherList[i])) return false; } return true; } @Override public int hashCode() { int result = 1; for (int i = 0; i < mList.length; ++i) { result = 31 * result + mList[i].hashCode(); } return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < mList.length; ++i) { sb.append(mList[i]); if (i < mList.length - 1) { sb.append(','); } } sb.append("]"); return sb.toString(); } public String toLanguageTags() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < mList.length; ++i) { sb.append(mList[i].toLanguageTag()); if (i < mList.length - 1) { sb.append(','); } } return sb.toString(); } /** * It is almost always better to call {@link #getEmptyLocaleList()} instead which returns * a pre-constructed empty locale list. */ public LocaleList() { mList = sEmptyList; } /** * @throws NullPointerException if any of the input locales is <code>null</code>. * @throws IllegalArgumentException if any of the input locales repeat. */ public LocaleList(@Nullable Locale locale) { if (locale == null) { mList = sEmptyList; } else { mList = new Locale[1]; mList[0] = (Locale) locale.clone(); } } /** * @throws NullPointerException if any of the input locales is <code>null</code>. * @throws IllegalArgumentException if any of the input locales repeat. Loading @@ -79,4 +147,21 @@ public final class LocaleList { mList = localeList; } } public static LocaleList getEmptyLocaleList() { return sEmptyLocaleList; } public static LocaleList forLanguageTags(@Nullable String list) { if (list == null || list.equals("")) { return getEmptyLocaleList(); } else { final String[] tags = list.split(","); final Locale[] localeArray = new Locale[tags.length]; for (int i = 0; i < localeArray.length; ++i) { localeArray[i] = Locale.forLanguageTag(tags[i]); } return new LocaleList(localeArray); } } } Loading
api/current.txt +7 −1 Original line number Diff line number Diff line Loading @@ -9663,12 +9663,14 @@ package android.content.res { method public int diff(android.content.res.Configuration); method public boolean equals(android.content.res.Configuration); method public int getLayoutDirection(); method public android.util.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); method public boolean isScreenRound(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); method public void setLocale(java.util.Locale); method public void setLocales(android.util.LocaleList); method public void setTo(android.content.res.Configuration); method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); Loading Loading @@ -9742,7 +9744,7 @@ package android.content.res { field public int hardKeyboardHidden; field public int keyboard; field public int keyboardHidden; field public java.util.Locale locale; field public deprecated java.util.Locale locale; field public int mcc; field public int mnc; field public int navigation; Loading Loading @@ -34201,11 +34203,15 @@ package android.util { public final class LocaleList { ctor public LocaleList(); ctor public LocaleList(java.util.Locale); ctor public LocaleList(java.util.Locale[]); method public static android.util.LocaleList forLanguageTags(java.lang.String); method public java.util.Locale get(int); method public static android.util.LocaleList getEmptyLocaleList(); method public java.util.Locale getPrimary(); method public boolean isEmpty(); method public int size(); method public java.lang.String toLanguageTags(); } public final class Log {
api/system-current.txt +7 −1 Original line number Diff line number Diff line Loading @@ -10000,12 +10000,14 @@ package android.content.res { method public int diff(android.content.res.Configuration); method public boolean equals(android.content.res.Configuration); method public int getLayoutDirection(); method public android.util.LocaleList getLocales(); method public boolean isLayoutSizeAtLeast(int); method public boolean isScreenRound(); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); method public void setLayoutDirection(java.util.Locale); method public void setLocale(java.util.Locale); method public void setLocales(android.util.LocaleList); method public void setTo(android.content.res.Configuration); method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); Loading Loading @@ -10079,7 +10081,7 @@ package android.content.res { field public int hardKeyboardHidden; field public int keyboard; field public int keyboardHidden; field public java.util.Locale locale; field public deprecated java.util.Locale locale; field public int mcc; field public int mnc; field public int navigation; Loading Loading @@ -36495,11 +36497,15 @@ package android.util { public final class LocaleList { ctor public LocaleList(); ctor public LocaleList(java.util.Locale); ctor public LocaleList(java.util.Locale[]); method public static android.util.LocaleList forLanguageTags(java.lang.String); method public java.util.Locale get(int); method public static android.util.LocaleList getEmptyLocaleList(); method public java.util.Locale getPrimary(); method public boolean isEmpty(); method public int size(); method public java.lang.String toLanguageTags(); } public final class Log {
core/java/android/content/res/Configuration.java +146 −64 Original line number Diff line number Diff line Loading @@ -22,11 +22,13 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.annotation.Nullable; import android.content.pm.ActivityInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.LocaleList; import android.view.View; import java.io.IOException; Loading @@ -36,7 +38,7 @@ import java.util.Locale; /** * This class describes all device configuration information that can * impact the resources the application retrieves. This includes both * user-specified configuration options (locale and scaling) as well * user-specified configuration options (locale list and scaling) as well * as device configurations (such as input modes, screen size and screen orientation). * <p>You can acquire this object from {@link Resources}, using {@link * Resources#getConfiguration}. Thus, from an activity, you can get it by chaining the request Loading Loading @@ -78,8 +80,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration * Current user preference for the locale, corresponding to * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a> * resource qualifier. * * @deprecated Do not set or read this directly. Use {@link #getLocales()} and * {@link #setLocales(LocaleList)}. */ public Locale locale; @Deprecated public Locale locale; private LocaleList mLocaleList; /** * Locale should persist on setting. This is hidden because it is really Loading Loading @@ -648,6 +655,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration setTo(o); } /* This brings mLocaleList in sync with locale in case a user of the older API who doesn't know * about setLocales() has changed locale directly. */ private void fixUpLocaleList() { if ((locale == null && !mLocaleList.isEmpty()) || (locale != null && !locale.equals(mLocaleList.getPrimary()))) { mLocaleList = new LocaleList(locale); } } public void setTo(Configuration o) { fontScale = o.fontScale; mcc = o.mcc; Loading @@ -655,6 +671,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (o.locale != null) { locale = (Locale) o.locale.clone(); } o.fixUpLocaleList(); mLocaleList = o.mLocaleList; userSetLocale = o.userSetLocale; touchscreen = o.touchscreen; keyboard = o.keyboard; Loading Loading @@ -692,11 +710,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration } else { sb.append("?mnc"); } if (locale != null) { fixUpLocaleList(); if (!mLocaleList.isEmpty()) { sb.append(" "); sb.append(locale); sb.append(mLocaleList); } else { sb.append(" ?locale"); sb.append(" ?localeList"); } int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK); switch (layoutDir) { Loading Loading @@ -819,6 +838,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration public void setToDefaults() { fontScale = 1; mcc = mnc = 0; mLocaleList = LocaleList.getEmptyLocaleList(); locale = null; userSetLocale = false; touchscreen = TOUCHSCREEN_UNDEFINED; Loading Loading @@ -864,17 +884,21 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_MNC; mnc = delta.mnc; } if (delta.locale != null && (locale == null || !locale.equals(delta.locale))) { fixUpLocaleList(); delta.fixUpLocaleList(); if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) { changed |= ActivityInfo.CONFIG_LOCALE; locale = delta.locale != null ? (Locale) delta.locale.clone() : null; mLocaleList = delta.mLocaleList; // delta.locale can't be null, since delta.mLocaleList is not empty. if (!delta.locale.equals(locale)) { locale = (Locale) delta.locale.clone(); // If locale has changed, then layout direction is also changed ... changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; // ... and we need to update the layout direction (represented by the first // 2 most significant bits in screenLayout). setLayoutDirection(locale); } } final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK; if (deltaScreenLayoutDir != SCREENLAYOUT_LAYOUTDIR_UNDEFINED && deltaScreenLayoutDir != (screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) { Loading Loading @@ -1023,8 +1047,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (delta.mnc != 0 && mnc != delta.mnc) { changed |= ActivityInfo.CONFIG_MNC; } if (delta.locale != null && (locale == null || !locale.equals(delta.locale))) { fixUpLocaleList(); delta.fixUpLocaleList(); if (!mLocaleList.equals(delta.mLocaleList)) { changed |= ActivityInfo.CONFIG_LOCALE; changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; } Loading Loading @@ -1146,14 +1171,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeFloat(fontScale); dest.writeInt(mcc); dest.writeInt(mnc); if (locale == null) { dest.writeInt(0); } else { dest.writeInt(1); dest.writeString(locale.getLanguage()); dest.writeString(locale.getCountry()); dest.writeString(locale.getVariant()); fixUpLocaleList(); final int localeListSize = mLocaleList.size(); dest.writeInt(localeListSize); for (int i = 0; i < localeListSize; ++i) { final Locale l = mLocaleList.get(i); dest.writeString(l.toLanguageTag()); } if(userSetLocale) { dest.writeInt(1); } else { Loading Loading @@ -1182,10 +1208,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration fontScale = source.readFloat(); mcc = source.readInt(); mnc = source.readInt(); if (source.readInt() != 0) { locale = new Locale(source.readString(), source.readString(), source.readString()); final int localeListSize = source.readInt(); final Locale[] localeArray = new Locale[localeListSize]; for (int i = 0; i < localeListSize; ++i) { localeArray[i] = Locale.forLanguageTag(source.readString()); } mLocaleList = new LocaleList(localeArray); locale = mLocaleList.getPrimary(); userSetLocale = (source.readInt()==1); touchscreen = source.readInt(); keyboard = source.readInt(); Loading Loading @@ -1234,18 +1265,33 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (n != 0) return n; n = this.mnc - that.mnc; if (n != 0) return n; if (this.locale == null) { if (that.locale != null) return 1; } else if (that.locale == null) { fixUpLocaleList(); that.fixUpLocaleList(); // for backward compatibility, we consider an empty locale list to be greater // than any non-empty locale list. if (this.mLocaleList.isEmpty()) { if (!that.mLocaleList.isEmpty()) return 1; } else if (that.mLocaleList.isEmpty()) { return -1; } else { n = this.locale.getLanguage().compareTo(that.locale.getLanguage()); final int minSize = Math.min(this.mLocaleList.size(), that.mLocaleList.size()); for (int i = 0; i < minSize; ++i) { final Locale thisLocale = this.mLocaleList.get(i); final Locale thatLocale = that.mLocaleList.get(i); n = thisLocale.getLanguage().compareTo(thatLocale.getLanguage()); if (n != 0) return n; n = this.locale.getCountry().compareTo(that.locale.getCountry()); n = thisLocale.getCountry().compareTo(thatLocale.getCountry()); if (n != 0) return n; n = this.locale.getVariant().compareTo(that.locale.getVariant()); n = thisLocale.getVariant().compareTo(thatLocale.getVariant()); if (n != 0) return n; n = thisLocale.toLanguageTag().compareTo(thatLocale.toLanguageTag()); if (n != 0) return n; } n = this.mLocaleList.size() - that.mLocaleList.size(); if (n != 0) return n; } n = this.touchscreen - that.touchscreen; if (n != 0) return n; n = this.keyboard - that.keyboard; Loading Loading @@ -1294,7 +1340,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration result = 31 * result + Float.floatToIntBits(fontScale); result = 31 * result + mcc; result = 31 * result + mnc; result = 31 * result + (locale != null ? locale.hashCode() : 0); result = 31 * result + mLocaleList.hashCode(); result = 31 * result + touchscreen; result = 31 * result + keyboard; result = 31 * result + keyboardHidden; Loading @@ -1312,16 +1358,49 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** * Set the locale. This is the preferred way for setting up the locale (instead of using the * direct accessor). This will also set the layout direction according to the locale. * Get the locale list. This is the preferred way for getting the locales (instead of using * the direct accessor to {@link #locale}, which would only provide the primary locale). * * @param loc The locale. Can be null. * @return The locale list. */ public void setLocale(Locale loc) { locale = loc; public LocaleList getLocales() { fixUpLocaleList(); return mLocaleList; } /** * Set the locale list. This is the preferred way for setting up the locales (instead of using * the direct accessor or {@link #setLocale(Locale)}). This will also set the layout direction * according to the first locale in the list. * * Note that the layout direction will always come from the first locale in the locale list, * even if the locale is not supported by the resources (the resources may only support * another locale further down the list which has a different direction). * * @param locales The locale list. If null, an empty LocaleList will be assigned. */ public void setLocales(@Nullable LocaleList locales) { mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales; locale = mLocaleList.getPrimary(); setLayoutDirection(locale); } /** * Set the locale list to a list of just one locale. This will also set the layout direction * according to the locale. * * Note that after this is run, calling <code>.equals()</code> on the input locale and the * {@link #locale} attribute would return <code>true</code> if they are not null, but there is * no guarantee that they would be the same object. * * See also the note about layout direction in {@link #setLocales(LocaleList)}. * * @param loc The locale. Can be null. */ public void setLocale(@Nullable Locale loc) { setLocales(new LocaleList(loc)); } /** * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or * {@link View#LAYOUT_DIRECTION_RTL}. Loading @@ -1335,19 +1414,19 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** * Set the layout direction from the Locale. * Set the layout direction from a Locale. * * @param locale The Locale. If null will set the layout direction to * @param loc The Locale. If null will set the layout direction to * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction * corresponding to the Locale. * * @see View#LAYOUT_DIRECTION_LTR * @see View#LAYOUT_DIRECTION_RTL */ public void setLayoutDirection(Locale locale) { public void setLayoutDirection(Locale loc) { // There is a "1" difference between the configuration values for // layout direction and View constants for layout direction, just add "1". final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(locale); final int layoutDirection = 1 + TextUtils.getLayoutDirectionFromLocale(loc); screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)| (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT); } Loading @@ -1370,21 +1449,21 @@ public final class Configuration implements Parcelable, Comparable<Configuration * * @hide */ public static String localeToResourceQualifier(Locale locale) { public static String localeToResourceQualifier(Locale loc) { StringBuilder sb = new StringBuilder(); boolean l = (locale.getLanguage().length() != 0); boolean c = (locale.getCountry().length() != 0); boolean s = (locale.getScript().length() != 0); boolean v = (locale.getVariant().length() != 0); boolean l = (loc.getLanguage().length() != 0); boolean c = (loc.getCountry().length() != 0); boolean s = (loc.getScript().length() != 0); boolean v = (loc.getVariant().length() != 0); // TODO: take script and extensions into account if (l) { sb.append(locale.getLanguage()); sb.append(loc.getLanguage()); if (c) { sb.append("-r").append(locale.getCountry()); sb.append("-r").append(loc.getCountry()); if (s) { sb.append("-s").append(locale.getScript()); sb.append("-s").append(loc.getScript()); if (v) { sb.append("-v").append(locale.getVariant()); sb.append("-v").append(loc.getVariant()); } } } Loading @@ -1409,6 +1488,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration } } // TODO: send the whole locale list if (config.locale != null && !config.locale.getLanguage().isEmpty()) { parts.add(localeToResourceQualifier(config.locale)); } Loading Loading @@ -1646,8 +1726,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration delta.mnc = change.mnc; } if ((base.locale == null && change.locale != null) || (base.locale != null && !base.locale.equals(change.locale))) { base.fixUpLocaleList(); change.fixUpLocaleList(); if (!base.mLocaleList.equals(change.mLocaleList)) { delta.mLocaleList = change.mLocaleList; delta.locale = change.locale; } Loading Loading @@ -1724,7 +1806,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration private static final String XML_ATTR_FONT_SCALE = "fs"; private static final String XML_ATTR_MCC = "mcc"; private static final String XML_ATTR_MNC = "mnc"; private static final String XML_ATTR_LOCALE = "locale"; private static final String XML_ATTR_LOCALES = "locales"; private static final String XML_ATTR_TOUCHSCREEN = "touch"; private static final String XML_ATTR_KEYBOARD = "key"; private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid"; Loading Loading @@ -1754,10 +1836,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0); configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0); final String localeStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALE); if (localeStr != null) { configOut.locale = Locale.forLanguageTag(localeStr); } final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES); configOut.mLocaleList = LocaleList.forLanguageTags(localesStr); configOut.locale = configOut.mLocaleList.getPrimary(); configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN, TOUCHSCREEN_UNDEFINED); Loading Loading @@ -1807,8 +1888,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (config.mnc != 0) { XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc); } if (config.locale != null) { XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALE, config.locale.toLanguageTag()); config.fixUpLocaleList(); if (!config.mLocaleList.isEmpty()) { XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALES, config.mLocaleList.toLanguageTags()); } if (config.touchscreen != TOUCHSCREEN_UNDEFINED) { XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen); Loading
core/java/android/util/LocaleList.java +87 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ import java.util.Locale; // TODO: We don't except too many LocaleLists to exist at the same time, and // we need access to the data at native level, so we should pass the data // down to the native level, create a mapt of every list seen there, take a // pointer back, and just keep that pointed in the Java-level object, so // down to the native level, create a map of every list seen there, take a // pointer back, and just keep that pointer in the Java-level object, so // things could be copied very quickly. /** Loading @@ -34,6 +34,7 @@ import java.util.Locale; public final class LocaleList { private final Locale[] mList; private static final Locale[] sEmptyList = new Locale[0]; private static final LocaleList sEmptyLocaleList = new LocaleList(); public Locale get(int location) { return location < mList.length ? mList[location] : null; Loading @@ -51,10 +52,77 @@ public final class LocaleList { return mList.length; } @Override public boolean equals(Object other) { if (other == this) return true; if (!(other instanceof LocaleList)) return false; final Locale[] otherList = ((LocaleList) other).mList; if (mList.length != otherList.length) return false; for (int i = 0; i < mList.length; ++i) { if (!mList[i].equals(otherList[i])) return false; } return true; } @Override public int hashCode() { int result = 1; for (int i = 0; i < mList.length; ++i) { result = 31 * result + mList[i].hashCode(); } return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < mList.length; ++i) { sb.append(mList[i]); if (i < mList.length - 1) { sb.append(','); } } sb.append("]"); return sb.toString(); } public String toLanguageTags() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < mList.length; ++i) { sb.append(mList[i].toLanguageTag()); if (i < mList.length - 1) { sb.append(','); } } return sb.toString(); } /** * It is almost always better to call {@link #getEmptyLocaleList()} instead which returns * a pre-constructed empty locale list. */ public LocaleList() { mList = sEmptyList; } /** * @throws NullPointerException if any of the input locales is <code>null</code>. * @throws IllegalArgumentException if any of the input locales repeat. */ public LocaleList(@Nullable Locale locale) { if (locale == null) { mList = sEmptyList; } else { mList = new Locale[1]; mList[0] = (Locale) locale.clone(); } } /** * @throws NullPointerException if any of the input locales is <code>null</code>. * @throws IllegalArgumentException if any of the input locales repeat. Loading @@ -79,4 +147,21 @@ public final class LocaleList { mList = localeList; } } public static LocaleList getEmptyLocaleList() { return sEmptyLocaleList; } public static LocaleList forLanguageTags(@Nullable String list) { if (list == null || list.equals("")) { return getEmptyLocaleList(); } else { final String[] tags = list.split(","); final Locale[] localeArray = new Locale[tags.length]; for (int i = 0; i < localeArray.length; ++i) { localeArray[i] = Locale.forLanguageTag(tags[i]); } return new LocaleList(localeArray); } } }