/*
 * Copyright (C) 2015 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.graphics.drawable;

import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlendMode;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Objects;

/**
 * An umbrella container for several serializable graphics representations, including Bitmaps,
 * compressed bitmap images (e.g. JPG or PNG), and drawable resources (including vectors).
 *
 * <a href="https://developer.android.com/training/displaying-bitmaps/index.html">Much ink</a>
 * has been spilled on the best way to load images, and many clients may have different needs when
 * it comes to threading and fetching. This class is therefore focused on encapsulation rather than
 * behavior.
 */

public final class Icon implements Parcelable {
    private static final String TAG = "Icon";

    /**
     * An icon that was created using {@link Icon#createWithBitmap(Bitmap)}.
     * @see #getType
     */
    public static final int TYPE_BITMAP   = 1;
    /**
     * An icon that was created using {@link Icon#createWithResource}.
     * @see #getType
     */
    public static final int TYPE_RESOURCE = 2;
    /**
     * An icon that was created using {@link Icon#createWithData(byte[], int, int)}.
     * @see #getType
     */
    public static final int TYPE_DATA     = 3;
    /**
     * An icon that was created using {@link Icon#createWithContentUri}
     * or {@link Icon#createWithFilePath(String)}.
     * @see #getType
     */
    public static final int TYPE_URI      = 4;
    /**
     * An icon that was created using {@link Icon#createWithAdaptiveBitmap}.
     * @see #getType
     */
    public static final int TYPE_ADAPTIVE_BITMAP = 5;
    /**
     * An icon that was created using {@link Icon#createWithAdaptiveBitmapContentUri}.
     * @see #getType
     */
    public static final int TYPE_URI_ADAPTIVE_BITMAP = 6;

    /**
     * @hide
     */
    @IntDef({TYPE_BITMAP, TYPE_RESOURCE, TYPE_DATA, TYPE_URI, TYPE_ADAPTIVE_BITMAP,
            TYPE_URI_ADAPTIVE_BITMAP})
    public @interface IconType {
    }

    private static final int VERSION_STREAM_SERIALIZER = 1;

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final int mType;

    private ColorStateList mTintList;
    static final BlendMode DEFAULT_BLEND_MODE = Drawable.DEFAULT_BLEND_MODE; // SRC_IN
    private BlendMode mBlendMode = Drawable.DEFAULT_BLEND_MODE;

    // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed
    // based on the value of mType.

    // TYPE_BITMAP: Bitmap
    // TYPE_ADAPTIVE_BITMAP: Bitmap
    // TYPE_RESOURCE: Resources
    // TYPE_DATA: DataBytes
    private Object          mObj1;

    // TYPE_RESOURCE: package name
    // TYPE_URI: uri string
    // TYPE_URI_ADAPTIVE_BITMAP: uri string
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private String          mString1;

    // TYPE_RESOURCE: resId
    // TYPE_DATA: data length
    private int             mInt1;

    // TYPE_DATA: data offset
    private int             mInt2;

    /**
     * Gets the type of the icon provided.
     * <p>
     * Note that new types may be added later, so callers should guard against other
     * types being returned.
     */
    @IconType
    public int getType() {
        return mType;
    }

