diff options
5 files changed, 155 insertions, 8 deletions
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 77796d9ebdf5..d8564d570a4d 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -855,13 +855,9 @@ public class ResourcesImpl { try { if (file.endsWith(".xml")) { if (file.startsWith("res/color/")) { - ColorStateList csl = loadColorStateList(wrapper, value, id, null); - dr = (csl != null ? new ColorStateListDrawable(csl) : null); + dr = loadColorOrXmlDrawable(wrapper, value, id, density, file); } else { - final XmlResourceParser rp = loadXmlResourceParser( - file, id, value.assetCookie, "drawable"); - dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null); - rp.close(); + dr = loadXmlDrawable(wrapper, value, id, density, file); } } else { final InputStream is = mAssets.openNonAsset( @@ -915,6 +911,33 @@ public class ResourcesImpl { return dr; } + private Drawable loadColorOrXmlDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, + int id, int density, String file) { + try { + ColorStateList csl = loadColorStateList(wrapper, value, id, null); + return new ColorStateListDrawable(csl); + } catch (NotFoundException originalException) { + // If we fail to load as color, try as normal XML drawable + try { + return loadXmlDrawable(wrapper, value, id, density, file); + } catch (Exception ignored) { + // If fallback also fails, throw the original exception + throw originalException; + } + } + } + + private Drawable loadXmlDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, + int id, int density, String file) + throws IOException, XmlPullParserException { + try ( + XmlResourceParser rp = + loadXmlResourceParser(file, id, value.assetCookie, "drawable") + ) { + return Drawable.createFromXmlForDensity(wrapper, rp, density, null); + } + } + /** * Loads a font from XML or resources stream. */ diff --git a/core/tests/coretests/README b/core/tests/coretests/README index ea282a0ebb3a..34beb454b397 100644 --- a/core/tests/coretests/README +++ b/core/tests/coretests/README @@ -30,9 +30,9 @@ Next, install the resulting APK and run tests as you would normal JUnit tests: adb install -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk adb shell am instrument -w \ - com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner + com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner -To run a tests within a specific package, add the following argument AFTER -w: +To run a tests within a specific package, add -e AFTER -w and before the runner class: -e package android.content.pm diff --git a/core/tests/coretests/res/color/drawable_in_color_dir_invalid.xml b/core/tests/coretests/res/color/drawable_in_color_dir_invalid.xml new file mode 100644 index 000000000000..8d630b09ef42 --- /dev/null +++ b/core/tests/coretests/res/color/drawable_in_color_dir_invalid.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- This drawable is purposely in the color directory to test a backwards compatible fallback. --> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@android:id/icon" android:drawable="@string/app_name" /> +</layer-list>
\ No newline at end of file diff --git a/core/tests/coretests/res/color/drawable_in_color_dir_valid.xml b/core/tests/coretests/res/color/drawable_in_color_dir_valid.xml new file mode 100644 index 000000000000..d1404753d57a --- /dev/null +++ b/core/tests/coretests/res/color/drawable_in_color_dir_valid.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- This drawable is purposely in the color directory to test a backwards compatible fallback. --> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@android:id/background" android:drawable="@drawable/test32x24" /> + <item android:id="@android:id/icon" android:drawable="@drawable/test16x12" /> +</layer-list>
\ No newline at end of file diff --git a/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java b/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java new file mode 100644 index 000000000000..c4df88b49935 --- /dev/null +++ b/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.graphics.drawable.ColorStateListDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.frameworks.coretests.R; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ResourcesDrawableTest { + + @Test + public void testLoadColorAsDrawable() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Resources resources = context.getResources(); + Drawable drawable = resources.getDrawable(R.color.color1); + assertTrue(drawable instanceof ColorStateListDrawable); + } + + @Test + public void testLoadColorAsDrawableFailureThrowsOriginalException() throws Throwable { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Resources resources = context.getResources(); + + Exception exception = null; + + try { + resources.getDrawable(R.color.drawable_in_color_dir_invalid); + } catch (Exception e) { + exception = e; + } + + assertNotNull( + "Loading drawable_in_color_dir_invalid should throw an exception", + exception + ); + + assertEquals( + "Can't find ColorStateList from drawable resource ID #0x" + + Integer.toHexString(R.color.drawable_in_color_dir_invalid), + exception.getCause().getCause().getMessage() + ); + } + + @Test + public void testLoadNormalDrawableInColorDir() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Resources resources = context.getResources(); + Drawable drawable = resources.getDrawable(R.color.drawable_in_color_dir_valid); + assertTrue(drawable instanceof LayerDrawable); + } +} |