diff options
-rw-r--r-- | core/java/android/app/ResourcesManager.java | 32 | ||||
-rw-r--r-- | core/tests/coretests/src/android/content/res/ResourcesManagerTest.java | 109 |
2 files changed, 73 insertions, 68 deletions
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index d66429a2192d..23a7d94b9308 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -160,7 +160,9 @@ public class ResourcesManager { return; } - final var sharedLibAssets = new SharedLibraryAssets(appInfo); + final var application = ActivityThread.currentActivityThread().getApplication(); + final var currentAppInfo = application != null ? application.getApplicationInfo() : null; + final var sharedLibAssets = new SharedLibraryAssets(appInfo, currentAppInfo); synchronized (mLock) { if (mSharedLibAssetsMap.containsKey(uniqueId)) { Slog.v(TAG, "Package resources' paths for uniqueId: " + uniqueId @@ -191,7 +193,7 @@ public class ResourcesManager { synchronized (mLock) { size = mSharedLibAssetsMap.size(); - if (assets == AssetManager.getSystem()) { + if (size == 0 || assets == AssetManager.getSystem()) { return new Pair<>(assets, size); } collector = new PathCollector(resourcesKeyFromAssets(assets)); @@ -1998,10 +2000,30 @@ public class ResourcesManager { public static class SharedLibraryAssets { private final ResourcesKey mResourcesKey; - private SharedLibraryAssets(ApplicationInfo appInfo) { + private SharedLibraryAssets(@NonNull ApplicationInfo appInfo, + @Nullable ApplicationInfo baseAppInfo) { // We're loading all library's files as shared libs, regardless where they are in // its own ApplicationInfo. final var collector = new PathCollector(null); + // Pre-populate the collector's sets with the base app paths so they all get filtered + // out if they exist in the info that's being registered as well. + // Note: if someone is registering their own appInfo, we can't filter out anything + // here and this means any asset path changes are going to be ignored. + if (baseAppInfo != null && !baseAppInfo.sourceDir.equals(appInfo.sourceDir)) { + collector.libsSet.add(baseAppInfo.sourceDir); + if (baseAppInfo.splitSourceDirs != null) { + collector.libsSet.addAll(Arrays.asList(baseAppInfo.splitSourceDirs)); + } + if (baseAppInfo.sharedLibraryFiles != null) { + collector.libsSet.addAll(Arrays.asList(baseAppInfo.sharedLibraryFiles)); + } + if (baseAppInfo.resourceDirs != null) { + collector.overlaysSet.addAll(Arrays.asList(baseAppInfo.resourceDirs)); + } + if (baseAppInfo.overlayPaths != null) { + collector.overlaysSet.addAll(Arrays.asList(baseAppInfo.overlayPaths)); + } + } PathCollector.appendNewPath(appInfo.sourceDir, collector.libsSet, collector.orderedLibs); PathCollector.appendAllNewPaths(appInfo.splitSourceDirs, collector.libsSet, @@ -2013,6 +2035,10 @@ public class ResourcesManager { PathCollector.appendAllNewPaths(appInfo.overlayPaths, collector.overlaysSet, collector.orderedOverlays); mResourcesKey = collector.collectedKey(); + + if (DEBUG) { + Log.i(TAG, "Created shared library assets: " + mResourcesKey); + } } /** diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java index cfcd53e14c79..486085521aab 100644 --- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java +++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java @@ -33,7 +33,6 @@ import android.platform.test.annotations.Postsubmit; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.Display; @@ -43,12 +42,12 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -66,6 +65,7 @@ public class ResourcesManagerTest { public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private ResourcesManager mResourcesManager; + private ResourcesManager mOldResourcesManager; private Map<Integer, DisplayMetrics> mDisplayMetricsMap; @Before @@ -115,6 +115,12 @@ public class ResourcesManagerTest { return mDisplayMetricsMap.get(displayId); } }; + mOldResourcesManager = ResourcesManager.setInstance(mResourcesManager); + } + + @After + public void tearDown() { + ResourcesManager.setInstance(mOldResourcesManager); } private PackageManager getPackageManager() { @@ -363,11 +369,6 @@ public class ResourcesManagerTest { @DisabledOnRavenwood(blockedBy = PackageManager.class) public void testExistingResourcesAfterResourcePathsRegistration() throws PackageManager.NameNotFoundException { - // Inject ResourcesManager instance from this test to the ResourcesManager class so that all - // the static method can interact with this test smoothly. - ResourcesManager oriResourcesManager = ResourcesManager.getInstance(); - ResourcesManager.setInstance(mResourcesManager); - // Create a Resources before register resources' paths for a package. Resources resources = mResourcesManager.getResources( null, APP_ONE_RES_DIR, null, null, null, null, null, null, @@ -380,16 +381,11 @@ public class ResourcesManagerTest { assertNotSame(oriResImpl, resources.getImpl()); - String[] resourcePaths = appInfo.getAllApkPaths(); - resourcePaths = removeDuplicates(resourcePaths); ApkAssets[] loadedAssets = resources.getAssets().getApkAssets(); - assertTrue(allResourcePathsLoaded(resourcePaths, loadedAssets)); + assertTrue(containsPath(TEST_LIB, loadedAssets)); // Package resources' paths should be cached in ResourcesManager. assertNotNull(ResourcesManager.getInstance().getRegisteredResourcePaths().get(TEST_LIB)); - - // Revert the ResourcesManager instance back. - ResourcesManager.setInstance(oriResourcesManager); } @Test @@ -398,11 +394,6 @@ public class ResourcesManagerTest { @DisabledOnRavenwood(blockedBy = PackageManager.class) public void testNewResourcesAfterResourcePathsRegistration() throws PackageManager.NameNotFoundException { - // Inject ResourcesManager instance from this test to the ResourcesManager class so that all - // the static method can interact with this test smoothly. - ResourcesManager oriResourcesManager = ResourcesManager.getInstance(); - ResourcesManager.setInstance(mResourcesManager); - ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_LIB, 0); Resources.registerResourcePaths(TEST_LIB, appInfo); @@ -412,15 +403,11 @@ public class ResourcesManagerTest { CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null); assertNotNull(resources); - String[] resourcePaths = appInfo.getAllApkPaths(); - resourcePaths = removeDuplicates(resourcePaths); ApkAssets[] loadedAssets = resources.getAssets().getApkAssets(); - assertTrue(allResourcePathsLoaded(resourcePaths, loadedAssets)); + assertTrue(containsPath(TEST_LIB, loadedAssets)); // Package resources' paths should be cached in ResourcesManager. assertNotNull(ResourcesManager.getInstance().getRegisteredResourcePaths().get(TEST_LIB)); - // Revert the ResourcesManager instance back. - ResourcesManager.setInstance(oriResourcesManager); } @Test @@ -429,11 +416,6 @@ public class ResourcesManagerTest { @DisabledOnRavenwood(blockedBy = PackageManager.class) public void testExistingResourcesCreatedByConstructorAfterResourcePathsRegistration() throws PackageManager.NameNotFoundException { - // Inject ResourcesManager instance from this test to the ResourcesManager class so that all - // the static method can interact with this test smoothly. - ResourcesManager oriResourcesManager = ResourcesManager.getInstance(); - ResourcesManager.setInstance(mResourcesManager); - // Create a Resources through constructor directly before register resources' paths. final DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); @@ -449,15 +431,11 @@ public class ResourcesManagerTest { assertNotSame(oriResImpl, resources.getImpl()); - String[] resourcePaths = appInfo.getAllApkPaths(); - resourcePaths = removeDuplicates(resourcePaths); ApkAssets[] loadedAssets = resources.getAssets().getApkAssets(); - assertTrue(allResourcePathsLoaded(resourcePaths, loadedAssets)); + assertTrue(containsPath(TEST_LIB, loadedAssets)); // Package resources' paths should be cached in ResourcesManager. assertNotNull(ResourcesManager.getInstance().getRegisteredResourcePaths().get(TEST_LIB)); - // Revert the ResourcesManager instance back. - ResourcesManager.setInstance(oriResourcesManager); } @Test @@ -509,9 +487,6 @@ public class ResourcesManagerTest { @DisabledOnRavenwood(blockedBy = PackageManager.class) public void testNewResourcesWithOutdatedImplAfterResourcePathsRegistration() throws PackageManager.NameNotFoundException { - ResourcesManager oriResourcesManager = ResourcesManager.getInstance(); - ResourcesManager.setInstance(mResourcesManager); - Resources old_resources = mResourcesManager.getResources( null, APP_ONE_RES_DIR, null, null, null, null, null, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null); @@ -532,44 +507,48 @@ public class ResourcesManagerTest { // which has proper asset paths appended. assertNotSame(oldImpl, resources.getImpl()); - String[] resourcePaths = appInfo.getAllApkPaths(); - resourcePaths = removeDuplicates(resourcePaths); ApkAssets[] loadedAssets = resources.getAssets().getApkAssets(); - assertTrue(allResourcePathsLoaded(resourcePaths, loadedAssets)); + assertTrue(containsPath(TEST_LIB, loadedAssets)); // Package resources' paths should be cached in ResourcesManager. assertNotNull(ResourcesManager.getInstance().getRegisteredResourcePaths().get(TEST_LIB)); - // Revert the ResourcesManager instance back. - ResourcesManager.setInstance(oriResourcesManager); } - private static boolean allResourcePathsLoaded(String[] resourcePaths, ApkAssets[] loadedAsset) { - for (int i = 0; i < resourcePaths.length; i++) { - if (!resourcePaths[i].endsWith(".apk")) { - continue; - } - boolean found = false; - for (int j = 0; j < loadedAsset.length; j++) { - if (loadedAsset[j].getAssetPath().equals(resourcePaths[i])) { - found = true; - } - } - if (!found) { - return false; - } - } - return true; + + @Test + @SmallTest + @RequiresFlagsEnabled(Flags.FLAG_REGISTER_RESOURCE_PATHS) + @DisabledOnRavenwood(blockedBy = PackageManager.class) + public void testRegisteringOwnApplicationInfo() { + Resources old_resources = mResourcesManager.getResources( + null, APP_ONE_RES_DIR, null, null, null, null, null, null, + CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null); + assertNotNull(old_resources); + ResourcesImpl oldImpl = old_resources.getImpl(); + + ApplicationInfo appInfo = + InstrumentationRegistry.getInstrumentation().getContext().getApplicationInfo(); + Resources.registerResourcePaths(TEST_LIB, appInfo); + + // Create another resources with identical parameters. + Resources resources = mResourcesManager.getResources( + null, APP_ONE_RES_DIR, null, null, null, null, null, null, + CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null); + assertNotNull(resources); + assertNotSame(oldImpl, resources.getImpl()); + + ApkAssets[] loadedAssets = resources.getAssets().getApkAssets(); + assertTrue(containsPath(appInfo.sourceDir, loadedAssets)); + + assertNotNull(ResourcesManager.getInstance().getRegisteredResourcePaths().get(TEST_LIB)); } - private static String[] removeDuplicates(String[] paths) { - var pathList = new ArrayList<String>(); - var pathSet = new ArraySet<String>(); - final int pathsLen = paths.length; - for (int i = 0; i < pathsLen; i++) { - if (pathSet.add(paths[i])) { - pathList.add(paths[i]); + private static boolean containsPath(String substring, ApkAssets[] assets) { + for (final var asset : assets) { + if (asset.getAssetPath().contains(substring)) { + return true; } } - return pathList.toArray(new String[0]); + return false; } } |