    /**
     * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} or
     * {@link #TYPE_ADAPTIVE_BITMAP} Icon.
     * @hide
     */
    @UnsupportedAppUsage
    public Bitmap getBitmap() {
        if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
            throw new IllegalStateException("called getBitmap() on " + this);
        }
        return (Bitmap) mObj1;
    }

    private void setBitmap(Bitmap b) {
        mObj1 = b;
    }

    /**
     * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon.
     * @hide
     */
    @UnsupportedAppUsage
    public int getDataLength() {
        if (mType != TYPE_DATA) {
            throw new IllegalStateException("called getDataLength() on " + this);
        }
        synchronized (this) {
            return mInt1;
        }
    }

    /**
     * @return The offset into the byte array held by this {@link #TYPE_DATA} Icon at which
     * valid compressed bitmap data is found.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public int getDataOffset() {
        if (mType != TYPE_DATA) {
            throw new IllegalStateException("called getDataOffset() on " + this);
        }
        synchronized (this) {
            return mInt2;
        }
    }

    /**
     * @return The byte array held by this {@link #TYPE_DATA} Icon ctonaining compressed
     * bitmap data.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public byte[] getDataBytes() {
        if (mType != TYPE_DATA) {
            throw new IllegalStateException("called getDataBytes() on " + this);
        }
        synchronized (this) {
            return (byte[]) mObj1;
        }
    }

    /**
     * @return The {@link android.content.res.Resources} for this {@link #TYPE_RESOURCE} Icon.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public Resources getResources() {
        if (mType != TYPE_RESOURCE) {
            throw new IllegalStateException("called getResources() on " + this);
        }
        return (Resources) mObj1;
    }

    /**
     * Gets the package used to create this icon.
     * <p>
     * Only valid for icons of type {@link #TYPE_RESOURCE}.
     * Note: This package may not be available if referenced in the future, and it is
     * up to the caller to ensure safety if this package is re-used and/or persisted.
     */
    @NonNull
    public String getResPackage() {
        if (mType != TYPE_RESOURCE) {
            throw new IllegalStateException("called getResPackage() on " + this);
        }
        return mString1;
    }

    /**
     * Gets the resource used to create this icon.
     * <p>
     * Only valid for icons of type {@link #TYPE_RESOURCE}.
     * Note: This resource may not be available if the application changes at all, and it is
     * up to the caller to ensure safety if this resource is re-used and/or persisted.
     */
    @IdRes
    public int getResId() {
        if (mType != TYPE_RESOURCE) {
            throw new IllegalStateException("called getResId() on " + this);
        }
        return mInt1;
    }

    /**
     * @return The URI (as a String) for this {@link #TYPE_URI} or {@link #TYPE_URI_ADAPTIVE_BITMAP}
     * Icon.
     * @hide
     */
    public String getUriString() {
        if (mType != TYPE_URI && mType != TYPE_URI_ADAPTIVE_BITMAP) {
            throw new IllegalStateException("called getUriString() on " + this);
        }
        return mString1;
    }

    /**
     * Gets the uri used to create this icon.
     * <p>
     * Only valid for icons of type {@link #TYPE_URI} and {@link #TYPE_URI_ADAPTIVE_BITMAP}.
     * Note: This uri may not be available in the future, and it is
     * up to the caller to ensure safety if this uri is re-used and/or persisted.
     */
    @NonNull
    public Uri getUri() {
        return Uri.parse(getUriString());
    }

    private static final String typeToString(int x) {
        switch (x) {
            case TYPE_BITMAP: return "BITMAP";
            case TYPE_ADAPTIVE_BITMAP: return "BITMAP_MASKABLE";
            case TYPE_DATA: return "DATA";
            case TYPE_RESOURCE: return "RESOURCE";
            case TYPE_URI: return "URI";
            case TYPE_URI_ADAPTIVE_BITMAP: return "URI_MASKABLE";
            default: return "UNKNOWN";
        }
    }

    /**
     * Invokes {@link #loadDrawable(Context)} on the given {@link android.os.Handler Handler}
     * and then sends <code>andThen</code> to the same Handler when finished.
     *
     * @param context {@link android.content.Context Context} in which to load the drawable; see
     *                {@link #loadDrawable(Context)}
     * @param andThen {@link android.os.Message} to send to its target once the drawable
     *                is available. The {@link android.os.Message#obj obj}
     *                property is populated with the Drawable.
     */
    public void loadDrawableAsync(Context context, Message andThen) {
        if (andThen.getTarget() == null) {
            throw new IllegalArgumentException("callback message must have a target handler");
        }
        new LoadDrawableTask(context, andThen).runAsync();
    }

    /**
     * Invokes {@link #loadDrawable(Context)} on a background thread and notifies the <code>
     * {@link OnDrawableLoadedListener#onDrawableLoaded listener} </code> on the {@code handler}
     * when finished.
     *
     * @param context {@link Context Context} in which to load the drawable; see
     *                {@link #loadDrawable(Context)}
     * @param listener to be {@link OnDrawableLoadedListener#onDrawableLoaded notified} when
     *                 {@link #loadDrawable(Context)} finished
     * @param handler {@link Handler} on which to notify the {@code listener}
     */
    public void loadDrawableAsync(Context context, final OnDrawableLoadedListener listener,
            Handler handler) {
        new LoadDrawableTask(context, handler, listener).runAsync();
    }

    /**
     * Returns a Drawable that can be used to draw the image inside this Icon, constructing it
     * if necessary. Depending on the type of image, this may not be something you want to do on
     * the UI thread, so consider using
     * {@link #loadDrawableAsync(Context, Message) loadDrawableAsync} instead.
     *
     * @param context {@link android.content.Context Context} in which to load the drawable; used
     *                to access {@link android.content.res.Resources Resources}, for example.
     * @return A fresh instance of a drawable for this image, yours to keep.
     */
    public Drawable loadDrawable(Context context) {
        final Drawable result = loadDrawableInner(context);
        if (result != null && (mTintList != null || mBlendMode != DEFAULT_BLEND_MODE)) {
            result.mutate();
            result.setTintList(mTintList);
            result.setTintBlendMode(mBlendMode);
        }
        return result;
    }

    /**
     * Do the heavy lifting of loading the drawable, but stop short of applying any tint.
     */
    private Drawable loadDrawableInner(Context context) {
        switch (mType) {
            case TYPE_BITMAP:
                return new BitmapDrawable(context.getResources(), getBitmap());
            case TYPE_ADAPTIVE_BITMAP:
                return new AdaptiveIconDrawable(null,
                    new BitmapDrawable(context.getResources(), getBitmap()));
            case TYPE_RESOURCE:
                if (getResources() == null) {
                    // figure out where to load resources from
                    String resPackage = getResPackage();
                    if (TextUtils.isEmpty(resPackage)) {
                        // if none is specified, try the given context
                        resPackage = context.getPackageName();
                    }
                    if ("android".equals(resPackage)) {
                        mObj1 = Resources.getSystem();
                    } else {
                        final PackageManager pm = context.getPackageManager();
                        try {
                            ApplicationInfo ai = pm.getApplicationInfo(
                                    resPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES);
                            if (ai != null) {
                                mObj1 = pm.getResourcesForApplication(ai);
                            } else {
                                break;
                            }
                        } catch (PackageManager.NameNotFoundException e) {
                            Log.e(TAG, String.format("Unable to find pkg=%s for icon %s",
                                    resPackage, this), e);
                            break;
                        }
                    }
                }
                try {
                    return getResources().getDrawable(getResId(), context.getTheme());
                } catch (RuntimeException e) {
                    Log.e(TAG, String.format("Unable to load resource 0x%08x from pkg=%s",
                                    getResId(),
                                    getResPackage()),
                            e);
                }
                break;
            case TYPE_DATA:
                return new BitmapDrawable(context.getResources(),
                    BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength())
                );
            case TYPE_URI:
                InputStream is = getUriInputStream(context);
                if (is != null) {
                    return new BitmapDrawable(context.getResources(),
                            BitmapFactory.decodeStream(is));
                }
                break;
            case TYPE_URI_ADAPTIVE_BITMAP:
                is = getUriInputStream(context);
                if (is != null) {
                    return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(),
                            BitmapFactory.decodeStream(is)));
                }
                break;
        }
        return null;
    }

    private InputStream getUriInputStream(Context context) {
        final Uri uri = getUri();
        final String scheme = uri.getScheme();
        if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                || ContentResolver.SCHEME_FILE.equals(scheme)) {
            try {
                return context.getContentResolver().openInputStream(uri);
            } catch (Exception e) {
                Log.w(TAG, "Unable to load image from URI: " + uri, e);
            }
        } else {
            try {
                return new FileInputStream(new File(mString1));
            } catch (FileNotFoundException e) {
                Log.w(TAG, "Unable to load image from path: " + uri, e);
            }
        }
        return null;
    }

    /**
     * Load the requested resources under the given userId, if the system allows it,
     * before actually loading the drawable.
     *
     * @hide
     */
    public Drawable loadDrawableAsUser(Context context, int userId) {
        if (mType == TYPE_RESOURCE) {
            String resPackage = getResPackage();
            if (TextUtils.isEmpty(resPackage)) {
                resPackage = context.getPackageName();
            }
            if (getResources() == null && !(getResPackage().equals("android"))) {
                final PackageManager pm = context.getPackageManager();
                try {
                    // assign getResources() as the correct user
                    mObj1 = pm.getResourcesForApplicationAsUser(resPackage, userId);
                } catch (PackageManager.NameNotFoundException e) {
                    Log.e(TAG, String.format("Unable to find pkg=%s user=%d",
                                    getResPackage(),
                                    userId),
                            e);
                }
            }
        }
        return loadDrawable(context);
    }

    /** @hide */
    public static final int MIN_ASHMEM_ICON_SIZE = 128 * (1 << 10);

    /**
     * Puts the memory used by this instance into Ashmem memory, if possible.
     * @hide
     */
    public void convertToAshmem() {
        if ((mType == TYPE_BITMAP || mType == TYPE_ADAPTIVE_BITMAP) &&
            getBitmap().isMutable() &&
            getBitmap().getAllocationByteCount() >= MIN_ASHMEM_ICON_SIZE) {
            setBitmap(getBitmap().createAshmemBitmap());
        }
    }

    /**
     * Writes a serialized version of an Icon to the specified stream.
     *
     * @param stream The stream on which to serialize the Icon.
     * @hide
     */
    public void writeToStream(OutputStream stream) throws IOException {
        DataOutputStream dataStream = new DataOutputStream(stream);

        dataStream.writeInt(VERSION_STREAM_SERIALIZER);
        dataStream.writeByte(mType);

        switch (mType) {
            case TYPE_BITMAP:
            case TYPE_ADAPTIVE_BITMAP:
                getBitmap().compress(Bitmap.CompressFormat.PNG, 100, dataStream);
                break;
            case TYPE_DATA:
                dataStream.writeInt(getDataLength());
                dataStream.write(getDataBytes(), getDataOffset(), getDataLength());
                break;
            case TYPE_RESOURCE:
                dataStream.writeUTF(getResPackage());
                dataStream.writeInt(getResId());
                break;
            case TYPE_URI:
            case TYPE_URI_ADAPTIVE_BITMAP:
                dataStream.writeUTF(getUriString());
                break;
        }
    }

    private Icon(int mType) {
        this.mType = mType;
    }

    /**
     * Create an Icon from the specified stream.
     *
     * @param stream The input stream from which to reconstruct the Icon.
     * @hide
     */
    public static Icon createFromStream(InputStream stream) throws IOException {
        DataInputStream inputStream = new DataInputStream(stream);

        final int version = inputStream.readInt();
        if (version >= VERSION_STREAM_SERIALIZER) {
            final int type = inputStream.readByte();
            switch (type) {
                case TYPE_BITMAP:
                    return createWithBitmap(BitmapFactory.decodeStream(inputStream));
                case TYPE_ADAPTIVE_BITMAP:
                    return createWithAdaptiveBitmap(BitmapFactory.decodeStream(inputStream));
                case TYPE_DATA:
                    final int length = inputStream.readInt();
                    final byte[] data = new byte[length];
                    inputStream.read(data, 0 /* offset */, length);
                    return createWithData(data, 0 /* offset */, length);
                case TYPE_RESOURCE:
                    final String packageName = inputStream.readUTF();
                    final int resId = inputStream.readInt();
                    return createWithResource(packageName, resId);
                case TYPE_URI:
                    final String uriOrPath = inputStream.readUTF();
                    return createWithContentUri(uriOrPath);
                case TYPE_URI_ADAPTIVE_BITMAP:
                    final String uri = inputStream.readUTF();
                    return createWithAdaptiveBitmapContentUri(uri);
            }
        }
        return null;
    }

    /**
     * Compares if this icon is constructed from the same resources as another icon.
     * Note that this is an inexpensive operation and doesn't do deep Bitmap equality comparisons.
     *
     * @param otherIcon the other icon
     * @return whether this icon is the same as the another one
     * @hide
     */
    public boolean sameAs(Icon otherIcon) {
        if (otherIcon == this) {
            return true;
        }
        if (mType != otherIcon.getType()) {
            return false;
        }
        switch (mType) {
            case TYPE_BITMAP:
            case TYPE_ADAPTIVE_BITMAP:
                return getBitmap() == otherIcon.getBitmap();
            case TYPE_DATA:
                return getDataLength() == otherIcon.getDataLength()
                        && getDataOffset() == otherIcon.getDataOffset()
                        && Arrays.equals(getDataBytes(), otherIcon.getDataBytes());
            case TYPE_RESOURCE:
                return getResId() == otherIcon.getResId()
                        && Objects.equals(getResPackage(), otherIcon.getResPackage());
            case TYPE_URI:
            case TYPE_URI_ADAPTIVE_BITMAP:
                return Objects.equals(getUriString(), otherIcon.getUriString());
        }
        return false;
    }

    /**
     * Create an Icon pointing to a drawable resource.
     * @param context The context for the application whose resources should be used to resolve the
     *                given resource ID.
     * @param resId ID of the drawable resource
     */
    public static Icon createWithResource(Context context, @DrawableRes int resId) {
        if (context == null) {
            throw new IllegalArgumentException("Context must not be null.");
        }
        final Icon rep = new Icon(TYPE_RESOURCE);
        rep.mInt1 = resId;
        rep.mString1 = context.getPackageName();
        return rep;
    }

    /**
     * Version of createWithResource that takes Resources. Do not use.
     * @hide
     */
    @UnsupportedAppUsage
    public static Icon createWithResource(Resources res, @DrawableRes int resId) {
        if (res == null) {
            throw new IllegalArgumentException("Resource must not be null.");
        }
        final Icon rep = new Icon(TYPE_RESOURCE);
        rep.mInt1 = resId;
        rep.mString1 = res.getResourcePackageName(resId);
        return rep;
    }

    /**
     * Create an Icon pointing to a drawable resource.
     * @param resPackage Name of the package containing the resource in question
     * @param resId ID of the drawable resource
     */
    public static Icon createWithResource(String resPackage, @DrawableRes int resId) {
        if (resPackage == null) {
            throw new IllegalArgumentException("Resource package name must not be null.");
        }
        final Icon rep = new Icon(TYPE_RESOURCE);
        rep.mInt1 = resId;
        rep.mString1 = resPackage;
        return rep;
    }

    /**
     * Create an Icon pointing to a bitmap in memory.
     * @param bits A valid {@link android.graphics.Bitmap} object
     */
    public static Icon createWithBitmap(Bitmap bits) {
        if (bits == null) {
            throw new IllegalArgumentException("Bitmap must not be null.");
        }
        final Icon rep = new Icon(TYPE_BITMAP);
        rep.setBitmap(bits);
        return rep;
    }

    /**
     * Create an Icon pointing to a bitmap in memory that follows the icon design guideline defined
     * by {@link AdaptiveIconDrawable}.
     * @param bits A valid {@link android.graphics.Bitmap} object
     */
    public static Icon createWithAdaptiveBitmap(Bitmap bits) {
        if (bits == null) {
            throw new IllegalArgumentException("Bitmap must not be null.");
        }
        final Icon rep = new Icon(TYPE_ADAPTIVE_BITMAP);
        rep.setBitmap(bits);
        return rep;
    }

    /**
     * Create an Icon pointing to a compressed bitmap stored in a byte array.
     * @param data Byte array storing compressed bitmap data of a type that
     *             {@link android.graphics.BitmapFactory}
     *             can decode (see {@link android.graphics.Bitmap.CompressFormat}).
     * @param offset Offset into <code>data</code> at which the bitmap data starts
     * @param length Length of the bitmap data
     */
    public static Icon createWithData(byte[] data, int offset, int length) {
        if (data == null) {
            throw new IllegalArgumentException("Data must not be null.");
        }
        final Icon rep = new Icon(TYPE_DATA);
        rep.mObj1 = data;
        rep.mInt1 = length;
        rep.mInt2 = offset;
        return rep;
    }

    /**
     * Create an Icon pointing to an image file specified by URI.
     *
     * @param uri A uri referring to local content:// or file:// image data.
     */
    public static Icon createWithContentUri(String uri) {
        if (uri == null) {
            throw new IllegalArgumentException("Uri must not be null.");
        }
        final Icon rep = new Icon(TYPE_URI);
        rep.mString1 = uri;
        return rep;
    }

    /**
     * Create an Icon pointing to an image file specified by URI.
     *
     * @param uri A uri referring to local content:// or file:// image data.
     */
    public static Icon createWithContentUri(Uri uri) {
        if (uri == null) {
            throw new IllegalArgumentException("Uri must not be null.");
        }
        return createWithContentUri(uri.toString());
    }

    /**
     * Create an Icon pointing to an image file specified by URI. Image file should follow the icon
     * design guideline defined by {@link AdaptiveIconDrawable}.
     *
     * @param uri A uri referring to local content:// or file:// image data.
     */
    @NonNull
    public static Icon createWithAdaptiveBitmapContentUri(@NonNull String uri) {
        if (uri == null) {
            throw new IllegalArgumentException("Uri must not be null.");
        }
        final Icon rep = new Icon(TYPE_URI_ADAPTIVE_BITMAP);
        rep.mString1 = uri;
        return rep;
    }

    /**
     * Create an Icon pointing to an image file specified by URI. Image file should follow the icon
     * design guideline defined by {@link AdaptiveIconDrawable}.
     *
     * @param uri A uri referring to local content:// or file:// image data.
     */
    @NonNull
    public static Icon createWithAdaptiveBitmapContentUri(@NonNull Uri uri) {
        if (uri == null) {
            throw new IllegalArgumentException("Uri must not be null.");
        }
        return createWithAdaptiveBitmapContentUri(uri.toString());
    }

    /**
     * Store a color to use whenever this Icon is drawn.
     *
     * @param tint a color, as in {@link Drawable#setTint(int)}
     * @return this same object, for use in chained construction
     */
    public Icon setTint(@ColorInt int tint) {
        return setTintList(ColorStateList.valueOf(tint));
    }

    /**
     * Store a color to use whenever this Icon is drawn.
     *
     * @param tintList as in {@link Drawable#setTintList(ColorStateList)}, null to remove tint
     * @return this same object, for use in chained construction
     */
    public Icon setTintList(ColorStateList tintList) {
        mTintList = tintList;
        return this;
    }

    /**
     * Store a blending mode to use whenever this Icon is drawn.
     *
     * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null
     * @return this same object, for use in chained construction
     */
    public @NonNull Icon setTintMode(@NonNull PorterDuff.Mode mode) {
        mBlendMode = BlendMode.fromValue(mode.nativeInt);
        return this;
    }

    /**
     * Store a blending mode to use whenever this Icon is drawn.
     *
     * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null
     * @return this same object, for use in chained construction
     */
    public @NonNull Icon setTintBlendMode(@NonNull BlendMode mode) {
        mBlendMode = mode;
        return this;
    }

    /** @hide */
    @UnsupportedAppUsage
    public boolean hasTint() {
        return (mTintList != null) || (mBlendMode != DEFAULT_BLEND_MODE);
    }

    /**
     * Create an Icon pointing to an image file specified by path.
     *
     * @param path A path to a file that contains compressed bitmap data of
     *           a type that {@link android.graphics.BitmapFactory} can decode.
     */
    public static Icon createWithFilePath(String path) {
        if (path == null) {
            throw new IllegalArgumentException("Path must not be null.");
        }
        final Icon rep = new Icon(TYPE_URI);
        rep.mString1 = path;
        return rep;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Icon(typ=").append(typeToString(mType));
        switch (mType) {
            case TYPE_BITMAP:
            case TYPE_ADAPTIVE_BITMAP:
                sb.append(" size=")
                        .append(getBitmap().getWidth())
                        .append("x")
                        .append(getBitmap().getHeight());
                break;
            case TYPE_RESOURCE:
                sb.append(" pkg=")
                        .append(getResPackage())
                        .append(" id=")
                        .append(String.format("0x%08x", getResId()));
                break;
            case TYPE_DATA:
                sb.append(" len=").append(getDataLength());
                if (getDataOffset() != 0) {
                    sb.append(" off=").append(getDataOffset());
                }
                break;
            case TYPE_URI:
            case TYPE_URI_ADAPTIVE_BITMAP:
                sb.append(" uri=").append(getUriString());
                break;
        }
        if (mTintList != null) {
            sb.append(" tint=");
            String sep = "";
            for (int c : mTintList.getColors()) {
                sb.append(String.format("%s0x%08x", sep, c));
                sep = "|";
            }
        }
        if (mBlendMode != DEFAULT_BLEND_MODE) sb.append(" mode=").append(mBlendMode);
        sb.append(")");
        return sb.toString();
    }

    /**
     * Parcelable interface
     */
    public int describeContents() {
        return (mType == TYPE_BITMAP || mType == TYPE_ADAPTIVE_BITMAP || mType == TYPE_DATA)
                ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
    }

    // ===== Parcelable interface ======

    private Icon(Parcel in) {
        this(in.readInt());
        switch (mType) {
            case TYPE_BITMAP:
            case TYPE_ADAPTIVE_BITMAP:
                final Bitmap bits = Bitmap.CREATOR.createFromParcel(in);
                mObj1 = bits;
                break;
            case TYPE_RESOURCE:
                final String pkg = in.readString();
                final int resId = in.readInt();
                mString1 = pkg;
                mInt1 = resId;
                break;
            case TYPE_DATA:
                final int len = in.readInt();
                final byte[] a = in.readBlob();
                if (len != a.length) {
                    throw new RuntimeException("internal unparceling error: blob length ("
                            + a.length + ") != expected length (" + len + ")");
                }
                mInt1 = len;
                mObj1 = a;
                break;
            case TYPE_URI:
            case TYPE_URI_ADAPTIVE_BITMAP:
                final String uri = in.readString();
                mString1 = uri;
                break;
            default:
                throw new RuntimeException("invalid "
                        + this.getClass().getSimpleName() + " type in parcel: " + mType);
        }
        if (in.readInt() == 1) {
            mTintList = ColorStateList.CREATOR.createFromParcel(in);
        }
        mBlendMode = BlendMode.fromValue(in.readInt());
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mType);
        switch (mType) {
            case TYPE_BITMAP:
            case TYPE_ADAPTIVE_BITMAP:
                final Bitmap bits = getBitmap();
                getBitmap().writeToParcel(dest, flags);
                break;
            case TYPE_RESOURCE:
                dest.writeString(getResPackage());
                dest.writeInt(getResId());
                break;
            case TYPE_DATA:
                dest.writeInt(getDataLength());
                dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength());
                break;
            case TYPE_URI:
            case TYPE_URI_ADAPTIVE_BITMAP:
                dest.writeString(getUriString());
                break;
        }
        if (mTintList == null) {
            dest.writeInt(0);
        } else {
            dest.writeInt(1);
            mTintList.writeToParcel(dest, flags);
        }
        dest.writeInt(BlendMode.toValue(mBlendMode));
    }

    public static final @android.annotation.NonNull Parcelable.Creator<Icon> CREATOR
            = new Parcelable.Creator<Icon>() {
        public Icon createFromParcel(Parcel in) {
            return new Icon(in);
        }

        public Icon[] newArray(int size) {
            return new Icon[size];
        }
    };

    /**
     * Scale down a bitmap to a given max width and max height. The scaling will be done in a uniform way
     * @param bitmap the bitmap to scale down
     * @param maxWidth the maximum width allowed
     * @param maxHeight the maximum height allowed
     *
     * @return the scaled bitmap if necessary or the original bitmap if no scaling was needed
     * @hide
     */
    public static Bitmap scaleDownIfNecessary(Bitmap bitmap, int maxWidth, int maxHeight) {
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        if (bitmapWidth > maxWidth || bitmapHeight > maxHeight) {
            float scale = Math.min((float) maxWidth / bitmapWidth,
                    (float) maxHeight / bitmapHeight);
            bitmap = Bitmap.createScaledBitmap(bitmap,
                    Math.max(1, (int) (scale * bitmapWidth)),
                    Math.max(1, (int) (scale * bitmapHeight)),
                    true /* filter */);
        }
        return bitmap;
    }

    /**
     * Scale down this icon to a given max width and max height.
     * The scaling will be done in a uniform way and currently only bitmaps are supported.
     * @param maxWidth the maximum width allowed
     * @param maxHeight the maximum height allowed
     *
     * @hide
     */
    public void scaleDownIfNecessary(int maxWidth, int maxHeight) {
        if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
            return;
        }
        Bitmap bitmap = getBitmap();
        setBitmap(scaleDownIfNecessary(bitmap, maxWidth, maxHeight));
    }

    /**
     * Implement this interface to receive a callback when
     * {@link #loadDrawableAsync(Context, OnDrawableLoadedListener, Handler) loadDrawableAsync}
     * is finished and your Drawable is ready.
     */
    public interface OnDrawableLoadedListener {
        void onDrawableLoaded(Drawable d);
    }

    /**
     * Wrapper around loadDrawable that does its work on a pooled thread and then
     * fires back the given (targeted) Message.
     */
    private class LoadDrawableTask implements Runnable {
        final Context mContext;
        final Message mMessage;

        public LoadDrawableTask(Context context, final Handler handler,
                final OnDrawableLoadedListener listener) {
            mContext = context;
            mMessage = Message.obtain(handler, new Runnable() {
                    @Override
                    public void run() {
                        listener.onDrawableLoaded((Drawable) mMessage.obj);
                    }
                });
        }

        public LoadDrawableTask(Context context, Message message) {
            mContext = context;
            mMessage = message;
        }

        @Override
        public void run() {
            mMessage.obj = loadDrawable(mContext);
            mMessage.sendToTarget();
        }

        public void runAsync() {
            AsyncTask.THREAD_POOL_EXECUTOR.execute(this);
        }
    }
}
