/*
 * 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 com.android.internal.app;

import static android.content.Context.ACTIVITY_SERVICE;
import static android.graphics.Paint.DITHER_FLAG;
import static android.graphics.Paint.FILTER_BITMAP_FLAG;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableWrapper;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Pools.SynchronizedPool;

import com.android.internal.R;

import org.xmlpull.v1.XmlPullParser;

import java.nio.ByteBuffer;


/**
 * @deprecated Use the Launcher3 Iconloaderlib at packages/apps/Launcher3/iconloaderlib. This class
 * is a temporary fork of Iconloader. It combines all necessary methods to render app icons that are
 * possibly badged. It is intended to be used only by Sharesheet for the Q release with custom code.
 */
@Deprecated
public class SimpleIconFactory {

    private static final SynchronizedPool<SimpleIconFactory> sPool =
            new SynchronizedPool<>(Runtime.getRuntime().availableProcessors());

    private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
    private static final float BLUR_FACTOR = 0.5f / 48;

    private Context mContext;
    private Canvas mCanvas;
    private PackageManager mPm;

    private int mFillResIconDpi;
    private int mIconBitmapSize;
    private int mBadgeBitmapSize;
    private int mWrapperBackgroundColor;

    private Drawable mWrapperIcon;
    private final Rect mOldBounds = new Rect();

    /**
     * Obtain a SimpleIconFactory from a pool objects.
     *
     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
     */
    @Deprecated
    public static SimpleIconFactory obtain(Context ctx) {
        SimpleIconFactory instance = sPool.acquire();
        if (instance == null) {
            final ActivityManager am = (ActivityManager) ctx.getSystemService(ACTIVITY_SERVICE);
            final int iconDpi = (am == null) ? 0 : am.getLauncherLargeIconDensity();

            final Resources r = ctx.getResources();
            final int iconSize = r.getDimensionPixelSize(R.dimen.resolver_icon_size);
            final int badgeSize = r.getDimensionPixelSize(R.dimen.resolver_badge_size);

            instance = new SimpleIconFactory(ctx, iconDpi, iconSize, badgeSize);
            instance.setWrapperBackgroundColor(Color.WHITE);
        }

        return instance;
    }

    /**
     * Recycles the SimpleIconFactory so others may use it.
     *
     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
     */
    @Deprecated
    public void recycle() {
        // Return to default background color
        setWrapperBackgroundColor(Color.WHITE);
        sPool.release(this);
    }

