summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/res/Resources.java52
-rw-r--r--core/java/android/content/res/ResourcesImpl.java31
-rw-r--r--core/java/android/content/res/TypedArray.java17
-rw-r--r--graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java25
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java51
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java71
-rw-r--r--graphics/java/android/graphics/drawable/DrawableInflater.java12
-rw-r--r--graphics/java/android/graphics/drawable/DrawableWrapper.java13
8 files changed, 201 insertions, 71 deletions
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 408bee8a0223..b559604ea14e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -815,14 +815,7 @@ public class Resources {
*/
public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue();
- try {
- final ResourcesImpl impl = mResourcesImpl;
- impl.getValue(id, value, true);
- return impl.loadDrawable(this, value, id, theme, true);
- } finally {
- releaseTempTypedValue(value);
- }
+ return getDrawableForDensity(id, 0, theme);
}
/**
@@ -844,7 +837,9 @@ public class Resources {
* This integer encodes the package, type, and resource entry.
* The value 0 is an invalid identifier.
* @param density the desired screen density indicated by the resource as
- * found in {@link DisplayMetrics}.
+ * found in {@link DisplayMetrics}. A value of 0 means to use the
+ * density returned from {@link #getConfiguration()}.
+ * This is equivalent to calling {@link #getDrawable(int)}.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
@@ -865,7 +860,9 @@ public class Resources {
* This integer encodes the package, type, and resource entry.
* The value 0 is an invalid identifier.
* @param density The desired screen density indicated by the resource as
- * found in {@link DisplayMetrics}.
+ * found in {@link DisplayMetrics}. A value of 0 means to use the
+ * density returned from {@link #getConfiguration()}.
+ * This is equivalent to calling {@link #getDrawable(int, Theme)}.
* @param theme The theme used to style the drawable attributes, may be {@code null}.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
@@ -876,37 +873,16 @@ public class Resources {
try {
final ResourcesImpl impl = mResourcesImpl;
impl.getValueForDensity(id, density, value, true);
-
- // If the drawable's XML lives in our current density qualifier,
- // it's okay to use a scaled version from the cache. Otherwise, we
- // need to actually load the drawable from XML.
- final DisplayMetrics metrics = impl.getDisplayMetrics();
- final boolean useCache = value.density == metrics.densityDpi;
-
- /*
- * Pretend the requested density is actually the display density. If
- * the drawable returned is not the requested density, then force it
- * to be scaled later by dividing its density by the ratio of
- * requested density to actual device density. Drawables that have
- * undefined density or no density don't need to be handled here.
- */
- if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
- if (value.density == density) {
- value.density = metrics.densityDpi;
- } else {
- value.density = (value.density * metrics.densityDpi) / density;
- }
- }
- return impl.loadDrawable(this, value, id, theme, useCache);
+ return impl.loadDrawable(this, value, id, density, theme);
} finally {
releaseTempTypedValue(value);
}
}
@NonNull
- Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
+ Drawable loadDrawable(@NonNull TypedValue value, int id, int density, @Nullable Theme theme)
throws NotFoundException {
- return mResourcesImpl.loadDrawable(this, value, id, theme, true);
+ return mResourcesImpl.loadDrawable(this, value, id, density, theme);
}
/**
@@ -1221,8 +1197,7 @@ public class Resources {
* used to open drawable, sound, and raw resources; it will fail on string
* and color resources.
*
- * @param id The resource identifier to open, as generated by the appt
- * tool.
+ * @param id The resource identifier to open, as generated by the aapt tool.
*
* @return InputStream Access to the resource data.
*
@@ -1278,7 +1253,7 @@ public class Resources {
* used to open drawable, sound, and raw resources; it will fail on string
* and color resources.
*
- * @param id The resource identifier to open, as generated by the appt tool.
+ * @param id The resource identifier to open, as generated by the aapt tool.
* @param value The TypedValue object to hold the resource information.
*
* @return InputStream Access to the resource data.
@@ -1300,8 +1275,7 @@ public class Resources {
* as uncompressed data, which typically includes things like mp3 files
* and png images.
*
- * @param id The resource identifier to open, as generated by the appt
- * tool.
+ * @param id The resource identifier to open, as generated by the aapt tool.
*
* @return AssetFileDescriptor A new file descriptor you can use to read
* the resource. This includes the file descriptor itself, as well as the
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index f9acab97b40b..02ddc89f177e 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -523,8 +523,27 @@ public class ResourcesImpl {
}
@Nullable
- Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
- boolean useCache) throws NotFoundException {
+ Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id,
+ int density, @Nullable Resources.Theme theme)
+ throws NotFoundException {
+ // If the drawable's XML lives in our current density qualifier,
+ // it's okay to use a scaled version from the cache. Otherwise, we
+ // need to actually load the drawable from XML.
+ final boolean useCache = density == 0 || value.density == mMetrics.densityDpi;
+
+ // Pretend the requested density is actually the display density. If
+ // the drawable returned is not the requested density, then force it
+ // to be scaled later by dividing its density by the ratio of
+ // requested density to actual device density. Drawables that have
+ // undefined density or no density don't need to be handled here.
+ if (density > 0 && value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
+ if (value.density == density) {
+ value.density = mMetrics.densityDpi;
+ } else {
+ value.density = (value.density * mMetrics.densityDpi) / density;
+ }
+ }
+
try {
if (TRACE_FOR_PRELOAD) {
// Log only framework resources
@@ -576,7 +595,7 @@ public class ResourcesImpl {
} else if (isColorDrawable) {
dr = new ColorDrawable(value.data);
} else {
- dr = loadDrawableForCookie(wrapper, value, id, null);
+ dr = loadDrawableForCookie(wrapper, value, id, density, null);
}
// Determine if the drawable has unresolved theme attributes. If it
@@ -691,8 +710,8 @@ public class ResourcesImpl {
/**
* Loads a drawable from XML or resources stream.
*/
- private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
- Resources.Theme theme) {
+ private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value,
+ int id, int density, @Nullable Resources.Theme theme) {
if (value.string == null) {
throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
+ Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
@@ -722,7 +741,7 @@ public class ResourcesImpl {
if (file.endsWith(".xml")) {
final XmlResourceParser rp = loadXmlResourceParser(
file, id, value.assetCookie, "drawable");
- dr = Drawable.createFromXml(wrapper, rp, theme);
+ dr = Drawable.createFromXmlForDensity(wrapper, rp, density, theme);
rp.close();
} else {
final InputStream is = mAssets.openNonAsset(
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 88bb1a4ce3b9..0b0f048196a5 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -923,6 +923,15 @@ public class TypedArray {
*/
@Nullable
public Drawable getDrawable(@StyleableRes int index) {
+ return getDrawableForDensity(index, 0);
+ }
+
+ /**
+ * Version of {@link #getDrawable(int)} that accepts an override density.
+ * @hide
+ */
+ @Nullable
+ public Drawable getDrawableForDensity(@StyleableRes int index, int density) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
@@ -933,7 +942,13 @@ public class TypedArray {
throw new UnsupportedOperationException(
"Failed to resolve attribute at index " + index + ": " + value);
}
- return mResources.loadDrawable(value, value.resourceId, mTheme);
+
+ if (density > 0) {
+ // If the density is overridden, the value in the TypedArray will not reflect this.
+ // Do a separate lookup of the resourceId with the density override.
+ mResources.getValueForDensity(value.resourceId, density, value, true);
+ }
+ return mResources.loadDrawable(value, value.resourceId, density, mTheme);
}
return null;
}
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 283a3e2b0b1e..ffadad9d68c5 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -16,8 +16,6 @@
package android.graphics.drawable;
-import static android.graphics.drawable.Drawable.obtainAttributes;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -218,14 +216,16 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
// The density may have changed since the last update. This will
// apply scaling to any existing constant state properties.
- final int density = Drawable.resolveDensity(r, 0);
- state.setDensity(density);
+ final int deviceDensity = Drawable.resolveDensity(r, 0);
+ state.setDensity(deviceDensity);
+ state.mSrcDensityOverride = mSrcDensityOverride;
final ChildDrawable[] array = state.mChildren;
for (int i = 0; i < state.mChildren.length; i++) {
final ChildDrawable layer = array[i];
- layer.setDensity(density);
+ layer.setDensity(deviceDensity);
}
+
inflateLayers(r, parser, attrs, theme);
}
@@ -444,7 +444,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
/**
* Inflates child layers using the specified parser.
*/
- void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
+ private void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
final LayerState state = mLayerState;
@@ -491,7 +491,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
}
// We found a child drawable. Take ownership.
- layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
+ layer.mDrawable = Drawable.createFromXmlInnerForDensity(r, parser, attrs,
+ mLayerState.mSrcDensityOverride, theme);
layer.mDrawable.setCallback(this);
state.mChildrenChangingConfigurations |=
layer.mDrawable.getChangingConfigurations();
@@ -509,7 +510,8 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
// Extract the theme attributes, if any.
layer.mThemeAttrs = a.extractThemeAttrs();
- Drawable dr = a.getDrawable(R.styleable.AdaptiveIconDrawableLayer_drawable);
+ Drawable dr = a.getDrawableForDensity(R.styleable.AdaptiveIconDrawableLayer_drawable,
+ state.mSrcDensityOverride);
if (dr != null) {
if (layer.mDrawable != null) {
// It's possible that a drawable was already set, in which case
@@ -951,7 +953,13 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
final static int N_CHILDREN = 2;
ChildDrawable[] mChildren;
+ // The density at which to render the drawable and its children.
int mDensity;
+
+ // The density to use when inflating/looking up the children drawables. A value of 0 means
+ // use the system's density.
+ int mSrcDensityOverride = 0;
+
int mOpacityOverride = PixelFormat.UNKNOWN;
@Config int mChangingConfigurations;
@@ -986,6 +994,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
mAutoMirrored = orig.mAutoMirrored;
mThemeAttrs = orig.mThemeAttrs;
mOpacityOverride = orig.mOpacityOverride;
+ mSrcDensityOverride = orig.mSrcDensityOverride;
} else {
for (int i = 0; i < N_CHILDREN; i++) {
mChildren[i] = new ChildDrawable(mDensity);
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 5004667c1089..e3740e3cf284 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -41,6 +41,7 @@ import android.graphics.Xfermode;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
+import android.util.TypedValue;
import android.view.Gravity;
import com.android.internal.R;
@@ -49,6 +50,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.io.InputStream;
/**
* A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a
@@ -749,7 +751,7 @@ public class BitmapDrawable extends Drawable {
super.inflate(r, parser, attrs, theme);
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.BitmapDrawable);
- updateStateFromTypedArray(a);
+ updateStateFromTypedArray(a, mSrcDensityOverride);
verifyRequiredAttributes(a);
a.recycle();
@@ -775,7 +777,8 @@ public class BitmapDrawable extends Drawable {
/**
* Updates the constant state from the values in the typed array.
*/
- private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
+ private void updateStateFromTypedArray(TypedArray a, int srcDensityOverride)
+ throws XmlPullParserException {
final Resources r = a.getResources();
final BitmapState state = mBitmapState;
@@ -785,9 +788,37 @@ public class BitmapDrawable extends Drawable {
// Extract the theme attributes, if any.
state.mThemeAttrs = a.extractThemeAttrs();
+ state.mSrcDensityOverride = srcDensityOverride;
+
+ state.mTargetDensity = Drawable.resolveDensity(r, 0);
+
final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0);
if (srcResId != 0) {
- final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId);
+ final TypedValue value = new TypedValue();
+ r.getValueForDensity(srcResId, srcDensityOverride, value, true);
+
+ // Pretend the requested density is actually the display density. If
+ // the drawable returned is not the requested density, then force it
+ // to be scaled later by dividing its density by the ratio of
+ // requested density to actual device density. Drawables that have
+ // undefined density or no density don't need to be handled here.
+ if (srcDensityOverride > 0 && value.density > 0
+ && value.density != TypedValue.DENSITY_NONE) {
+ if (value.density == srcDensityOverride) {
+ value.density = r.getDisplayMetrics().densityDpi;
+ } else {
+ value.density =
+ (value.density * r.getDisplayMetrics().densityDpi) / srcDensityOverride;
+ }
+ }
+
+ Bitmap bitmap = null;
+ try (InputStream is = r.openRawResource(srcResId, value)) {
+ bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
+ } catch (Exception e) {
+ // Do nothing and pick up the error below.
+ }
+
if (bitmap == null) {
throw new XmlPullParserException(a.getPositionDescription() +
": <bitmap> requires a valid 'src' attribute");
@@ -796,8 +827,6 @@ public class BitmapDrawable extends Drawable {
state.mBitmap = bitmap;
}
- state.mTargetDensity = r.getDisplayMetrics().densityDpi;
-
final boolean defMipMap = state.mBitmap != null ? state.mBitmap.hasMipMap() : false;
setMipMap(a.getBoolean(R.styleable.BitmapDrawable_mipMap, defMipMap));
@@ -839,8 +868,6 @@ public class BitmapDrawable extends Drawable {
if (tileModeY != TILE_MODE_UNDEFINED) {
setTileModeY(parseTileMode(tileModeY));
}
-
- state.mTargetDensity = Drawable.resolveDensity(r, 0);
}
@Override
@@ -855,7 +882,7 @@ public class BitmapDrawable extends Drawable {
if (state.mThemeAttrs != null) {
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable);
try {
- updateStateFromTypedArray(a);
+ updateStateFromTypedArray(a, state.mSrcDensityOverride);
} catch (XmlPullParserException e) {
rethrowAsRuntimeException(e);
} finally {
@@ -929,7 +956,14 @@ public class BitmapDrawable extends Drawable {
float mBaseAlpha = 1.0f;
Shader.TileMode mTileModeX = null;
Shader.TileMode mTileModeY = null;
+
+ // The density to use when looking up the bitmap in Resources. A value of 0 means use
+ // the system's density.
+ int mSrcDensityOverride = 0;
+
+ // The density at which to render the bitmap.
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+
boolean mAutoMirrored = false;
@Config int mChangingConfigurations;
@@ -949,6 +983,7 @@ public class BitmapDrawable extends Drawable {
mGravity = bitmapState.mGravity;
mTileModeX = bitmapState.mTileModeX;
mTileModeY = bitmapState.mTileModeY;
+ mSrcDensityOverride = bitmapState.mSrcDensityOverride;
mTargetDensity = bitmapState.mTargetDensity;
mBaseAlpha = bitmapState.mBaseAlpha;
mPaint = new Paint(bitmapState.mPaint);
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 44fb1c75684e..f17cd768c386 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -189,6 +189,21 @@ public abstract class Drawable {
private int mLayoutDirection;
/**
+ * The source density to use when looking up resources using
+ * {@link Resources#getDrawableForDensity(int, int, Theme)}. A value of 0 means there is no
+ * override and the system density will be used.
+ *
+ * NOTE(adamlesinski): This is transient state used to get around the public API that does not
+ * account for source density overrides. Custom drawables implemented by developers do not need
+ * to be aware of the source density override, as it is only used by Launcher to load higher
+ * resolution icons from external Resources packages, which do not execute custom code.
+ * This is all to support the {@link Resources#getDrawableForDensity(int, int, Theme)} API.
+ *
+ * @hide
+ */
+ protected int mSrcDensityOverride = 0;
+
+ /**
* Draw in its bounds (set via setBounds) respecting optional effects such
* as alpha (set via setAlpha) and color filter (set via setColorFilter).
*
@@ -1197,7 +1212,8 @@ public abstract class Drawable {
* create resources in XML, see
* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*/
- public static Drawable createFromXml(Resources r, XmlPullParser parser)
+ @NonNull
+ public static Drawable createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser)
throws XmlPullParserException, IOException {
return createFromXml(r, parser, null);
}
@@ -1207,7 +1223,20 @@ public abstract class Drawable {
* For more information on how to create resources in XML, see
* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*/
- public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)
+ @NonNull
+ public static Drawable createFromXml(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @Nullable Theme theme) throws XmlPullParserException, IOException {
+ return createFromXmlForDensity(r, parser, 0, theme);
+ }
+
+ /**
+ * Version of {@link #createFromXml(Resources, XmlPullParser, Theme)} that accepts a density
+ * override.
+ * @hide
+ */
+ @NonNull
+ public static Drawable createFromXmlForDensity(@NonNull Resources r,
+ @NonNull XmlPullParser parser, int density, @Nullable Theme theme)
throws XmlPullParserException, IOException {
AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -1222,7 +1251,7 @@ public abstract class Drawable {
throw new XmlPullParserException("No start tag found");
}
- Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
+ Drawable drawable = createFromXmlInnerForDensity(r, parser, attrs, density, theme);
if (drawable == null) {
throw new RuntimeException("Unknown initial tag: " + parser.getName());
@@ -1236,8 +1265,9 @@ public abstract class Drawable {
* a tag in an XML document, tries to create a Drawable from that tag.
* Returns null if the tag is not a valid drawable.
*/
- public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
- throws XmlPullParserException, IOException {
+ @NonNull
+ public static Drawable createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs) throws XmlPullParserException, IOException {
return createFromXmlInner(r, parser, attrs, null);
}
@@ -1247,14 +1277,29 @@ public abstract class Drawable {
* document, tries to create a Drawable from that tag. Returns {@code null}
* if the tag is not a valid drawable.
*/
- public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- return r.getDrawableInflater().inflateFromXml(parser.getName(), parser, attrs, theme);
+ @NonNull
+ public static Drawable createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Theme theme)
+ throws XmlPullParserException, IOException {
+ return createFromXmlInnerForDensity(r, parser, attrs, 0, theme);
+ }
+
+ /**
+ * Version of {@link #createFromXmlInner(Resources, XmlPullParser, AttributeSet, Theme)} that
+ * accepts an override density.
+ */
+ @NonNull
+ static Drawable createFromXmlInnerForDensity(@NonNull Resources r,
+ @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, int density,
+ @Nullable Theme theme) throws XmlPullParserException, IOException {
+ return r.getDrawableInflater().inflateFromXmlForDensity(parser.getName(), parser, attrs,
+ density, theme);
}
/**
* Create a drawable from file path name.
*/
+ @Nullable
public static Drawable createFromPath(String pathName) {
if (pathName == null) {
return null;
@@ -1316,6 +1361,16 @@ public abstract class Drawable {
}
/**
+ * Sets the source override density for this Drawable. If non-zero, this density is to be used
+ * for any calls to {@link Resources#getDrawableForDensity(int, int, Theme)} or
+ * {@link Resources#getValueForDensity(int, int, TypedValue, boolean)}.
+ * @hide
+ */
+ final void setSrcDensityOverride(int density) {
+ mSrcDensityOverride = density;
+ }
+
+ /**
* This abstract class is used by {@link Drawable}s to store shared constant state and data
* between Drawables. {@link BitmapDrawable}s created from the same resource will for instance
* share a unique bitmap stored in their ConstantState.
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index 3404d8c26910..eea7048ca534 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -112,6 +112,17 @@ public final class DrawableInflater {
public Drawable inflateFromXml(@NonNull String name, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
+ return inflateFromXmlForDensity(name, parser, attrs, 0, theme);
+ }
+
+ /**
+ * Version of {@link #inflateFromXml(String, XmlPullParser, AttributeSet, Theme)} that accepts
+ * an override density.
+ */
+ @NonNull
+ Drawable inflateFromXmlForDensity(@NonNull String name, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, int density, @Nullable Theme theme)
+ throws XmlPullParserException, IOException {
// Inner classes must be referenced as Outer$Inner, but XML tag names
// can't contain $, so the <drawable> tag allows developers to specify
// the class in an attribute. We'll still run it through inflateFromTag
@@ -127,6 +138,7 @@ public final class DrawableInflater {
if (drawable == null) {
drawable = inflateFromClass(name);
}
+ drawable.setSrcDensityOverride(density);
drawable.inflate(mRes, parser, attrs, theme);
return drawable;
}
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 431b63bd64e5..cf821bb6ac8b 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -131,6 +131,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
final int densityDpi = r.getDisplayMetrics().densityDpi;
final int targetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
state.setDensity(targetDensity);
+ state.mSrcDensityOverride = mSrcDensityOverride;
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.DrawableWrapper);
updateStateFromTypedArray(a);
@@ -437,7 +438,8 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.START_TAG) {
- dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInnerForDensity(r, parser, attrs,
+ mState.mSrcDensityOverride, theme);
}
}
@@ -452,6 +454,14 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
@Config int mChangingConfigurations;
int mDensity = DisplayMetrics.DENSITY_DEFAULT;
+ /**
+ * The density to use when looking up resources from
+ * {@link Resources#getDrawableForDensity(int, int, Theme)}.
+ * A value of 0 means there is no override and the system density will be used.
+ * @hide
+ */
+ int mSrcDensityOverride = 0;
+
Drawable.ConstantState mDrawableState;
DrawableWrapperState(@Nullable DrawableWrapperState orig, @Nullable Resources res) {
@@ -459,6 +469,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb
mThemeAttrs = orig.mThemeAttrs;
mChangingConfigurations = orig.mChangingConfigurations;
mDrawableState = orig.mDrawableState;
+ mSrcDensityOverride = orig.mSrcDensityOverride;
}
final int density;