Loading core/java/android/content/res/Resources.java +13 −39 Original line number Diff line number Diff line Loading @@ -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); } /** Loading @@ -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. Loading @@ -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 Loading @@ -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); } /** Loading Loading @@ -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. * Loading Loading @@ -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. Loading @@ -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 Loading core/java/android/content/res/ResourcesImpl.java +25 −6 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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( Loading core/java/android/content/res/TypedArray.java +16 −1 Original line number Diff line number Diff line Loading @@ -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!"); } Loading @@ -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; } Loading graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +17 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading graphics/java/android/graphics/drawable/BitmapDrawable.java +43 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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(); Loading @@ -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; Loading @@ -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"); Loading @@ -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)); Loading Loading @@ -839,8 +868,6 @@ public class BitmapDrawable extends Drawable { if (tileModeY != TILE_MODE_UNDEFINED) { setTileModeY(parseTileMode(tileModeY)); } state.mTargetDensity = Drawable.resolveDensity(r, 0); } @Override Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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); Loading Loading
core/java/android/content/res/Resources.java +13 −39 Original line number Diff line number Diff line Loading @@ -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); } /** Loading @@ -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. Loading @@ -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 Loading @@ -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); } /** Loading Loading @@ -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. * Loading Loading @@ -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. Loading @@ -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 Loading
core/java/android/content/res/ResourcesImpl.java +25 −6 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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( Loading
core/java/android/content/res/TypedArray.java +16 −1 Original line number Diff line number Diff line Loading @@ -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!"); } Loading @@ -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; } Loading
graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +17 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading
graphics/java/android/graphics/drawable/BitmapDrawable.java +43 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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(); Loading @@ -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; Loading @@ -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"); Loading @@ -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)); Loading Loading @@ -839,8 +868,6 @@ public class BitmapDrawable extends Drawable { if (tileModeY != TILE_MODE_UNDEFINED) { setTileModeY(parseTileMode(tileModeY)); } state.mTargetDensity = Drawable.resolveDensity(r, 0); } @Override Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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); Loading