    /**
     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
     */
    @Deprecated
    private SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize,
            int badgeBitmapSize) {
        mContext = context.getApplicationContext();
        mPm = mContext.getPackageManager();
        mIconBitmapSize = iconBitmapSize;
        mBadgeBitmapSize = badgeBitmapSize;
        mFillResIconDpi = fillResIconDpi;

        mCanvas = new Canvas();
        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));

        // Normalizer init
        // Use twice the icon size as maximum size to avoid scaling down twice.
        mMaxSize = iconBitmapSize * 2;
        mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8);
        mScaleCheckCanvas = new Canvas(mBitmap);
        mPixels = new byte[mMaxSize * mMaxSize];
        mLeftBorder = new float[mMaxSize];
        mRightBorder = new float[mMaxSize];
        mBounds = new Rect();
        mAdaptiveIconBounds = new Rect();
        mAdaptiveIconScale = SCALE_NOT_INITIALIZED;

        // Shadow generator init
        mDefaultBlurMaskFilter = new BlurMaskFilter(iconBitmapSize * BLUR_FACTOR,
                Blur.NORMAL);
    }

    /**
     * Sets the background color used for wrapped adaptive icon
     *
     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
     */
    @Deprecated
    void setWrapperBackgroundColor(int color) {
        mWrapperBackgroundColor = (Color.alpha(color) < 255) ? DEFAULT_WRAPPER_BACKGROUND : color;
    }

    /**
     * Creates bitmap using the source drawable and various parameters.
     * The bitmap is visually normalized with other icons and has enough spacing to add shadow.
     * Note: this method has been modified from iconloaderlib to remove a profile diff check.
     *
     * @param icon                      source of the icon associated with a user that has no badge,
     *                                  likely user 0
     * @param user                      info can be used for a badge
     * @return a bitmap suitable for disaplaying as an icon at various system UIs.
     *
     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
     */
    @Deprecated
    Bitmap createUserBadgedIconBitmap(@Nullable Drawable icon, UserHandle user) {
        float [] scale = new float[1];

        // If no icon is provided use the system default
        if (icon == null) {
            icon = getFullResDefaultActivityIcon(mFillResIconDpi);
        }
        icon = normalizeAndWrapToAdaptiveIcon(icon, null, scale);
        Bitmap bitmap = createIconBitmap(icon, scale[0]);
        if (icon instanceof AdaptiveIconDrawable) {
            mCanvas.setBitmap(bitmap);
            recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
            mCanvas.setBitmap(null);
        }

        final Bitmap result;
        if (user != null /* if modification from iconloaderlib */) {
            BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
            Drawable badged = mPm.getUserBadgedIcon(drawable, user);
            if (badged instanceof BitmapDrawable) {
                result = ((BitmapDrawable) badged).getBitmap();
            } else {
                result = createIconBitmap(badged, 1f);
            }
        } else {
            result = bitmap;
        }

        return result;
    }

    /**
     * Creates bitmap using the source drawable and flattened pre-rendered app icon.
     * The bitmap is visually normalized with other icons and has enough spacing to add shadow.
     * This is custom functionality added to Iconloaderlib that will need to be ported.
     *
     * @param icon                      source of the icon associated with a user that has no badge
     * @param renderedAppIcon           pre-rendered app icon to use as a badge, likely the output
     *                                  of createUserBadgedIconBitmap for user 0
     * @return a bitmap suitable for disaplaying as an icon at various system UIs.
     *
     * @deprecated Do not use, functionality will be replaced by iconloader lib eventually.
     */
    @Deprecated
    public Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) {
        // If no icon is provided use the system default
        if (icon == null) {
            icon = getFullResDefaultActivityIcon(mFillResIconDpi);
        }

        // Direct share icons cannot be adaptive, most will arrive as bitmaps. To get reliable
        // presentation, force all DS icons to be circular. Scale DS image so it completely fills.
        int w = icon.getIntrinsicWidth();
        int h = icon.getIntrinsicHeight();
        float scale = 1;
        if (h > w && w > 0) {
            scale = (float) h / w;
        } else if (w > h && h > 0) {
            scale = (float) w / h;
        }
        Bitmap bitmap = createIconBitmap(icon, scale);
        bitmap = maskBitmapToCircle(bitmap);
        icon = new BitmapDrawable(mContext.getResources(), bitmap);

        // We now have a circular masked and scaled icon, inset and apply shadow
        scale = getScale(icon, null);
        bitmap = createIconBitmap(icon, scale);

        mCanvas.setBitmap(bitmap);
        recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);

        if (renderedAppIcon != null) {
            // Now scale down and apply the badge to the bottom right corner of the flattened icon
            renderedAppIcon = Bitmap.createScaledBitmap(renderedAppIcon, mBadgeBitmapSize,
                    mBadgeBitmapSize, false);

            // Paint the provided badge on top of the flattened icon
            mCanvas.drawBitmap(renderedAppIcon, mIconBitmapSize - mBadgeBitmapSize,
                    mIconBitmapSize - mBadgeBitmapSize, null);
        }

        mCanvas.setBitmap(null);

        return bitmap;
    }

    private Bitmap maskBitmapToCircle(Bitmap bitmap) {
        final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(output);
        final Paint paint = new Paint();
        paint.setAntiAlias(true);

        // Draw mask
        paint.setColor(0xffffffff);
        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawCircle(bitmap.getWidth() / 2f,
                bitmap.getHeight() / 2f,
                bitmap.getWidth() / 2f - 1 /* -1 to avoid circles with flat sides */,
                paint);

        // Draw masked bitmap
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }

    private static Drawable getFullResDefaultActivityIcon(int iconDpi) {
        return Resources.getSystem().getDrawableForDensity(android.R.mipmap.sym_def_app_icon,
                iconDpi);
    }

    private Bitmap createIconBitmap(Drawable icon, float scale) {
        return createIconBitmap(icon, scale, mIconBitmapSize);
    }

    /**
     * @param icon drawable that should be flattened to a bitmap
     * @param scale the scale to apply before drawing {@param icon} on the canvas
     */
    private Bitmap createIconBitmap(Drawable icon, float scale, int size) {
        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);

        mCanvas.setBitmap(bitmap);
        mOldBounds.set(icon.getBounds());

        if (icon instanceof AdaptiveIconDrawable) {
            int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
                    Math.round(size * (1 - scale) / 2));
            icon.setBounds(offset, offset, size - offset, size - offset);
            icon.draw(mCanvas);
        } else {
            if (icon instanceof BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
                Bitmap b = bitmapDrawable.getBitmap();
                if (bitmap != null && b.getDensity() == Bitmap.DENSITY_NONE) {
                    bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
                }
            }
            int width = size;
            int height = size;

            int intrinsicWidth = icon.getIntrinsicWidth();
            int intrinsicHeight = icon.getIntrinsicHeight();
            if (intrinsicWidth > 0 && intrinsicHeight > 0) {
                // Scale the icon proportionally to the icon dimensions
                final float ratio = (float) intrinsicWidth / intrinsicHeight;
                if (intrinsicWidth > intrinsicHeight) {
                    height = (int) (width / ratio);
                } else if (intrinsicHeight > intrinsicWidth) {
                    width = (int) (height * ratio);
                }
            }
            final int left = (size - width) / 2;
            final int top = (size - height) / 2;
            icon.setBounds(left, top, left + width, top + height);
            mCanvas.save();
            mCanvas.scale(scale, scale, size / 2, size / 2);
            icon.draw(mCanvas);
            mCanvas.restore();

        }

        icon.setBounds(mOldBounds);
        mCanvas.setBitmap(null);
        return bitmap;
    }

    private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, RectF outIconBounds,
            float[] outScale) {
        float scale = 1f;

        if (mWrapperIcon == null) {
            mWrapperIcon = mContext.getDrawable(
                    R.drawable.iconfactory_adaptive_icon_drawable_wrapper).mutate();
        }

        AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
        dr.setBounds(0, 0, 1, 1);
        scale = getScale(icon, outIconBounds);
        if (!(icon instanceof AdaptiveIconDrawable)) {
            FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
            fsd.setDrawable(icon);
            fsd.setScale(scale);
            icon = dr;
            scale = getScale(icon, outIconBounds);

            ((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
        }

        outScale[0] = scale;
        return icon;
    }


    /* Normalization block */

    private static final float SCALE_NOT_INITIALIZED = 0;
    // Ratio of icon visible area to full icon size for a square shaped icon
    private static final float MAX_SQUARE_AREA_FACTOR = 375.0f / 576;
    // Ratio of icon visible area to full icon size for a circular shaped icon
    private static final float MAX_CIRCLE_AREA_FACTOR = 380.0f / 576;

    private static final float CIRCLE_AREA_BY_RECT = (float) Math.PI / 4;

    // Slope used to calculate icon visible area to full icon size for any generic shaped icon.
    private static final float LINEAR_SCALE_SLOPE =
            (MAX_CIRCLE_AREA_FACTOR - MAX_SQUARE_AREA_FACTOR) / (1 - CIRCLE_AREA_BY_RECT);

    private static final int MIN_VISIBLE_ALPHA = 40;

    private float mAdaptiveIconScale;
    private final Rect mAdaptiveIconBounds;
    private final Rect mBounds;
    private final int mMaxSize;
    private final byte[] mPixels;
    private final float[] mLeftBorder;
    private final float[] mRightBorder;
    private final Bitmap mBitmap;
    private final Canvas mScaleCheckCanvas;

    /**
     * Returns the amount by which the {@param d} should be scaled (in both dimensions) so that it
     * matches the design guidelines for a launcher icon.
     *
     * We first calculate the convex hull of the visible portion of the icon.
     * This hull then compared with the bounding rectangle of the hull to find how closely it
     * resembles a circle and a square, by comparing the ratio of the areas. Note that this is not
     * an ideal solution but it gives satisfactory result without affecting the performance.
     *
     * This closeness is used to determine the ratio of hull area to the full icon size.
     * Refer {@link #MAX_CIRCLE_AREA_FACTOR} and {@link #MAX_SQUARE_AREA_FACTOR}
     *
     * @param outBounds optional rect to receive the fraction distance from each edge.
     */
    private synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds) {
        if (d instanceof AdaptiveIconDrawable) {
            if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
                if (outBounds != null) {
                    outBounds.set(mAdaptiveIconBounds);
                }
                return mAdaptiveIconScale;
            }
        }
        int width = d.getIntrinsicWidth();
        int height = d.getIntrinsicHeight();
        if (width <= 0 || height <= 0) {
            width = width <= 0 || width > mMaxSize ? mMaxSize : width;
            height = height <= 0 || height > mMaxSize ? mMaxSize : height;
        } else if (width > mMaxSize || height > mMaxSize) {
            int max = Math.max(width, height);
            width = mMaxSize * width / max;
            height = mMaxSize * height / max;
        }

        mBitmap.eraseColor(Color.TRANSPARENT);
        d.setBounds(0, 0, width, height);
        d.draw(mScaleCheckCanvas);

        ByteBuffer buffer = ByteBuffer.wrap(mPixels);
        buffer.rewind();
        mBitmap.copyPixelsToBuffer(buffer);

        // Overall bounds of the visible icon.
        int topY = -1;
        int bottomY = -1;
        int leftX = mMaxSize + 1;
        int rightX = -1;

        // Create border by going through all pixels one row at a time and for each row find
        // the first and the last non-transparent pixel. Set those values to mLeftBorder and
        // mRightBorder and use -1 if there are no visible pixel in the row.

        // buffer position
        int index = 0;
        // buffer shift after every row, width of buffer = mMaxSize
        int rowSizeDiff = mMaxSize - width;
        // first and last position for any row.
        int firstX, lastX;

        for (int y = 0; y < height; y++) {
            firstX = lastX = -1;
            for (int x = 0; x < width; x++) {
                if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) {
                    if (firstX == -1) {
                        firstX = x;
                    }
                    lastX = x;
                }
                index++;
            }
            index += rowSizeDiff;

            mLeftBorder[y] = firstX;
            mRightBorder[y] = lastX;

            // If there is at least one visible pixel, update the overall bounds.
            if (firstX != -1) {
                bottomY = y;
                if (topY == -1) {
                    topY = y;
                }

                leftX = Math.min(leftX, firstX);
                rightX = Math.max(rightX, lastX);
            }
        }

        if (topY == -1 || rightX == -1) {
            // No valid pixels found. Do not scale.
            return 1;
        }

        convertToConvexArray(mLeftBorder, 1, topY, bottomY);
        convertToConvexArray(mRightBorder, -1, topY, bottomY);

        // Area of the convex hull
        float area = 0;
        for (int y = 0; y < height; y++) {
            if (mLeftBorder[y] <= -1) {
                continue;
            }
            area += mRightBorder[y] - mLeftBorder[y] + 1;
        }

        // Area of the rectangle required to fit the convex hull
        float rectArea = (bottomY + 1 - topY) * (rightX + 1 - leftX);
        float hullByRect = area / rectArea;

        float scaleRequired;
        if (hullByRect < CIRCLE_AREA_BY_RECT) {
            scaleRequired = MAX_CIRCLE_AREA_FACTOR;
        } else {
            scaleRequired = MAX_SQUARE_AREA_FACTOR + LINEAR_SCALE_SLOPE * (1 - hullByRect);
        }
        mBounds.left = leftX;
        mBounds.right = rightX;

        mBounds.top = topY;
        mBounds.bottom = bottomY;

        if (outBounds != null) {
            outBounds.set(((float) mBounds.left) / width, ((float) mBounds.top) / height,
                    1 - ((float) mBounds.right) / width,
                    1 - ((float) mBounds.bottom) / height);
        }
        float areaScale = area / (width * height);
        // Use sqrt of the final ratio as the images is scaled across both width and height.
        float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
        if (d instanceof AdaptiveIconDrawable && mAdaptiveIconScale == SCALE_NOT_INITIALIZED) {
            mAdaptiveIconScale = scale;
            mAdaptiveIconBounds.set(mBounds);
        }
        return scale;
    }

    /**
     * Modifies {@param xCoordinates} to represent a convex border. Fills in all missing values
     * (except on either ends) with appropriate values.
     * @param xCoordinates map of x coordinate per y.
     * @param direction 1 for left border and -1 for right border.
     * @param topY the first Y position (inclusive) with a valid value.
     * @param bottomY the last Y position (inclusive) with a valid value.
     */
    private static void convertToConvexArray(
            float[] xCoordinates, int direction, int topY, int bottomY) {
        int total = xCoordinates.length;
        // The tangent at each pixel.
        float[] angles = new float[total - 1];

        int first = topY; // First valid y coordinate
        int last = -1;    // Last valid y coordinate which didn't have a missing value

        float lastAngle = Float.MAX_VALUE;

        for (int i = topY + 1; i <= bottomY; i++) {
            if (xCoordinates[i] <= -1) {
                continue;
            }
            int start;

            if (lastAngle == Float.MAX_VALUE) {
                start = first;
            } else {
                float currentAngle = (xCoordinates[i] - xCoordinates[last]) / (i - last);
                start = last;
                // If this position creates a concave angle, keep moving up until we find a
                // position which creates a convex angle.
                if ((currentAngle - lastAngle) * direction < 0) {
                    while (start > first) {
                        start--;
                        currentAngle = (xCoordinates[i] - xCoordinates[start]) / (i - start);
                        if ((currentAngle - angles[start]) * direction >= 0) {
                            break;
                        }
                    }
                }
            }

            // Reset from last check
            lastAngle = (xCoordinates[i] - xCoordinates[start]) / (i - start);
            // Update all the points from start.
            for (int j = start; j < i; j++) {
                angles[j] = lastAngle;
                xCoordinates[j] = xCoordinates[start] + lastAngle * (j - start);
            }
            last = i;
        }
    }

    /* Shadow generator block */

    private static final float KEY_SHADOW_DISTANCE = 1f / 48;
    private static final int KEY_SHADOW_ALPHA = 61;
    private static final int AMBIENT_SHADOW_ALPHA = 30;

    private Paint mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    private Paint mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    private BlurMaskFilter mDefaultBlurMaskFilter;

    private synchronized void recreateIcon(Bitmap icon, Canvas out) {
        recreateIcon(icon, mDefaultBlurMaskFilter, AMBIENT_SHADOW_ALPHA, KEY_SHADOW_ALPHA, out);
    }

    private synchronized void recreateIcon(Bitmap icon, BlurMaskFilter blurMaskFilter,
            int ambientAlpha, int keyAlpha, Canvas out) {
        int[] offset = new int[2];
        mBlurPaint.setMaskFilter(blurMaskFilter);
        Bitmap shadow = icon.extractAlpha(mBlurPaint, offset);

        // Draw ambient shadow
        mDrawPaint.setAlpha(ambientAlpha);
        out.drawBitmap(shadow, offset[0], offset[1], mDrawPaint);

        // Draw key shadow
        mDrawPaint.setAlpha(keyAlpha);
        out.drawBitmap(shadow, offset[0], offset[1] + KEY_SHADOW_DISTANCE * mIconBitmapSize,
                mDrawPaint);

        // Draw the icon
        mDrawPaint.setAlpha(255); // TODO if b/128609682 not fixed by launch use .setAlpha(254)
        out.drawBitmap(icon, 0, 0, mDrawPaint);
    }

    /* Classes */

    /**
     * Extension of {@link DrawableWrapper} which scales the child drawables by a fixed amount.
     */
    public static class FixedScaleDrawable extends DrawableWrapper {

        private static final float LEGACY_ICON_SCALE = .7f * .6667f;
        private float mScaleX, mScaleY;

        public FixedScaleDrawable() {
            super(new ColorDrawable());
            mScaleX = LEGACY_ICON_SCALE;
            mScaleY = LEGACY_ICON_SCALE;
        }

        @Override
        public void draw(@NonNull Canvas canvas) {
            int saveCount = canvas.save();
            canvas.scale(mScaleX, mScaleY,
                    getBounds().exactCenterX(), getBounds().exactCenterY());
            super.draw(canvas);
            canvas.restoreToCount(saveCount);
        }

        @Override
        public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) { }

        @Override
        public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) { }

        /**
         * Sets the scale associated with this drawable
         * @param scale
         */
        public void setScale(float scale) {
            float h = getIntrinsicHeight();
            float w = getIntrinsicWidth();
            mScaleX = scale * LEGACY_ICON_SCALE;
            mScaleY = scale * LEGACY_ICON_SCALE;
            if (h > w && w > 0) {
                mScaleX *= w / h;
            } else if (w > h && h > 0) {
                mScaleY *= h / w;
            }
        }
    }

    /**
     * An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
     * This allows the badging to be done based on the action bitmap size rather than
     * the scaled bitmap size.
     */
    private static class FixedSizeBitmapDrawable extends BitmapDrawable {

        FixedSizeBitmapDrawable(Bitmap bitmap) {
            super(null, bitmap);
        }

        @Override
        public int getIntrinsicHeight() {
            return getBitmap().getWidth();
        }

        @Override
        public int getIntrinsicWidth() {
            return getBitmap().getWidth();
        }
    }

}
