Loading core/java/android/content/res/AssetManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -698,6 +698,18 @@ public final class AssetManager implements AutoCloseable { */ public native final String[] getLocales(); /** * Same as getLocales(), except that locales that are only provided by the system (i.e. those * present in framework-res.apk or its overlays) will not be listed. * * For example, if the "system" assets support English, French, and German, and the additional * assets support Cherokee and French, getLocales() would return * [Cherokee, English, French, German], while getNonSystemLocales() would return * [Cherokee, French]. * {@hide} */ public native final String[] getNonSystemLocales(); /** {@hide} */ public native final Configuration[] getSizeConfigurations(); Loading core/java/android/content/res/Resources.java +15 −1 Original line number Diff line number Diff line Loading @@ -1976,7 +1976,21 @@ public class Resources { if (setLocalesToDefault || mResolvedLocale == null || (configChanges & Configuration.NATIVE_CONFIG_LOCALE) != 0) { mResolvedLocale = locales.getFirstMatch(mAssets.getLocales()); if (locales.size() == 1) { // This is an optimization to avoid the JNI call(s) when the result of // getFirstMatch() does not depend on the supported locales. mResolvedLocale = locales.getPrimary(); } else { String[] supportedLocales = mAssets.getNonSystemLocales(); if (LocaleList.isPseudoLocalesOnly(supportedLocales)) { // We fallback to all locales (including system locales) if there was no // locale specifically supported by the assets. This is to properly support // apps that only rely on the shared system assets and don't need assets of // their own. supportedLocales = mAssets.getLocales(); } mResolvedLocale = locales.getFirstMatch(supportedLocales); } } mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, adjustLanguageTag(mResolvedLocale.toLanguageTag()), Loading core/java/android/util/LocaleList.java +40 −1 Original line number Diff line number Diff line Loading @@ -213,6 +213,20 @@ public final class LocaleList implements Parcelable { } } private static final String STRING_EN_XA = "en-XA"; private static final String STRING_AR_XB = "ar-XB"; private static final Locale LOCALE_EN_XA = new Locale("en", "XA"); private static final Locale LOCALE_AR_XB = new Locale("ar", "XB"); private static final int NUM_PSEUDO_LOCALES = 2; private static boolean isPseudoLocale(String locale) { return STRING_EN_XA.equals(locale) || STRING_AR_XB.equals(locale); } private static boolean isPseudoLocale(Locale locale) { return LOCALE_EN_XA.equals(locale) || LOCALE_AR_XB.equals(locale); } private static int matchScore(Locale supported, Locale desired) { if (supported.equals(desired)) { return 1; // return early so we don't do unnecessary computation Loading @@ -220,6 +234,11 @@ public final class LocaleList implements Parcelable { if (!supported.getLanguage().equals(desired.getLanguage())) { return 0; } if (isPseudoLocale(supported) || isPseudoLocale(desired)) { // The locales are not the same, but the languages are the same, and one of the locales // is a pseudo-locale. So this is not a match. return 0; } // There is no match if the two locales use different scripts. This will most imporantly // take care of traditional vs simplified Chinese. final String supportedScr = getLikelyScript(supported); Loading @@ -241,7 +260,6 @@ public final class LocaleList implements Parcelable { if (mList.length == 0) { // empty locale list return null; } // TODO: Figure out what to if en-XA or ar-XB are in the locale list int bestIndex = Integer.MAX_VALUE; for (String tag : supportedLocales) { final Locale supportedLocale = Locale.forLanguageTag(tag); Loading @@ -265,6 +283,27 @@ public final class LocaleList implements Parcelable { } } /** * Returns true if the array of locale tags only contains empty locales and pseudolocales. * Assumes that there is no repetition in the input. * {@hide} */ public static boolean isPseudoLocalesOnly(String[] supportedLocales) { if (supportedLocales.length > NUM_PSEUDO_LOCALES + 1) { // This is for optimization. Since there's no repetition in the input, if we have more // than the number of pseudo-locales plus one for the empty string, it's guaranteed // that we have some meaninful locale in the list, so the list is not "practically // empty". return false; } for (String locale : supportedLocales) { if (!locale.isEmpty() && !isPseudoLocale(locale)) { return false; } } return true; } private final static Object sLock = new Object(); @GuardedBy("sLock") Loading core/jni/android_util_AssetManager.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -578,7 +578,7 @@ static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject cla return am->isUpToDate() ? JNI_TRUE : JNI_FALSE; } static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz) static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales) { Vector<String8> locales; Loading @@ -587,7 +587,7 @@ static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject return NULL; } am->getLocales(&locales); am->getLocales(&locales, includeSystemLocales); const int N = locales.size(); Loading @@ -608,6 +608,16 @@ static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject return result; } static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz) { return getLocales(env, clazz, true /* include system locales */); } static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz) { return getLocales(env, clazz, false /* don't include system locales */); } static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) { jobject result = env->NewObject(gConfigurationOffsets.classObject, gConfigurationOffsets.constructor); Loading Loading @@ -2154,6 +2164,8 @@ static const JNINativeMethod gAssetManagerMethods[] = { // Resources. { "getLocales", "()[Ljava/lang/String;", (void*) android_content_AssetManager_getLocales }, { "getNonSystemLocales", "()[Ljava/lang/String;", (void*) android_content_AssetManager_getNonSystemLocales }, { "getSizeConfigurations", "()[Landroid/content/res/Configuration;", (void*) android_content_AssetManager_getSizeConfigurations }, { "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V", Loading include/androidfw/AssetManager.h +10 −7 Original line number Diff line number Diff line Loading @@ -100,7 +100,8 @@ public: * then on success, *cookie is set to the value corresponding to the * newly-added asset source. */ bool addAssetPath(const String8& path, int32_t* cookie, bool appAsLib=false); bool addAssetPath(const String8& path, int32_t* cookie, bool appAsLib=false, bool isSystemAsset=false); bool addOverlayPath(const String8& path, int32_t* cookie); /* Loading Loading @@ -225,7 +226,7 @@ public: /** * Get the known locales for this asset manager object. */ void getLocales(Vector<String8>* locales) const; void getLocales(Vector<String8>* locales, bool includeSystemLocales=true) const; /** * Generate idmap data to translate resources IDs between a package and a Loading @@ -237,11 +238,13 @@ public: private: struct asset_path { asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemOverlay(false) {} asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemOverlay(false), isSystemAsset(false) {} String8 path; FileType type; String8 idmap; bool isSystemOverlay; bool isSystemAsset; }; Asset* openInPathLocked(const char* fileName, AccessMode mode, Loading Loading
core/java/android/content/res/AssetManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -698,6 +698,18 @@ public final class AssetManager implements AutoCloseable { */ public native final String[] getLocales(); /** * Same as getLocales(), except that locales that are only provided by the system (i.e. those * present in framework-res.apk or its overlays) will not be listed. * * For example, if the "system" assets support English, French, and German, and the additional * assets support Cherokee and French, getLocales() would return * [Cherokee, English, French, German], while getNonSystemLocales() would return * [Cherokee, French]. * {@hide} */ public native final String[] getNonSystemLocales(); /** {@hide} */ public native final Configuration[] getSizeConfigurations(); Loading
core/java/android/content/res/Resources.java +15 −1 Original line number Diff line number Diff line Loading @@ -1976,7 +1976,21 @@ public class Resources { if (setLocalesToDefault || mResolvedLocale == null || (configChanges & Configuration.NATIVE_CONFIG_LOCALE) != 0) { mResolvedLocale = locales.getFirstMatch(mAssets.getLocales()); if (locales.size() == 1) { // This is an optimization to avoid the JNI call(s) when the result of // getFirstMatch() does not depend on the supported locales. mResolvedLocale = locales.getPrimary(); } else { String[] supportedLocales = mAssets.getNonSystemLocales(); if (LocaleList.isPseudoLocalesOnly(supportedLocales)) { // We fallback to all locales (including system locales) if there was no // locale specifically supported by the assets. This is to properly support // apps that only rely on the shared system assets and don't need assets of // their own. supportedLocales = mAssets.getLocales(); } mResolvedLocale = locales.getFirstMatch(supportedLocales); } } mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, adjustLanguageTag(mResolvedLocale.toLanguageTag()), Loading
core/java/android/util/LocaleList.java +40 −1 Original line number Diff line number Diff line Loading @@ -213,6 +213,20 @@ public final class LocaleList implements Parcelable { } } private static final String STRING_EN_XA = "en-XA"; private static final String STRING_AR_XB = "ar-XB"; private static final Locale LOCALE_EN_XA = new Locale("en", "XA"); private static final Locale LOCALE_AR_XB = new Locale("ar", "XB"); private static final int NUM_PSEUDO_LOCALES = 2; private static boolean isPseudoLocale(String locale) { return STRING_EN_XA.equals(locale) || STRING_AR_XB.equals(locale); } private static boolean isPseudoLocale(Locale locale) { return LOCALE_EN_XA.equals(locale) || LOCALE_AR_XB.equals(locale); } private static int matchScore(Locale supported, Locale desired) { if (supported.equals(desired)) { return 1; // return early so we don't do unnecessary computation Loading @@ -220,6 +234,11 @@ public final class LocaleList implements Parcelable { if (!supported.getLanguage().equals(desired.getLanguage())) { return 0; } if (isPseudoLocale(supported) || isPseudoLocale(desired)) { // The locales are not the same, but the languages are the same, and one of the locales // is a pseudo-locale. So this is not a match. return 0; } // There is no match if the two locales use different scripts. This will most imporantly // take care of traditional vs simplified Chinese. final String supportedScr = getLikelyScript(supported); Loading @@ -241,7 +260,6 @@ public final class LocaleList implements Parcelable { if (mList.length == 0) { // empty locale list return null; } // TODO: Figure out what to if en-XA or ar-XB are in the locale list int bestIndex = Integer.MAX_VALUE; for (String tag : supportedLocales) { final Locale supportedLocale = Locale.forLanguageTag(tag); Loading @@ -265,6 +283,27 @@ public final class LocaleList implements Parcelable { } } /** * Returns true if the array of locale tags only contains empty locales and pseudolocales. * Assumes that there is no repetition in the input. * {@hide} */ public static boolean isPseudoLocalesOnly(String[] supportedLocales) { if (supportedLocales.length > NUM_PSEUDO_LOCALES + 1) { // This is for optimization. Since there's no repetition in the input, if we have more // than the number of pseudo-locales plus one for the empty string, it's guaranteed // that we have some meaninful locale in the list, so the list is not "practically // empty". return false; } for (String locale : supportedLocales) { if (!locale.isEmpty() && !isPseudoLocale(locale)) { return false; } } return true; } private final static Object sLock = new Object(); @GuardedBy("sLock") Loading
core/jni/android_util_AssetManager.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -578,7 +578,7 @@ static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject cla return am->isUpToDate() ? JNI_TRUE : JNI_FALSE; } static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz) static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales) { Vector<String8> locales; Loading @@ -587,7 +587,7 @@ static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject return NULL; } am->getLocales(&locales); am->getLocales(&locales, includeSystemLocales); const int N = locales.size(); Loading @@ -608,6 +608,16 @@ static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject return result; } static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz) { return getLocales(env, clazz, true /* include system locales */); } static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz) { return getLocales(env, clazz, false /* don't include system locales */); } static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) { jobject result = env->NewObject(gConfigurationOffsets.classObject, gConfigurationOffsets.constructor); Loading Loading @@ -2154,6 +2164,8 @@ static const JNINativeMethod gAssetManagerMethods[] = { // Resources. { "getLocales", "()[Ljava/lang/String;", (void*) android_content_AssetManager_getLocales }, { "getNonSystemLocales", "()[Ljava/lang/String;", (void*) android_content_AssetManager_getNonSystemLocales }, { "getSizeConfigurations", "()[Landroid/content/res/Configuration;", (void*) android_content_AssetManager_getSizeConfigurations }, { "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V", Loading
include/androidfw/AssetManager.h +10 −7 Original line number Diff line number Diff line Loading @@ -100,7 +100,8 @@ public: * then on success, *cookie is set to the value corresponding to the * newly-added asset source. */ bool addAssetPath(const String8& path, int32_t* cookie, bool appAsLib=false); bool addAssetPath(const String8& path, int32_t* cookie, bool appAsLib=false, bool isSystemAsset=false); bool addOverlayPath(const String8& path, int32_t* cookie); /* Loading Loading @@ -225,7 +226,7 @@ public: /** * Get the known locales for this asset manager object. */ void getLocales(Vector<String8>* locales) const; void getLocales(Vector<String8>* locales, bool includeSystemLocales=true) const; /** * Generate idmap data to translate resources IDs between a package and a Loading @@ -237,11 +238,13 @@ public: private: struct asset_path { asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemOverlay(false) {} asset_path() : path(""), type(kFileTypeRegular), idmap(""), isSystemOverlay(false), isSystemAsset(false) {} String8 path; FileType type; String8 idmap; bool isSystemOverlay; bool isSystemAsset; }; Asset* openInPathLocked(const char* fileName, AccessMode mode, Loading