Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7728f8e authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7398294 from ab267964 to sc-release

Change-Id: I039a7d8693cc7c7f54e2311d93b701f7411a4d46
parents 332bf7c2 ab267964
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.UserHandle;
import android.util.Log;
@@ -146,14 +147,17 @@ public class BitmapInfo {
        /**
         * Called for creating a custom BitmapInfo
         */
        default BitmapInfo getExtendedInfo(Bitmap bitmap, int color,
                BaseIconFactory iconFactory, float normalizationScale, UserHandle user) {
            return BitmapInfo.of(bitmap, color);
        }
        BitmapInfo getExtendedInfo(Bitmap bitmap, int color,
                BaseIconFactory iconFactory, float normalizationScale, UserHandle user);

        /**
         * Called to draw the UI independent of any runtime configurations like time or theme
         */
        default void drawForPersistence(Canvas canvas) { }
        void drawForPersistence(Canvas canvas);

        /**
         * Returns a new icon with theme applied
         */
        Drawable getThemedDrawable(Context context);
    }
}
+137 −47
Original line number Diff line number Diff line
@@ -15,14 +15,25 @@
 */
package com.android.launcher3.icons;

import static com.android.launcher3.icons.ThemedIconDrawable.getColors;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
@@ -31,11 +42,15 @@ import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.util.TypedValue;

import androidx.annotation.Nullable;

import com.android.launcher3.icons.ThemedIconDrawable.ThemeData;

import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import java.util.function.IntFunction;

