diff options
author | 2023-08-15 21:42:03 +0000 | |
---|---|---|
committer | 2023-08-17 18:24:48 +0000 | |
commit | ccf5cd710da9e50932390deba68e1263990bea02 (patch) | |
tree | a9d2cf4d82cf3b52e9926117f16c2857cb3ff023 | |
parent | 413089960aa898eeb17a68bf1d4b8c9ca4df5c65 (diff) |
Reland try 2 "Pass all preferred locales to AssetManager"
This reverts commit c57041138696b7a152a80513c67793fac1cad7c4.
Reason for revert: roll forward with fix
Test: manual
Change-Id: Ic4d1aa892efd9058d21ac88709fc565fd5f61909
-rw-r--r-- | core/java/android/app/LocaleConfig.java | 5 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 12 | ||||
-rw-r--r-- | core/java/android/content/res/AssetManager.java | 38 | ||||
-rw-r--r-- | core/java/android/content/res/ResourcesImpl.java | 45 | ||||
-rw-r--r-- | core/java/android/os/LocaleList.java | 20 | ||||
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 238 | ||||
-rw-r--r-- | libs/androidfw/AssetManager2.cpp | 292 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 16 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/AssetManager2.h | 18 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 2 | ||||
-rw-r--r-- | libs/androidfw/tests/AssetManager2_bench.cpp | 6 | ||||
-rw-r--r-- | libs/androidfw/tests/AssetManager2_test.cpp | 20 | ||||
-rw-r--r-- | libs/androidfw/tests/BenchmarkHelpers.cpp | 2 | ||||
-rw-r--r-- | libs/androidfw/tests/Theme_test.cpp | 2 | ||||
-rw-r--r-- | native/android/configuration.cpp | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java | 8 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java | 4 |
17 files changed, 453 insertions, 277 deletions
diff --git a/core/java/android/app/LocaleConfig.java b/core/java/android/app/LocaleConfig.java index 729e555509a6..0857c9655e8d 100644 --- a/core/java/android/app/LocaleConfig.java +++ b/core/java/android/app/LocaleConfig.java @@ -40,7 +40,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Set; @@ -195,7 +195,8 @@ public class LocaleConfig implements Parcelable { XmlUtils.beginDocument(parser, TAG_LOCALE_CONFIG); int outerDepth = parser.getDepth(); AttributeSet attrs = Xml.asAttributeSet(parser); - Set<String> localeNames = new HashSet<String>(); + // LinkedHashSet to preserve insertion order + Set<String> localeNames = new LinkedHashSet<>(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { if (TAG_LOCALE.equals(parser.getName())) { final TypedArray attributes = res.obtainAttributes( diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 9387ae1d6ac8..41ba1dc43926 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1456,8 +1456,8 @@ public class PackageParser { private static AssetManager newConfiguredAssetManager() { AssetManager assetManager = new AssetManager(); - assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Build.VERSION.RESOURCES_SDK_INT); + assetManager.setConfiguration(0, 0, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); return assetManager; } @@ -9011,8 +9011,8 @@ public class PackageParser { } AssetManager assets = new AssetManager(); - assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Build.VERSION.RESOURCES_SDK_INT); + assets.setConfiguration(0, 0, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); assets.setApkAssets(apkAssets, false /*invalidateCaches*/); mCachedAssetManager = assets; @@ -9086,8 +9086,8 @@ public class PackageParser { private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) { final AssetManager assets = new AssetManager(); - assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Build.VERSION.RESOURCES_SDK_INT); + assets.setConfiguration(0, 0, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); assets.setApkAssets(apkAssets, false /*invalidateCaches*/); return assets; } diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index b225de402f17..23b9d0b7c9a7 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -1480,9 +1480,13 @@ public final class AssetManager implements AutoCloseable { int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode, int colorMode, int grammaticalGender, int majorVersion) { - synchronized (this) { - ensureValidLocked(); - nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density, + if (locale != null) { + setConfiguration(mcc, mnc, null, new String[]{locale}, orientation, touchscreen, + density, keyboard, keyboardHidden, navigation, screenWidth, screenHeight, + smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode, + colorMode, grammaticalGender, majorVersion); + } else { + setConfiguration(mcc, mnc, null, null, orientation, touchscreen, density, keyboard, keyboardHidden, navigation, screenWidth, screenHeight, smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode, colorMode, grammaticalGender, majorVersion); @@ -1490,6 +1494,25 @@ public final class AssetManager implements AutoCloseable { } /** + * Change the configuration used when retrieving resources. Not for use by + * applications. + * @hide + */ + public void setConfiguration(int mcc, int mnc, String defaultLocale, String[] locales, + int orientation, int touchscreen, int density, int keyboard, int keyboardHidden, + int navigation, int screenWidth, int screenHeight, int smallestScreenWidthDp, + int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode, int colorMode, + int grammaticalGender, int majorVersion) { + synchronized (this) { + ensureValidLocked(); + nativeSetConfiguration(mObject, mcc, mnc, defaultLocale, locales, orientation, + touchscreen, density, keyboard, keyboardHidden, navigation, screenWidth, + screenHeight, smallestScreenWidthDp, screenWidthDp, screenHeightDp, + screenLayout, uiMode, colorMode, grammaticalGender, majorVersion); + } + } + + /** * @hide */ @UnsupportedAppUsage @@ -1572,10 +1595,11 @@ public final class AssetManager implements AutoCloseable { private static native void nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets, boolean invalidateCaches); private static native void nativeSetConfiguration(long ptr, int mcc, int mnc, - @Nullable String locale, int orientation, int touchscreen, int density, int keyboard, - int keyboardHidden, int navigation, int screenWidth, int screenHeight, - int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout, - int uiMode, int colorMode, int grammaticalGender, int majorVersion); + @Nullable String defaultLocale, @NonNull String[] locales, int orientation, + int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, + int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp, + int screenHeightDp, int screenLayout, int uiMode, int colorMode, int grammaticalGender, + int majorVersion); private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers( long ptr, boolean includeOverlays, boolean includeLoaders); diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 395fef2d3a68..76b29e683312 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -425,14 +425,12 @@ public class ResourcesImpl { mConfiguration.setLocales(locales); } + String[] selectedLocales = null; + String defaultLocale = null; if ((configChanges & ActivityInfo.CONFIG_LOCALE) != 0) { if (locales.size() > 1) { String[] availableLocales; - - LocaleList localeList = ResourcesManager.getInstance().getLocaleList(); - if (!localeList.isEmpty()) { - availableLocales = localeList.toLanguageTags().split(","); - } else { + if (ResourcesManager.getInstance().getLocaleList().isEmpty()) { // The LocaleList has changed. We must query the AssetManager's // available Locales and figure out the best matching Locale in the new // LocaleList. @@ -444,13 +442,35 @@ public class ResourcesImpl { availableLocales = null; } } - } - if (availableLocales != null) { - final Locale bestLocale = locales.getFirstMatchWithEnglishSupported( - availableLocales); - if (bestLocale != null && bestLocale != locales.get(0)) { - mConfiguration.setLocales(new LocaleList(bestLocale, locales)); + + if (availableLocales != null) { + final Locale bestLocale = locales.getFirstMatchWithEnglishSupported( + availableLocales); + if (bestLocale != null) { + selectedLocales = new String[]{ + adjustLanguageTag(bestLocale.toLanguageTag())}; + if (!bestLocale.equals(locales.get(0))) { + mConfiguration.setLocales( + new LocaleList(bestLocale, locales)); + } + } } + } else { + selectedLocales = locales.getIntersection( + ResourcesManager.getInstance().getLocaleList()); + defaultLocale = ResourcesManager.getInstance() + .getLocaleList().get(0).toLanguageTag(); + } + } + } + if (selectedLocales == null) { + if (ResourcesManager.getInstance().getLocaleList().isEmpty()) { + selectedLocales = new String[]{ + adjustLanguageTag(locales.get(0).toLanguageTag())}; + } else { + selectedLocales = new String[locales.size()]; + for (int i = 0; i < locales.size(); i++) { + selectedLocales[i] = adjustLanguageTag(locales.get(i).toLanguageTag()); } } } @@ -488,7 +508,8 @@ public class ResourcesImpl { } mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, - adjustLanguageTag(mConfiguration.getLocales().get(0).toLanguageTag()), + defaultLocale, + selectedLocales, mConfiguration.orientation, mConfiguration.touchscreen, mConfiguration.densityDpi, mConfiguration.keyboard, diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java index b74bb333deae..82cdd280a0f3 100644 --- a/core/java/android/os/LocaleList.java +++ b/core/java/android/os/LocaleList.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Locale; /** @@ -151,6 +152,25 @@ public final class LocaleList implements Parcelable { } /** + * Find the intersection between this LocaleList and another + * @return a String array of the Locales in both LocaleLists + * {@hide} + */ + @NonNull + public String[] getIntersection(@NonNull LocaleList other) { + List<String> intersection = new ArrayList<>(); + for (Locale l1 : mList) { + for (Locale l2 : other.mList) { + if (matchesLanguageAndScript(l2, l1)) { + intersection.add(l1.toLanguageTag()); + break; + } + } + } + return intersection.toArray(new String[0]); + } + + /** * Creates a new {@link LocaleList}. * * If two or more same locales are passed, the repeated locales will be dropped. diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 979c9e3ea7a3..1afae2944178 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -347,14 +347,23 @@ static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr, } static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint mcc, jint mnc, - jstring locale, jint orientation, jint touchscreen, jint density, - jint keyboard, jint keyboard_hidden, jint navigation, - jint screen_width, jint screen_height, - jint smallest_screen_width_dp, jint screen_width_dp, - jint screen_height_dp, jint screen_layout, jint ui_mode, - jint color_mode, jint grammatical_gender, jint major_version) { + jstring default_locale, jobjectArray locales, jint orientation, + jint touchscreen, jint density, jint keyboard, + jint keyboard_hidden, jint navigation, jint screen_width, + jint screen_height, jint smallest_screen_width_dp, + jint screen_width_dp, jint screen_height_dp, jint screen_layout, + jint ui_mode, jint color_mode, jint grammatical_gender, + jint major_version) { ATRACE_NAME("AssetManager::SetConfiguration"); + const jsize locale_count = (locales == NULL) ? 0 : env->GetArrayLength(locales); + + // Constants duplicated from Java class android.content.res.Configuration. + static const jint kScreenLayoutRoundMask = 0x300; + static const jint kScreenLayoutRoundShift = 8; + + std::vector<ResTable_config> configs; + ResTable_config configuration; memset(&configuration, 0, sizeof(configuration)); configuration.mcc = static_cast<uint16_t>(mcc); @@ -375,25 +384,37 @@ static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin configuration.colorMode = static_cast<uint8_t>(color_mode); configuration.grammaticalInflection = static_cast<uint8_t>(grammatical_gender); configuration.sdkVersion = static_cast<uint16_t>(major_version); - - if (locale != nullptr) { - ScopedUtfChars locale_utf8(env, locale); - CHECK(locale_utf8.c_str() != nullptr); - configuration.setBcp47Locale(locale_utf8.c_str()); - } - - // Constants duplicated from Java class android.content.res.Configuration. - static const jint kScreenLayoutRoundMask = 0x300; - static const jint kScreenLayoutRoundShift = 8; - // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer // in C++. We must extract the round qualifier out of the Java screenLayout and put it // into screenLayout2. configuration.screenLayout2 = - static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift); + static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift); + + if (locale_count > 0) { + configs.resize(locale_count, configuration); + for (int i = 0; i < locale_count; i++) { + jstring locale = (jstring)(env->GetObjectArrayElement(locales, i)); + ScopedUtfChars locale_utf8(env, locale); + CHECK(locale_utf8.c_str() != nullptr); + configs[i].setBcp47Locale(locale_utf8.c_str()); + } + } else { + configs.push_back(configuration); + } + + uint32_t default_locale_int = 0; + if (default_locale != nullptr) { + ResTable_config config; + static_assert(std::is_same_v<decltype(config.locale), decltype(default_locale_int)>); + ScopedUtfChars locale_utf8(env, default_locale); + CHECK(locale_utf8.c_str() != nullptr); + config.setBcp47Locale(locale_utf8.c_str()); + default_locale_int = config.locale; + } auto assetmanager = LockAndStartAssetManager(ptr); - assetmanager->SetConfiguration(configuration); + assetmanager->SetConfigurations(configs); + assetmanager->SetDefaultLocale(default_locale_int); } static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr, @@ -1498,94 +1519,97 @@ static jlong NativeAssetGetRemainingLength(JNIEnv* /*env*/, jclass /*clazz*/, jl // JNI registration. static const JNINativeMethod gAssetManagerMethods[] = { - // AssetManager setup methods. - {"nativeCreate", "()J", (void*)NativeCreate}, - {"nativeDestroy", "(J)V", (void*)NativeDestroy}, - {"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets}, - {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIIII)V", - (void*)NativeSetConfiguration}, - {"nativeGetAssignedPackageIdentifiers", "(JZZ)Landroid/util/SparseArray;", - (void*)NativeGetAssignedPackageIdentifiers}, - - // AssetManager file methods. - {"nativeContainsAllocatedTable", "(J)Z", (void*)ContainsAllocatedTable}, - {"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList}, - {"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset}, - {"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;", - (void*)NativeOpenAssetFd}, - {"nativeOpenNonAsset", "(JILjava/lang/String;I)J", (void*)NativeOpenNonAsset}, - {"nativeOpenNonAssetFd", "(JILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;", - (void*)NativeOpenNonAssetFd}, - {"nativeOpenXmlAsset", "(JILjava/lang/String;)J", (void*)NativeOpenXmlAsset}, - {"nativeOpenXmlAssetFd", "(JILjava/io/FileDescriptor;)J", (void*)NativeOpenXmlAssetFd}, - - // AssetManager resource methods. - {"nativeGetResourceValue", "(JISLandroid/util/TypedValue;Z)I", (void*)NativeGetResourceValue}, - {"nativeGetResourceBagValue", "(JIILandroid/util/TypedValue;)I", - (void*)NativeGetResourceBagValue}, - {"nativeGetStyleAttributes", "(JI)[I", (void*)NativeGetStyleAttributes}, - {"nativeGetResourceStringArray", "(JI)[Ljava/lang/String;", - (void*)NativeGetResourceStringArray}, - {"nativeGetResourceStringArrayInfo", "(JI)[I", (void*)NativeGetResourceStringArrayInfo}, - {"nativeGetResourceIntArray", "(JI)[I", (void*)NativeGetResourceIntArray}, - {"nativeGetResourceArraySize", "(JI)I", (void*)NativeGetResourceArraySize}, - {"nativeGetResourceArray", "(JI[I)I", (void*)NativeGetResourceArray}, - {"nativeGetParentThemeIdentifier", "(JI)I", - (void*)NativeGetParentThemeIdentifier}, - - // AssetManager resource name/ID methods. - {"nativeGetResourceIdentifier", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", - (void*)NativeGetResourceIdentifier}, - {"nativeGetResourceName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceName}, - {"nativeGetResourcePackageName", "(JI)Ljava/lang/String;", (void*)NativeGetResourcePackageName}, - {"nativeGetResourceTypeName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceTypeName}, - {"nativeGetResourceEntryName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceEntryName}, - {"nativeSetResourceResolutionLoggingEnabled", "(JZ)V", - (void*) NativeSetResourceResolutionLoggingEnabled}, - {"nativeGetLastResourceResolution", "(J)Ljava/lang/String;", - (void*) NativeGetLastResourceResolution}, - {"nativeGetLocales", "(JZ)[Ljava/lang/String;", (void*)NativeGetLocales}, - {"nativeGetSizeConfigurations", "(J)[Landroid/content/res/Configuration;", - (void*)NativeGetSizeConfigurations}, - {"nativeGetSizeAndUiModeConfigurations", "(J)[Landroid/content/res/Configuration;", - (void*)NativeGetSizeAndUiModeConfigurations}, - - // Style attribute related methods. - {"nativeAttributeResolutionStack", "(JJIII)[I", (void*)NativeAttributeResolutionStack}, - {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle}, - {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs}, - {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes}, - - // Theme related methods. - {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate}, - {"nativeGetThemeFreeFunction", "()J", (void*)NativeGetThemeFreeFunction}, - {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle}, - {"nativeThemeRebase", "(JJ[I[ZI)V", (void*)NativeThemeRebase}, - - {"nativeThemeCopy", "(JJJJ)V", (void*)NativeThemeCopy}, - {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I", - (void*)NativeThemeGetAttributeValue}, - {"nativeThemeDump", "(JJILjava/lang/String;Ljava/lang/String;)V", (void*)NativeThemeDump}, - {"nativeThemeGetChangingConfigurations", "(J)I", (void*)NativeThemeGetChangingConfigurations}, - - // AssetInputStream methods. - {"nativeAssetDestroy", "(J)V", (void*)NativeAssetDestroy}, - {"nativeAssetReadChar", "(J)I", (void*)NativeAssetReadChar}, - {"nativeAssetRead", "(J[BII)I", (void*)NativeAssetRead}, - {"nativeAssetSeek", "(JJI)J", (void*)NativeAssetSeek}, - {"nativeAssetGetLength", "(J)J", (void*)NativeAssetGetLength}, - {"nativeAssetGetRemainingLength", "(J)J", (void*)NativeAssetGetRemainingLength}, - - // System/idmap related methods. - {"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;", - (void*)NativeGetOverlayableMap}, - {"nativeGetOverlayablesToString", "(JLjava/lang/String;)Ljava/lang/String;", - (void*)NativeGetOverlayablesToString}, - - // Global management/debug methods. - {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount}, - {"getAssetAllocations", "()Ljava/lang/String;", (void*)NativeGetAssetAllocations}, - {"getGlobalAssetManagerCount", "()I", (void*)NativeGetGlobalAssetManagerCount}, + // AssetManager setup methods. + {"nativeCreate", "()J", (void*)NativeCreate}, + {"nativeDestroy", "(J)V", (void*)NativeDestroy}, + {"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets}, + {"nativeSetConfiguration", "(JIILjava/lang/String;[Ljava/lang/String;IIIIIIIIIIIIIIII)V", + (void*)NativeSetConfiguration}, + {"nativeGetAssignedPackageIdentifiers", "(JZZ)Landroid/util/SparseArray;", + (void*)NativeGetAssignedPackageIdentifiers}, + + // AssetManager file methods. + {"nativeContainsAllocatedTable", "(J)Z", (void*)ContainsAllocatedTable}, + {"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList}, + {"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset}, + {"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;", + (void*)NativeOpenAssetFd}, + {"nativeOpenNonAsset", "(JILjava/lang/String;I)J", (void*)NativeOpenNonAsset}, + {"nativeOpenNonAssetFd", "(JILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;", + (void*)NativeOpenNonAssetFd}, + {"nativeOpenXmlAsset", "(JILjava/lang/String;)J", (void*)NativeOpenXmlAsset}, + {"nativeOpenXmlAssetFd", "(JILjava/io/FileDescriptor;)J", (void*)NativeOpenXmlAssetFd}, + + // AssetManager resource methods. + {"nativeGetResourceValue", "(JISLandroid/util/TypedValue;Z)I", + (void*)NativeGetResourceValue}, + {"nativeGetResourceBagValue", "(JIILandroid/util/TypedValue;)I", + (void*)NativeGetResourceBagValue}, + {"nativeGetStyleAttributes", "(JI)[I", (void*)NativeGetStyleAttributes}, + {"nativeGetResourceStringArray", "(JI)[Ljava/lang/String;", + (void*)NativeGetResourceStringArray}, + {"nativeGetResourceStringArrayInfo", "(JI)[I", (void*)NativeGetResourceStringArrayInfo}, + {"nativeGetResourceIntArray", "(JI)[I", (void*)NativeGetResourceIntArray}, + {"nativeGetResourceArraySize", "(JI)I", (void*)NativeGetResourceArraySize}, + {"nativeGetResourceArray", "(JI[I)I", (void*)NativeGetResourceArray}, + {"nativeGetParentThemeIdentifier", "(JI)I", (void*)NativeGetParentThemeIdentifier}, + + // AssetManager resource name/ID methods. + {"nativeGetResourceIdentifier", + "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", + (void*)NativeGetResourceIdentifier}, + {"nativeGetResourceName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceName}, + {"nativeGetResourcePackageName", "(JI)Ljava/lang/String;", + (void*)NativeGetResourcePackageName}, + {"nativeGetResourceTypeName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceTypeName}, + {"nativeGetResourceEntryName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceEntryName}, + {"nativeSetResourceResolutionLoggingEnabled", "(JZ)V", + (void*)NativeSetResourceResolutionLoggingEnabled}, + {"nativeGetLastResourceResolution", "(J)Ljava/lang/String;", + (void*)NativeGetLastResourceResolution}, + {"nativeGetLocales", "(JZ)[Ljava/lang/String;", (void*)NativeGetLocales}, + {"nativeGetSizeConfigurations", "(J)[Landroid/content/res/Configuration;", + (void*)NativeGetSizeConfigurations}, + {"nativeGetSizeAndUiModeConfigurations", "(J)[Landroid/content/res/Configuration;", + (void*)NativeGetSizeAndUiModeConfigurations}, + + // Style attribute related methods. + {"nativeAttributeResolutionStack", "(JJIII)[I", (void*)NativeAttributeResolutionStack}, + {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle}, + {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs}, + {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes}, + + // Theme related methods. + {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate}, + {"nativeGetThemeFreeFunction", "()J", (void*)NativeGetThemeFreeFunction}, + {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle}, + {"nativeThemeRebase", "(JJ[I[ZI)V", (void*)NativeThemeRebase}, + + {"nativeThemeCopy", "(JJJJ)V", (void*)NativeThemeCopy}, + {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I", + (void*)NativeThemeGetAttributeValue}, + {"nativeThemeDump", "(JJILjava/lang/String;Ljava/lang/String;)V", (void*)NativeThemeDump}, + {"nativeThemeGetChangingConfigurations", "(J)I", + (void*)NativeThemeGetChangingConfigurations}, + + // AssetInputStream methods. + {"nativeAssetDestroy", "(J)V", (void*)NativeAssetDestroy}, + {"nativeAssetReadChar", "(J)I", (void*)NativeAssetReadChar}, + {"nativeAssetRead", "(J[BII)I", (void*)NativeAssetRead}, + {"nativeAssetSeek", "(JJI)J", (void*)NativeAssetSeek}, + {"nativeAssetGetLength", "(J)J", (void*)NativeAssetGetLength}, + {"nativeAssetGetRemainingLength", "(J)J", (void*)NativeAssetGetRemainingLength}, + + // System/idmap related methods. + {"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;", + (void*)NativeGetOverlayableMap}, + {"nativeGetOverlayablesToString", "(JLjava/lang/String;)Ljava/lang/String;", + (void*)NativeGetOverlayablesToString}, + + // Global management/debug methods. + {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount}, + {"getAssetAllocations", "()Ljava/lang/String;", (void*)NativeGetAssetAllocations}, + {"getGlobalAssetManagerCount", "()I", (void*)NativeGetGlobalAssetManagerCount}, }; int register_android_content_AssetManager(JNIEnv* env) { diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index b1ef4e5cd3a9..5ffec34be397 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -91,12 +91,17 @@ struct FindEntryResult { StringPoolRef entry_string_ref; }; -AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration) - : configuration_(configuration) { +AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration) { + configurations_.push_back(configuration); + // Don't invalidate caches here as there's nothing cached yet. SetApkAssets(apk_assets, false); } +AssetManager2::AssetManager2() { + configurations_.resize(1); +} + bool AssetManager2::SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches) { BuildDynamicRefTable(apk_assets); RebuildFilterList(); @@ -421,9 +426,16 @@ bool AssetManager2::ContainsAllocatedTable() const { return false; } -void AssetManager2::SetConfiguration(const ResTable_config& configuration) { - const int diff = configuration_.diff(configuration); - configuration_ = configuration; +void AssetManager2::SetConfigurations(std::vector<ResTable_config> configurations) { + int diff = 0; + if (configurations_.size() != configurations.size()) { + diff = -1; + } else { + for (int i = 0; i < configurations_.size(); i++) { + diff |= configurations_[i].diff(configurations[i]); + } + } + configurations_ = std::move(configurations); if (diff) { RebuildFilterList(); @@ -620,16 +632,6 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( auto op = StartOperation(); - // Might use this if density_override != 0. - ResTable_config density_override_config; - - // Select our configuration or generate a density override configuration. - const ResTable_config* desired_config = &configuration_; - if (density_override != 0 && density_override != configuration_.density) { - density_override_config = configuration_; - density_override_config.density = density_override; - desired_config = &density_override_config; - } // Retrieve the package group from the package id of the resource id. if (UNLIKELY(!is_valid_resid(resid))) { @@ -648,119 +650,160 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( } const PackageGroup& package_group = package_groups_[package_idx]; - auto result = FindEntryInternal(package_group, type_idx, entry_idx, *desired_config, - stop_at_first_match, ignore_configuration); - if (UNLIKELY(!result.has_value())) { - return base::unexpected(result.error()); - } + std::optional<FindEntryResult> final_result; + bool final_has_locale = false; + bool final_overlaid = false; + for (auto & config : configurations_) { + // Might use this if density_override != 0. + ResTable_config density_override_config; + + // Select our configuration or generate a density override configuration. + const ResTable_config* desired_config = &config; + if (density_override != 0 && density_override != config.density) { + density_override_config = config; + density_override_config.density = density_override; + desired_config = &density_override_config; + } - bool overlaid = false; - if (!stop_at_first_match && !ignore_configuration) { - const auto& assets = GetApkAssets(result->cookie); - if (!assets) { - ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid); - return base::unexpected(std::nullopt); + auto result = FindEntryInternal(package_group, type_idx, entry_idx, *desired_config, + stop_at_first_match, ignore_configuration); + if (UNLIKELY(!result.has_value())) { + return base::unexpected(result.error()); } - if (!assets->IsLoader()) { - for (const auto& id_map : package_group.overlays_) { - auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid); - if (!overlay_entry) { - // No id map entry exists for this target resource. - continue; - } - if (overlay_entry.IsInlineValue()) { - // The target resource is overlaid by an inline value not represented by a resource. - ConfigDescription best_frro_config; - Res_value best_frro_value; - bool frro_found = false; - for( const auto& [config, value] : overlay_entry.GetInlineValue()) { - if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) - && config.match(*desired_config)) { - frro_found = true; - best_frro_config = config; - best_frro_value = value; + bool overlaid = false; + if (!stop_at_first_match && !ignore_configuration) { + const auto& assets = GetApkAssets(result->cookie); + if (!assets) { + ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid); + return base::unexpected(std::nullopt); + } + if (!assets->IsLoader()) { + for (const auto& id_map : package_group.overlays_) { + auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid); + if (!overlay_entry) { + // No id map entry exists for this target resource. + continue; + } + if (overlay_entry.IsInlineValue()) { + // The target resource is overlaid by an inline value not represented by a resource. + ConfigDescription best_frro_config; + Res_value best_frro_value; + bool frro_found = false; + for( const auto& [config, value] : overlay_entry.GetInlineValue()) { + if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) + && config.match(*desired_config)) { + frro_found = true; + best_frro_config = config; + best_frro_value = value; + } + } + if (!frro_found) { + continue; } + result->entry = best_frro_value; + result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); + result->cookie = id_map.cookie; + + if (UNLIKELY(logging_enabled)) { + last_resolution_.steps.push_back(Resolution::Step{ + Resolution::Step::Type::OVERLAID_INLINE, result->cookie, String8()}); + if (auto path = assets->GetPath()) { + const std::string overlay_path = path->data(); + if (IsFabricatedOverlay(overlay_path)) { + // FRRO don't have package name so we use the creating package here. + String8 frro_name = String8("FRRO"); + // Get the first part of it since the expected one should be like + // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro + // under /data/resource-cache/. + const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1); + const size_t end = name.find('-'); + if (frro_name.size() != overlay_path.size() && end != std::string::npos) { + frro_name.append(base::StringPrintf(" created by %s", + name.substr(0 /* pos */, + end).c_str()).c_str()); + } + last_resolution_.best_package_name = frro_name; + } else { + last_resolution_.best_package_name = result->package_name->c_str(); + } + } + overlaid = true; + } + continue; + } + + auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override, + false /* stop_at_first_match */, + false /* ignore_configuration */); + if (UNLIKELY(IsIOError(overlay_result))) { + return base::unexpected(overlay_result.error()); + } + if (!overlay_result.has_value()) { + continue; } - if (!frro_found) { + + if (!overlay_result->config.isBetterThan(result->config, desired_config) + && overlay_result->config.compare(result->config) != 0) { + // The configuration of the entry for the overlay must be equal to or better than the + // target configuration to be chosen as the better value. continue; } - result->entry = best_frro_value; + + result->cookie = overlay_result->cookie; + result->entry = overlay_result->entry; + result->config = overlay_result->config; result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); - result->cookie = id_map.cookie; if (UNLIKELY(logging_enabled)) { last_resolution_.steps.push_back( - Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, result->cookie, String8()}); - if (auto path = assets->GetPath()) { - const std::string overlay_path = path->data(); - if (IsFabricatedOverlay(overlay_path)) { - // FRRO don't have package name so we use the creating package here. - String8 frro_name = String8("FRRO"); - // Get the first part of it since the expected one should be like - // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro - // under /data/resource-cache/. - const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1); - const size_t end = name.find('-'); - if (frro_name.size() != overlay_path.size() && end != std::string::npos) { - frro_name.append(base::StringPrintf(" created by %s", - name.substr(0 /* pos */, - end).c_str()).c_str()); - } - last_resolution_.best_package_name = frro_name; - } else { - last_resolution_.best_package_name = result->package_name->c_str(); - } - } + Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->cookie, + overlay_result->config.toString()}); + last_resolution_.best_package_name = + overlay_result->package_name->c_str(); overlaid = true; } - continue; } + } + } - auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override, - false /* stop_at_first_match */, - false /* ignore_configuration */); - if (UNLIKELY(IsIOError(overlay_result))) { - return base::unexpected(overlay_result.error()); - } - if (!overlay_result.has_value()) { - continue; - } - - if (!overlay_result->config.isBetterThan(result->config, desired_config) - && overlay_result->config.compare(result->config) != 0) { - // The configuration of the entry for the overlay must be equal to or better than the target - // configuration to be chosen as the better value. - continue; - } - - result->cookie = overlay_result->cookie; - result->entry = overlay_result->entry; - result->config = overlay_result->config; - result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); - - if (UNLIKELY(logging_enabled)) { - last_resolution_.steps.push_back( - Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->cookie, - overlay_result->config.toString()}); - last_resolution_.best_package_name = - overlay_result->package_name->c_str(); - overlaid = true; - } + bool has_locale = false; + if (result->config.locale == 0) { + if (default_locale_ != 0) { + ResTable_config conf; + conf.locale = default_locale_; + // Since we know conf has a locale and only a locale, match will tell us if that locale + // matches + has_locale = conf.match(config); } + } else { + has_locale = true; + } + + // if we don't have a result yet + if (!final_result || + // or this config is better before the locale than the existing result + result->config.isBetterThanBeforeLocale(final_result->config, desired_config) || + // or the existing config isn't better before locale and this one specifies a locale + // whereas the existing one doesn't + (!final_result->config.isBetterThanBeforeLocale(result->config, desired_config) + && has_locale && !final_has_locale)) { + final_result = result.value(); + final_overlaid = overlaid; + final_has_locale = has_locale; } } if (UNLIKELY(logging_enabled)) { - last_resolution_.cookie = result->cookie; - last_resolution_.type_string_ref = result->type_string_ref; - last_resolution_.entry_string_ref = result->entry_string_ref; - last_resolution_.best_config_name = result->config.toString(); - if (!overlaid) { - last_resolution_.best_package_name = result->package_name->c_str(); + last_resolution_.cookie = final_result->cookie; + last_resolution_.type_string_ref = final_result->type_string_ref; + last_resolution_.entry_string_ref = final_result->entry_string_ref; + last_resolution_.best_config_name = final_result->config.toString(); + if (!final_overlaid) { + last_resolution_.best_package_name = final_result->package_name->c_str(); } } - return result; + return *final_result; } base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( @@ -778,8 +821,10 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( // If `desired_config` is not the same as the set configuration or the caller will accept a value // from any configuration, then we cannot use our filtered list of types since it only it contains // types matched to the set configuration. - const bool use_filtered = !ignore_configuration && &desired_config == &configuration_; - + const bool use_filtered = !ignore_configuration && std::find_if( + configurations_.begin(), configurations_.end(), + [&desired_config](auto& value) { return &desired_config == &value; }) + != configurations_.end(); const size_t package_count = package_group.packages_.size(); for (size_t pi = 0; pi < package_count; pi++) { const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi]; @@ -934,10 +979,22 @@ std::string AssetManager2::GetLastResourceResolution() const { } std::stringstream log_stream; - log_stream << base::StringPrintf("Resolution for 0x%08x %s\n" - "\tFor config - %s", resid, resource_name_string.c_str(), - configuration_.toString().c_str()); - + if (configurations_.size() == 1) { + log_stream << base::StringPrintf("Resolution for 0x%08x %s\n" + "\tFor config - %s", resid, resource_name_string.c_str(), + configurations_[0].toString().c_str()); + } else { + ResTable_config conf = configurations_[0]; + conf.clearLocale(); + log_stream << base::StringPrintf("Resolution for 0x%08x %s\n\tFor config - %s and locales", + resid, resource_name_string.c_str(), conf.toString().c_str()); + char str[40]; + str[0] = '\0'; + for(auto iter = configurations_.begin(); iter < configurations_.end(); iter++) { + iter->getBcp47Locale(str); + log_stream << base::StringPrintf(" %s%s", str, iter < configurations_.end() ? "," : ""); + } + } for (const Resolution::Step& step : last_resolution_.steps) { constexpr static std::array kStepStrings = { "Found initial", @@ -1427,11 +1484,14 @@ void AssetManager2::RebuildFilterList() { package.loaded_package_->ForEachTypeSpec([&](const TypeSpec& type_spec, uint8_t type_id) { FilteredConfigGroup* group = nullptr; for (const auto& type_entry : type_spec.type_entries) { - if (type_entry.config.match(configuration_)) { - if (!group) { - group = &package.filtered_configs_.editItemAt(type_id - 1); + for (auto & config : configurations_) { + if (type_entry.config.match(config)) { + if (!group) { + group = &package.filtered_configs_.editItemAt(type_id - 1); + } + group->type_entries.push_back(&type_entry); + break; } - group->type_entries.push_back(&type_entry); } } }); diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 5a636128e076..06d19e064c91 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -2568,6 +2568,22 @@ bool ResTable_config::isLocaleBetterThan(const ResTable_config& o, return false; } +bool ResTable_config::isBetterThanBeforeLocale(const ResTable_config& o, + const ResTable_config* requested) const { + if (requested) { + if (imsi || o.imsi) { + if ((mcc != o.mcc) && requested->mcc) { + return (mcc); + } + + if ((mnc != o.mnc) && requested->mnc) { + return (mnc); + } + } + } + return false; +} + bool ResTable_config::isBetterThan(const ResTable_config& o, const ResTable_config* requested) const { if (requested) { diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index f611d0d8566a..d9ff35b49e0a 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -100,7 +100,7 @@ class AssetManager2 { using ApkAssetsWPtr = wp<const ApkAssets>; using ApkAssetsList = std::span<const ApkAssetsPtr>; - AssetManager2() = default; + AssetManager2(); explicit AssetManager2(AssetManager2&& other) = default; AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration); @@ -156,10 +156,14 @@ class AssetManager2 { // Sets/resets the configuration for this AssetManager. This will cause all // caches that are related to the configuration change to be invalidated. - void SetConfiguration(const ResTable_config& configuration); + void SetConfigurations(std::vector<ResTable_config> configurations); - inline const ResTable_config& GetConfiguration() const { - return configuration_; + inline const std::vector<ResTable_config>& GetConfigurations() const { + return configurations_; + } + + inline void SetDefaultLocale(uint32_t default_locale) { + default_locale_ = default_locale; } // Returns all configurations for which there are resources defined, or an I/O error if reading @@ -465,9 +469,11 @@ class AssetManager2 { // without taking too much memory. std::array<uint8_t, std::numeric_limits<uint8_t>::max() + 1> package_ids_; - // The current configuration set for this AssetManager. When this changes, cached resources + uint32_t default_locale_; + + // The current configurations set for this AssetManager. When this changes, cached resources // may need to be purged. - ResTable_config configuration_ = {}; + std::vector<ResTable_config> configurations_; // Cached set of bags. These are cached because they can inherit keys from parent bags, // which involves some calculation. diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 6de1d1e927dc..fdb355192676 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1375,6 +1375,8 @@ struct ResTable_config // match the requested configuration at all. bool isLocaleBetterThan(const ResTable_config& o, const ResTable_config* requested) const; + bool isBetterThanBeforeLocale(const ResTable_config& o, const ResTable_config* requested) const; + String8 toString() const; }; diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp index 6fae72a6d10e..2caa98c35971 100644 --- a/libs/androidfw/tests/AssetManager2_bench.cpp +++ b/libs/androidfw/tests/AssetManager2_bench.cpp @@ -228,10 +228,12 @@ static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) { ResTable_config config; memset(&config, 0, sizeof(config)); + std::vector<ResTable_config> configs; + configs.push_back(config); while (state.KeepRunning()) { - config.sdkVersion = ~config.sdkVersion; - assets.SetConfiguration(config); + configs[0].sdkVersion = ~configs[0].sdkVersion; + assets.SetConfigurations(configs); } } BENCHMARK(BM_AssetManagerSetConfigurationFramework); diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp index df3fa02ce44c..c62f095e9dac 100644 --- a/libs/androidfw/tests/AssetManager2_test.cpp +++ b/libs/androidfw/tests/AssetManager2_test.cpp @@ -113,7 +113,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { desired_config.language[1] = 'e'; AssetManager2 assetmanager; - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -137,7 +137,7 @@ TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) { desired_config.language[1] = 'e'; AssetManager2 assetmanager; - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -466,10 +466,10 @@ TEST_F(AssetManager2Test, ResolveDeepIdReference) { TEST_F(AssetManager2Test, DensityOverride) { AssetManager2 assetmanager; assetmanager.SetApkAssets({basic_assets_, basic_xhdpi_assets_, basic_xxhdpi_assets_}); - assetmanager.SetConfiguration({ + assetmanager.SetConfigurations({{ .density = ResTable_config::DENSITY_XHIGH, .sdkVersion = 21, - }); + }}); auto value = assetmanager.GetResource(basic::R::string::density, false /*may_be_bag*/); ASSERT_TRUE(value.has_value()); @@ -721,7 +721,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutEnablingReturnsEmpty) { ResTable_config desired_config; AssetManager2 assetmanager; - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_}); assetmanager.SetResourceResolutionLoggingEnabled(false); @@ -736,7 +736,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutResolutionReturnsEmpty) { ResTable_config desired_config; AssetManager2 assetmanager; - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_}); auto result = assetmanager.GetLastResourceResolution(); @@ -751,7 +751,7 @@ TEST_F(AssetManager2Test, GetLastPathWithSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -774,7 +774,7 @@ TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -796,7 +796,7 @@ TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -817,7 +817,7 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfiguration(desired_config); + assetmanager.SetConfigurations({desired_config}); assetmanager.SetApkAssets({overlayable_assets_}); const auto map = assetmanager.GetOverlayableMapForPackage(0x7f); diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp index b97dd96f8934..8b883f4ed1df 100644 --- a/libs/androidfw/tests/BenchmarkHelpers.cpp +++ b/libs/androidfw/tests/BenchmarkHelpers.cpp @@ -66,7 +66,7 @@ void GetResourceBenchmark(const std::vector<std::string>& paths, const ResTable_ AssetManager2 assetmanager; assetmanager.SetApkAssets(apk_assets); if (config != nullptr) { - assetmanager.SetConfiguration(*config); + assetmanager.SetConfigurations({*config}); } while (state.KeepRunning()) { diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp index e08a6a7f277d..181d1411fb91 100644 --- a/libs/androidfw/tests/Theme_test.cpp +++ b/libs/androidfw/tests/Theme_test.cpp @@ -260,7 +260,7 @@ TEST_F(ThemeTest, ThemeRebase) { ResTable_config night{}; night.uiMode = ResTable_config::UI_MODE_NIGHT_YES; night.version = 8u; - am_night.SetConfiguration(night); + am_night.SetConfigurations({night}); auto theme = am.NewTheme(); { diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp index b50514d27bac..283445fc8a9a 100644 --- a/native/android/configuration.cpp +++ b/native/android/configuration.cpp @@ -36,7 +36,7 @@ void AConfiguration_delete(AConfiguration* config) { void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am) { ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(am)); - ResTable_config config = locked_mgr->GetConfiguration(); + ResTable_config config = locked_mgr->GetConfigurations()[0]; // AConfiguration is not a virtual subclass, so we can memcpy. memcpy(out, &config, sizeof(config)); diff --git a/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java b/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java index a2177e87bcdb..0bb969f488fe 100644 --- a/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java +++ b/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java @@ -17,13 +17,13 @@ package com.android.server.pm.split; import android.content.pm.parsing.ApkLiteParseUtils; import android.content.pm.parsing.PackageLite; -import com.android.server.pm.pkg.parsing.ParsingPackageUtils; -import com.android.server.pm.pkg.parsing.ParsingPackageUtils.ParseFlags; import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.os.Build; import com.android.internal.util.ArrayUtils; +import com.android.server.pm.pkg.parsing.ParsingPackageUtils; +import com.android.server.pm.pkg.parsing.ParsingPackageUtils.ParseFlags; import libcore.io.IoUtils; @@ -82,8 +82,8 @@ public class DefaultSplitAssetLoader implements SplitAssetLoader { } AssetManager assets = new AssetManager(); - assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Build.VERSION.RESOURCES_SDK_INT); + assets.setConfiguration(0, 0, null, new String[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, Build.VERSION.RESOURCES_SDK_INT); assets.setApkAssets(apkAssets, false /*invalidateCaches*/); mCachedAssetManager = assets; diff --git a/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java b/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java index 1a8c199608df..56d92fbc95a2 100644 --- a/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java +++ b/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java @@ -80,8 +80,8 @@ public class SplitAssetDependencyLoader extends SplitDependencyLoader<IllegalArg private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) { final AssetManager assets = new AssetManager(); - assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Build.VERSION.RESOURCES_SDK_INT); + assets.setConfiguration(0, 0, null, new String[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, Build.VERSION.RESOURCES_SDK_INT); assets.setApkAssets(apkAssets, false /*invalidateCaches*/); return assets; } |