From e272307dd3319bbdc24e349a5334654a397f8629 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 11 Feb 2020 15:51:29 -0800 Subject: API council changes for ResourcesLoaders Per API council guidance, setLoaders, getLoaders, and clearLoaders are no longer part of the public API. addLoader and removeLoader are now consume variadic loaders. Bug: 142716192 Test: atest FrameworksResourceLoaderTests Change-Id: If29d47b526ae6acd582b14206b2c6372f3c497be --- api/current.txt | 7 +- core/java/android/content/res/Resources.java | 107 ++++++++++----------- .../content/res/loader/ResourcesLoader.java | 4 +- .../res/loader/test/DirectoryAssetsProviderTest.kt | 2 +- .../res/loader/test/ResourceLoaderAssetsTest.kt | 10 +- .../res/loader/test/ResourceLoaderValuesTest.kt | 92 +++++++++--------- 6 files changed, 111 insertions(+), 111 deletions(-) diff --git a/api/current.txt b/api/current.txt index a7367e8c4943..c07b8e2850e7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12700,8 +12700,7 @@ package android.content.res { public class Resources { ctor @Deprecated public Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); - method public void addLoader(@NonNull android.content.res.loader.ResourcesLoader); - method public void clearLoaders(); + method public void addLoaders(@NonNull android.content.res.loader.ResourcesLoader...); method public final void finishPreloading(); method public final void flushLayoutCache(); method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimRes @AnimatorRes int) throws android.content.res.Resources.NotFoundException; @@ -12728,7 +12727,6 @@ package android.content.res { method @NonNull public int[] getIntArray(@ArrayRes int) throws android.content.res.Resources.NotFoundException; method public int getInteger(@IntegerRes int) throws android.content.res.Resources.NotFoundException; method @NonNull public android.content.res.XmlResourceParser getLayout(@LayoutRes int) throws android.content.res.Resources.NotFoundException; - method @NonNull public java.util.List getLoaders(); method @Deprecated public android.graphics.Movie getMovie(@RawRes int) throws android.content.res.Resources.NotFoundException; method @NonNull public String getQuantityString(@PluralsRes int, int, java.lang.Object...) throws android.content.res.Resources.NotFoundException; method @NonNull public String getQuantityString(@PluralsRes int, int) throws android.content.res.Resources.NotFoundException; @@ -12756,8 +12754,7 @@ package android.content.res { method public android.content.res.AssetFileDescriptor openRawResourceFd(@RawRes int) throws android.content.res.Resources.NotFoundException; method public void parseBundleExtra(String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException; method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; - method public void removeLoader(@NonNull android.content.res.loader.ResourcesLoader); - method public void setLoaders(@NonNull java.util.List); + method public void removeLoaders(@NonNull android.content.res.loader.ResourcesLoader...); method @Deprecated public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); field @AnyRes public static final int ID_NULL = 0; // 0x0 } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 471e83c4c3eb..cb809da3b867 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -62,6 +62,7 @@ import android.view.DisplayAdjustments; import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; @@ -112,7 +113,7 @@ public class Resources { static final String TAG = "Resources"; private static final Object sSync = new Object(); - private final Object mLock = new Object(); + private final Object mUpdateLock = new Object(); // Used by BridgeResources in layoutlib @UnsupportedAppUsage @@ -139,6 +140,7 @@ public class Resources { @UnsupportedAppUsage final ClassLoader mClassLoader; + @GuardedBy("mUpdateLock") private UpdateCallbacks mCallbacks = null; /** @@ -2375,6 +2377,7 @@ public class Resources { * *

Loaders are listed in increasing precedence order. A loader will override the resources * and assets of loaders listed before itself. + * @hide */ @NonNull public List getLoaders() { @@ -2382,87 +2385,81 @@ public class Resources { } /** - * Appends a loader to the end of the loader list. If the loader is already present in the - * loader list, the list will not be modified. - * - * @param loader the loader to add - */ - public void addLoader(@NonNull ResourcesLoader loader) { - synchronized (mLock) { - checkCallbacksRegistered(); - - final List loaders = new ArrayList<>( - mResourcesImpl.getAssets().getLoaders()); - if (loaders.contains(loader)) { - return; - } - - loaders.add(loader); - mCallbacks.onLoadersChanged(this, loaders); - loader.registerOnProvidersChangedCallback(this, mCallbacks); - } - } - - /** - * Removes a loader from the loaders. If the loader is not present in the loader list, the list + * Adds a loader to the list of loaders. If the loader is already present in the list, the list * will not be modified. * - * @param loader the loader to remove + * @param loaders the loaders to add */ - public void removeLoader(@NonNull ResourcesLoader loader) { - synchronized (mLock) { + public void addLoaders(@NonNull ResourcesLoader... loaders) { + synchronized (mUpdateLock) { checkCallbacksRegistered(); + final List newLoaders = + new ArrayList<>(mResourcesImpl.getAssets().getLoaders()); + final ArraySet loaderSet = new ArraySet<>(newLoaders); + + for (int i = 0; i < loaders.length; i++) { + final ResourcesLoader loader = loaders[i]; + if (!loaderSet.contains(loader)) { + newLoaders.add(loader); + } + } - final List loaders = new ArrayList<>( - mResourcesImpl.getAssets().getLoaders()); - if (!loaders.remove(loader)) { + if (loaderSet.size() == newLoaders.size()) { return; } - mCallbacks.onLoadersChanged(this, loaders); - loader.unregisterOnProvidersChangedCallback(this); + mCallbacks.onLoadersChanged(this, newLoaders); + for (int i = loaderSet.size(), n = newLoaders.size(); i < n; i++) { + newLoaders.get(i).registerOnProvidersChangedCallback(this, mCallbacks); + } } } /** - * Sets the list of loaders. + * Removes loaders from the list of loaders. If the loader is not present in the list, the list + * will not be modified. * - * @param loaders the new loaders + * @param loaders the loaders to remove */ - public void setLoaders(@NonNull List loaders) { - synchronized (mLock) { + public void removeLoaders(@NonNull ResourcesLoader... loaders) { + synchronized (mUpdateLock) { checkCallbacksRegistered(); - + final ArraySet removedLoaders = new ArraySet<>(loaders); + final List newLoaders = new ArrayList<>(); final List oldLoaders = mResourcesImpl.getAssets().getLoaders(); - int index = 0; - boolean modified = loaders.size() != oldLoaders.size(); - final ArraySet seenLoaders = new ArraySet<>(); - for (final ResourcesLoader loader : loaders) { - if (!seenLoaders.add(loader)) { - throw new IllegalArgumentException("Loader " + loader + " present twice"); - } - if (!modified && oldLoaders.get(index++) != loader) { - modified = true; + for (int i = 0, n = oldLoaders.size(); i < n; i++) { + final ResourcesLoader loader = oldLoaders.get(i); + if (!removedLoaders.contains(loader)) { + newLoaders.add(loader); } } - if (!modified) { + if (oldLoaders.size() == newLoaders.size()) { return; } - mCallbacks.onLoadersChanged(this, loaders); - for (int i = 0, n = oldLoaders.size(); i < n; i++) { - oldLoaders.get(i).unregisterOnProvidersChangedCallback(this); - } - for (ResourcesLoader newLoader : loaders) { - newLoader.registerOnProvidersChangedCallback(this, mCallbacks); + mCallbacks.onLoadersChanged(this, newLoaders); + for (int i = 0; i < loaders.length; i++) { + loaders[i].unregisterOnProvidersChangedCallback(this); } } } - /** Removes all {@link ResourcesLoader ResourcesLoader(s)}. */ + /** + * Removes all {@link ResourcesLoader ResourcesLoader(s)}. + * @hide + */ + @VisibleForTesting public void clearLoaders() { - setLoaders(Collections.emptyList()); + synchronized (mUpdateLock) { + checkCallbacksRegistered(); + final List newLoaders = Collections.emptyList(); + final List oldLoaders = mResourcesImpl.getAssets().getLoaders(); + mCallbacks.onLoadersChanged(this, newLoaders); + for (ResourcesLoader loader : oldLoaders) { + loader.unregisterOnProvidersChangedCallback(this); + } + } } } diff --git a/core/java/android/content/res/loader/ResourcesLoader.java b/core/java/android/content/res/loader/ResourcesLoader.java index 69daceeaffc2..58fec603a2d5 100644 --- a/core/java/android/content/res/loader/ResourcesLoader.java +++ b/core/java/android/content/res/loader/ResourcesLoader.java @@ -40,8 +40,8 @@ import java.util.List; * of {@link ResourcesProvider ResourcesProvider(s)} a loader contains propagates to all Resources * objects that use the loader. * - *

Loaders retrieved with {@link Resources#getLoaders()} are listed in increasing precedence - * order. A loader will override the resources and assets of loaders listed before itself. + *

Loaders must be added to Resources objects in increasing precedence order. A loader will + * override the resources and assets of loaders added before itself. * *

Providers retrieved with {@link #getProviders()} are listed in increasing precedence order. A * provider will override the resources and assets of providers listed before itself. diff --git a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/DirectoryAssetsProviderTest.kt b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/DirectoryAssetsProviderTest.kt index 9e94bdc8a081..afe9d7f19f0d 100644 --- a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/DirectoryAssetsProviderTest.kt +++ b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/DirectoryAssetsProviderTest.kt @@ -44,7 +44,7 @@ class DirectoryAssetsProviderTest : ResourceLoaderTestBase() { testDir = context.filesDir.resolve("DirectoryAssetsProvider_${testName.methodName}") assetsProvider = DirectoryAssetsProvider(testDir) loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) } @After diff --git a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderAssetsTest.kt b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderAssetsTest.kt index e3ba93d64b0f..da5092de0627 100644 --- a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderAssetsTest.kt +++ b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderAssetsTest.kt @@ -119,7 +119,7 @@ class ResourceLoaderAssetsTest : ResourceLoaderTestBase() { val loader = ResourcesLoader() loader.providers = listOf(one, two) - resources.addLoader(loader) + resources.addLoaders(loader) assertOpenedAsset() inOrder(two.assetsProvider, one.assetsProvider).apply { @@ -149,7 +149,7 @@ class ResourceLoaderAssetsTest : ResourceLoaderTestBase() { val loader2 = ResourcesLoader() loader2.addProvider(two) - resources.loaders = listOf(loader1, loader2) + resources.addLoaders(loader1, loader2) assertOpenedAsset() inOrder(two.assetsProvider, one.assetsProvider).apply { @@ -170,7 +170,7 @@ class ResourceLoaderAssetsTest : ResourceLoaderTestBase() { val loader = ResourcesLoader() val one = ResourcesProvider.empty(assetsProvider1) val two = ResourcesProvider.empty(assetsProvider2) - resources.addLoader(loader) + resources.addLoaders(loader) loader.providers = listOf(one, two) assertOpenedAsset() @@ -186,7 +186,7 @@ class ResourceLoaderAssetsTest : ResourceLoaderTestBase() { val loader = ResourcesLoader() val one = ResourcesProvider.empty(assetsProvider1) val two = ResourcesProvider.empty(assetsProvider2) - resources.addLoader(loader) + resources.addLoaders(loader) loader.providers = listOf(one, two) assertOpenedAsset() @@ -202,7 +202,7 @@ class ResourceLoaderAssetsTest : ResourceLoaderTestBase() { val loader = ResourcesLoader() val one = ResourcesProvider.empty(assetsProvider1) val two = ResourcesProvider.empty(assetsProvider2) - resources.addLoader(loader) + resources.addLoaders(loader) loader.providers = listOf(one, two) assertOpenedAsset() diff --git a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt index 0cc56d721651..16eafcd451c2 100644 --- a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt +++ b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt @@ -192,13 +192,13 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { } @Test - fun addMultipleProviders() { + fun addProvidersRepeatedly() { val originalValue = getValue() val testOne = openOne() val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.addProvider(testOne) assertEquals(valueOne, getValue()) @@ -213,25 +213,25 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { } @Test - fun addMultipleLoaders() { + fun addLoadersRepeatedly() { val originalValue = getValue() val testOne = openOne() val testTwo = openTwo() val loader1 = ResourcesLoader() val loader2 = ResourcesLoader() - resources.addLoader(loader1) + resources.addLoaders(loader1) loader1.addProvider(testOne) assertEquals(valueOne, getValue()) - resources.addLoader(loader2) + resources.addLoaders(loader2) loader2.addProvider(testTwo) assertEquals(valueTwo, getValue()) - resources.removeLoader(loader1) + resources.removeLoaders(loader1) assertEquals(valueTwo, getValue()) - resources.removeLoader(loader2) + resources.removeLoaders(loader2) assertEquals(originalValue, getValue()) } @@ -242,7 +242,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.providers = listOf(testOne, testTwo) assertEquals(valueTwo, getValue()) @@ -254,20 +254,20 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { } @Test - fun setMultipleLoaders() { + fun addMultipleLoaders() { val originalValue = getValue() val loader1 = ResourcesLoader() loader1.addProvider(openOne()) val loader2 = ResourcesLoader() loader2.addProvider(openTwo()) - resources.loaders = listOf(loader1, loader2) + resources.addLoaders(loader1, loader2) assertEquals(valueTwo, getValue()) - resources.removeLoader(loader2) + resources.removeLoaders(loader2) assertEquals(valueOne, getValue()) - resources.loaders = Collections.emptyList() + resources.removeLoaders(loader1) assertEquals(originalValue, getValue()) } @@ -291,7 +291,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.addProvider(testOne) loader.addProvider(testTwo) loader.addProvider(testOne) @@ -308,9 +308,9 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val loader2 = ResourcesLoader() loader2.addProvider(openTwo()) - resources.addLoader(loader1) - resources.addLoader(loader2) - resources.addLoader(loader1) + resources.addLoaders(loader1) + resources.addLoaders(loader2) + resources.addLoaders(loader1) assertEquals(2, resources.loaders.size) assertEquals(resources.loaders[0], loader1) @@ -323,7 +323,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.addProvider(testOne) loader.addProvider(testTwo) @@ -341,12 +341,16 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val loader2 = ResourcesLoader() loader2.addProvider(openTwo()) - resources.loaders = listOf(loader1, loader2) - resources.removeLoader(loader1) - resources.removeLoader(loader1) + resources.addLoaders(loader1, loader2) + resources.removeLoaders(loader1) + resources.removeLoaders(loader1) assertEquals(1, resources.loaders.size) assertEquals(resources.loaders[0], loader2) + + resources.removeLoaders(loader2, loader2) + + assertEquals(0, resources.loaders.size) } @Test @@ -355,7 +359,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.providers = listOf(testOne, testTwo) loader.providers = listOf(testOne, testTwo) @@ -365,14 +369,14 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { } @Test - fun repeatedSetLoaders() { + fun repeatedAddMultipleLoaders() { val loader1 = ResourcesLoader() loader1.addProvider(openOne()) val loader2 = ResourcesLoader() loader2.addProvider(openTwo()) - resources.loaders = listOf(loader1, loader2) - resources.loaders = listOf(loader1, loader2) + resources.addLoaders(loader1, loader2) + resources.addLoaders(loader1, loader2) assertEquals(2, resources.loaders.size) assertEquals(resources.loaders[0], loader1) @@ -386,7 +390,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.addProvider(testOne) loader.addProvider(testTwo) assertEquals(valueTwo, getValue()) @@ -414,20 +418,20 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val loader2 = ResourcesLoader() loader2.addProvider(testTwo) - resources.addLoader(loader1) - resources.addLoader(loader2) + resources.addLoaders(loader1) + resources.addLoaders(loader2) assertEquals(valueTwo, getValue()) - resources.removeLoader(loader1) + resources.removeLoaders(loader1) assertEquals(valueTwo, getValue()) - resources.addLoader(loader1) + resources.addLoaders(loader1) assertEquals(valueOne, getValue()) - resources.removeLoader(loader2) + resources.removeLoaders(loader2) assertEquals(valueOne, getValue()) - resources.removeLoader(loader1) + resources.removeLoaders(loader1) assertEquals(originalValue, getValue()) } @@ -444,10 +448,11 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val loader2 = ResourcesLoader() loader2.providers = listOf(testThree, testFour) - resources.loaders = listOf(loader1, loader2) + resources.addLoaders(loader1, loader2) assertEquals(valueFour, getValue()) - resources.loaders = listOf(loader2, loader1) + resources.removeLoaders(loader1) + resources.addLoaders(loader1) assertEquals(valueTwo, getValue()) loader1.removeProvider(testTwo) @@ -471,7 +476,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val loader2 = ResourcesLoader() loader2.addProvider(openTwo()) - resources.loaders = listOf(loader1) + resources.addLoaders(loader1) assertEquals(valueOne, getValue()) // The child context should include the loaders of the original context. @@ -479,12 +484,12 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { assertEquals(valueOne, getValue(childContext)) // Changing the loaders of the child context should not affect the original context. - childContext.resources.loaders = listOf(loader1, loader2) + childContext.resources.addLoaders(loader2) assertEquals(valueOne, getValue()) assertEquals(valueTwo, getValue(childContext)) // Changing the loaders of the original context should not affect the child context. - resources.removeLoader(loader1) + resources.removeLoaders(loader1) assertEquals(originalValue, getValue()) assertEquals(valueTwo, getValue(childContext)) @@ -506,7 +511,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { val testTwo = openTwo() val loader = ResourcesLoader() - resources.addLoader(loader) + resources.addLoaders(loader) loader.addProvider(testOne) assertEquals(valueOne, getValue()) @@ -527,7 +532,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { assertEquals(originalValue, getValue()) assertEquals(originalValue, getValue(childContext2)) - childContext2.resources.addLoader(loader) + childContext2.resources.addLoaders(loader) assertEquals(originalValue, getValue()) assertEquals(valueTwo, getValue(childContext)) assertEquals(valueTwo, getValue(childContext2)) @@ -539,7 +544,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { loader.addProvider(openOne()) val applicationContext = context.applicationContext - applicationContext.resources.addLoader(loader) + applicationContext.resources.addLoaders(loader) assertEquals(valueOne, getValue(applicationContext)) val activity = mTestActivityRule.launchActivity(Intent()) @@ -556,7 +561,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { loader2.addProvider(openTwo()) val applicationContext = context.applicationContext - applicationContext.resources.addLoader(loader1) + applicationContext.resources.addLoaders(loader1) assertEquals(valueOne, getValue(applicationContext)) var token: IBinder? = null @@ -569,7 +574,7 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { assertEquals(valueOne, getValue(applicationContext)) assertEquals(valueOne, getValue(activity)) - activity.resources.addLoader(loader2) + activity.resources.addLoaders(loader2) assertEquals(valueOne, getValue(applicationContext)) assertEquals(valueTwo, getValue(activity)) @@ -598,10 +603,11 @@ class ResourceLoaderValuesTest : ResourceLoaderTestBase() { loader2.addProvider(provider1) loader2.addProvider(openTwo()) - resources.loaders = listOf(loader1, loader2) + resources.addLoaders(loader1, loader2) assertEquals(valueTwo, getValue()) - resources.loaders = listOf(loader2, loader1) + resources.removeLoaders(loader1) + resources.addLoaders(loader1) assertEquals(valueOne, getValue()) assertEquals(2, resources.assets.apkAssets.count { apkAssets -> apkAssets.isForLoader }) -- cgit v1.2.3-59-g8ed1b