/**
 * Wrapper over {@link AdaptiveIconDrawable} to intercept icon flattening logic for dynamic
@@ -74,6 +89,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap

    private final AnimationInfo mAnimationInfo = new AnimationInfo();
    private int mTargetSdkVersion;
    protected ThemeData mThemeData;

    public ClockDrawableWrapper(AdaptiveIconDrawable base) {
        super(base.getBackground(), base.getForeground());
@@ -88,7 +104,46 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
            PackageManager pm = context.getPackageManager();
            ApplicationInfo appInfo =  pm.getApplicationInfo(pkg,
                    PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
            final Bundle metadata = appInfo.metaData;
            Resources res = pm.getResourcesForApplication(appInfo);
            return forExtras(appInfo, appInfo.metaData,
                    resId -> res.getDrawableForDensity(resId, iconDpi));
        } catch (Exception e) {
            Log.d(TAG, "Unable to load clock drawable info", e);
        }
        return null;
    }

    private static ClockDrawableWrapper fromThemeData(Context context, ThemeData themeData) {
        try {
            TypedArray ta = themeData.mResources.obtainTypedArray(themeData.mResID);
            int count = ta.length();
            Bundle extras = new Bundle();
            for (int i = 0; i < count; i += 2) {
                TypedValue v = ta.peekValue(i + 1);
                extras.putInt(ta.getString(i), v.type >= TypedValue.TYPE_FIRST_INT
                        && v.type <= TypedValue.TYPE_LAST_INT
                        ? v.data : v.resourceId);
            }
            ta.recycle();
            ClockDrawableWrapper drawable = ClockDrawableWrapper.forExtras(
                    context.getApplicationInfo(), extras, resId -> {
                        int[] colors = getColors(context);
                        Drawable bg = new ColorDrawable(colors[0]);
                        Drawable fg = themeData.mResources.getDrawable(resId).mutate();
                        fg.setTint(colors[1]);
                        return new AdaptiveIconDrawable(bg, fg);
                    });
            if (drawable != null) {
                return drawable;
            }
        } catch (Exception e) {
            Log.e(TAG, "Error loading themed clock", e);
        }
        return null;
    }

    private static ClockDrawableWrapper forExtras(ApplicationInfo appInfo, Bundle metadata,
            IntFunction<Drawable> drawableProvider) {
        if (metadata == null) {
            return null;
        }
@@ -97,8 +152,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
            return null;
        }

            Drawable drawable = pm.getResourcesForApplication(appInfo).getDrawableForDensity(
                    drawableId, iconDpi).mutate();
        Drawable drawable = drawableProvider.apply(drawableId).mutate();
        if (!(drawable instanceof AdaptiveIconDrawable)) {
            return null;
        }
@@ -134,14 +188,10 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
        }
        info.applyTime(Calendar.getInstance(), foreground);
        return wrapper;
        } catch (Exception e) {
            Log.d(TAG, "Unable to load clock drawable info", e);
        }
        return null;
    }

    @Override
    public BitmapInfo getExtendedInfo(Bitmap bitmap, int color,
    public ClockBitmapInfo getExtendedInfo(Bitmap bitmap, int color,
            BaseIconFactory iconFactory, float normalizationScale, UserHandle user) {
        iconFactory.disableColorExtraction();
        AdaptiveIconDrawable background = new AdaptiveIconDrawable(
@@ -150,7 +200,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
                Process.myUserHandle(), mTargetSdkVersion, false);

        return new ClockBitmapInfo(bitmap, color, normalizationScale,
                mAnimationInfo, bitmapInfo.icon);
                mAnimationInfo, bitmapInfo.icon, mThemeData);
    }

    @Override
@@ -163,6 +213,15 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
        mAnimationInfo.applyTime(Calendar.getInstance(), (LayerDrawable) getForeground());
    }

    @Override
    public Drawable getThemedDrawable(Context context) {
        if (mThemeData != null) {
            ClockDrawableWrapper drawable = fromThemeData(context, mThemeData);
            return drawable == null ? this : drawable;
        }
        return this;
    }

    private void resetLevel(LayerDrawable drawable, int index) {
        if (index != INVALID_VALUE) {
            drawable.getDrawable(index).setLevel(0);
@@ -214,20 +273,47 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
        }
    }

    private static class ClockBitmapInfo extends BitmapInfo {
    static class ClockBitmapInfo extends BitmapInfo {

        public final float scale;
        public final int offset;
        public final AnimationInfo animInfo;
        public final Bitmap mFlattenedBackground;

        public final ThemeData themeData;

        ClockBitmapInfo(Bitmap icon, int color, float scale, AnimationInfo animInfo,
                Bitmap background) {
                Bitmap background, ThemeData themeData) {
            super(icon, color);
            this.scale = scale;
            this.animInfo = animInfo;
            this.offset = (int) Math.ceil(ShadowGenerator.BLUR_FACTOR * icon.getWidth());
            this.mFlattenedBackground = background;
            this.themeData = themeData;
        }

        @Override
        public FastBitmapDrawable newThemedIcon(Context context) {
            if (themeData != null) {
                ClockDrawableWrapper wrapper = fromThemeData(context, themeData);
                if (wrapper != null) {
                    int[] colors = getColors(context);
                    ColorFilter bgFilter = new PorterDuffColorFilter(colors[0], Mode.SRC_ATOP);
                    ClockBitmapInfo bitmapInfo = new ClockBitmapInfo(icon, colors[1], scale,
                            wrapper.mAnimationInfo, mFlattenedBackground, themeData) {

                        @Override
                        void drawBackground(Canvas canvas, Rect bounds, Paint paint) {
                            ColorFilter oldFilter = paint.getColorFilter();
                            paint.setColorFilter(bgFilter);
                            super.drawBackground(canvas, bounds, paint);
                            paint.setColorFilter(oldFilter);
                        }
                    };
                    return bitmapInfo.newIcon(context);
                }
            }
            return super.newThemedIcon(context);
        }

        @Override
@@ -242,6 +328,11 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
        public byte[] toByteArray() {
            return null;
        }

        void drawBackground(Canvas canvas, Rect bounds, Paint paint) {
            // draw the background that is already flattened to a bitmap
            canvas.drawBitmap(mFlattenedBackground, null, bounds, paint);
        }
    }

    private static class ClockIconDrawable extends FastBitmapDrawable implements Runnable {
@@ -274,8 +365,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
                super.drawInternal(canvas, bounds);
                return;
            }
            // draw the background that is already flattened to a bitmap
            canvas.drawBitmap(mInfo.mFlattenedBackground, null, bounds, mPaint);
            mInfo.drawBackground(canvas, bounds, mPaint);

            // prepare and draw the foreground
            mInfo.animInfo.applyTime(mTime, mForeground);
+7 −0
Original line number Diff line number Diff line
@@ -113,6 +113,13 @@ public class FastBitmapDrawable extends Drawable {
        canvas.drawBitmap(mBitmap, null, bounds, mPaint);
    }

    /**
     * Returns the primary icon color
     */
    public int getIconColor() {
        return mIconColor;
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mColorFilter = cf;
+13 −3
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ public class IconProvider {
    private final ComponentName mCalendar;
    private final ComponentName mClock;

    static final int ICON_TYPE_DEFAULT = 0;
    static final int ICON_TYPE_CALENDAR = 1;
    static final int ICON_TYPE_CLOCK = 2;

    public IconProvider(Context context) {
        this(context, false);
    }
@@ -143,17 +147,23 @@ public class IconProvider {
            Supplier<Drawable> fallback) {
        Drawable icon = null;

        int iconType = ICON_TYPE_DEFAULT;
        if (mCalendar != null && mCalendar.getPackageName().equals(packageName)) {
            icon = loadCalendarDrawable(iconDpi);
            iconType = ICON_TYPE_CALENDAR;
        } else if (mClock != null
                && mClock.getPackageName().equals(packageName)
                && Process.myUserHandle().equals(user)) {
            icon = loadClockDrawable(iconDpi);
            iconType = ICON_TYPE_CLOCK;
        }
        if (icon == null) {
            icon = fallback.get();
            iconType = ICON_TYPE_DEFAULT;
        }
        icon = icon == null ? fallback.get() : icon;

        ThemeData td = getThemedIconMap().get(packageName);
        return td != null ? td.wrapDrawable(icon) : icon;
        return td != null ? td.wrapDrawable(icon, iconType) : icon;
    }

    private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) {
@@ -265,7 +275,7 @@ public class IconProvider {
    /**
     * @return Today's day of the month, zero-indexed.
     */
    private int getDay() {
    static int getDay() {
        return Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - 1;
    }

+35 −16
Original line number Diff line number Diff line
@@ -20,9 +20,12 @@ import static android.content.res.Configuration.UI_MODE_NIGHT_YES;
import static android.content.res.Resources.ID_NULL;

import static com.android.launcher3.icons.GraphicsUtils.getExpectedBitmapSize;
import static com.android.launcher3.icons.IconProvider.ICON_TYPE_CALENDAR;
import static com.android.launcher3.icons.IconProvider.ICON_TYPE_CLOCK;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -38,6 +41,7 @@ import android.util.Log;
import androidx.annotation.Nullable;

import com.android.launcher3.icons.BitmapInfo.Extender;
import com.android.launcher3.icons.ClockDrawableWrapper.ClockBitmapInfo;
import com.android.launcher3.icons.cache.BaseIconCache;

import java.io.ByteArrayInputStream;
@@ -63,7 +67,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable {
    private final Rect mBadgeBounds;

    protected ThemedIconDrawable(ThemedConstantState constantState) {
        super(constantState.mBitmap, constantState.mIconColor, constantState.mIsDisabled);
        super(constantState.mBitmap, constantState.colorFg, constantState.mIsDisabled);
        bitmapInfo = constantState.bitmapInfo;
        colorBg = constantState.colorBg;
        colorFg = constantState.colorFg;
@@ -72,6 +76,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable {
        mBgWrapper = new AdaptiveIconDrawable(new ColorDrawable(colorBg), null);
        mBadgeBounds = bitmapInfo.mUserBadge == null ? null :
                new Rect(0, 0, bitmapInfo.mUserBadge.getWidth(), bitmapInfo.mUserBadge.getHeight());

    }

    @Override
@@ -147,7 +152,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable {
            if (isNullOrLowRes()) {
                return null;
            }
            String resName = mThemeData.mResources.getResourceName(mThemeData.mIconID);
            String resName = mThemeData.mResources.getResourceName(mThemeData.mResID);
            ByteArrayOutputStream out = new ByteArrayOutputStream(
                    getExpectedBitmapSize(icon) + 3 + resName.length());
            try {
@@ -200,30 +205,46 @@ public class ThemedIconDrawable extends FastBitmapDrawable {
    public static class ThemeData {

        final Resources mResources;
        final int mIconID;
        final int mResID;

        public ThemeData(Resources resources, int iconID) {
        public ThemeData(Resources resources, int resID) {
            mResources = resources;
            mIconID = iconID;
            mResID = resID;
        }

        Drawable loadMonochromeDrawable(int accentColor) {
            Drawable d = mResources.getDrawable(mIconID).mutate();
            Drawable d = mResources.getDrawable(mResID).mutate();
            d.setTint(accentColor);
            d = new InsetDrawable(d, .15f);
            d = new InsetDrawable(d, .2f);
            return d;
        }

        public Drawable wrapDrawable(Drawable original) {
            return (original instanceof AdaptiveIconDrawable)
                    ? new ThemedAdaptiveIcon((AdaptiveIconDrawable) original, this)
                    : original;
        public Drawable wrapDrawable(Drawable original, int iconType) {
            if (!(original instanceof AdaptiveIconDrawable)) {
                return original;
            }
            AdaptiveIconDrawable aid = (AdaptiveIconDrawable) original;
            String resourceType = mResources.getResourceTypeName(mResID);
            if (iconType == ICON_TYPE_CALENDAR && "array".equals(resourceType)) {
                TypedArray ta = mResources.obtainTypedArray(mResID);
                int id = ta.getResourceId(IconProvider.getDay(), ID_NULL);
                ta.recycle();
                return id == ID_NULL ? original
                        : new ThemedAdaptiveIcon(aid, new ThemeData(mResources, id));
            } else if (iconType == ICON_TYPE_CLOCK && "array".equals(resourceType)) {
                ((ClockDrawableWrapper) original).mThemeData = this;
                return original;
            } else if ("drawable".equals(resourceType)) {
                return new ThemedAdaptiveIcon(aid, this);
            } else {
                return original;
            }
        }
    }

    public static class ThemedAdaptiveIcon extends AdaptiveIconDrawable implements Extender {
    static class ThemedAdaptiveIcon extends AdaptiveIconDrawable implements Extender {

        private final ThemeData mThemeData;
        protected final ThemeData mThemeData;

        public ThemedAdaptiveIcon(AdaptiveIconDrawable parent, ThemeData themeData) {
            super(parent.getBackground(), parent.getForeground());
@@ -243,9 +264,7 @@ public class ThemedIconDrawable extends FastBitmapDrawable {
            draw(canvas);
        }

        /**
         * Returns a new icon with theme applied
         */
        @Override
        public Drawable getThemedDrawable(Context context) {
            int[] colors = getColors(context);
            Drawable bg = new ColorDrawable(colors[0]);