diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java index 4eeb20769e091..d6803e8052c6e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java @@ -19,14 +19,14 @@ package com.android.wm.shell.bubbles; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Paint; +import android.graphics.Color; import android.graphics.Path; +import android.graphics.Rect; import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.Drawable; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BitmapInfo; -import com.android.launcher3.icons.ShadowGenerator; import com.android.wm.shell.R; /** @@ -44,78 +44,77 @@ public class BubbleBadgeIconFactory extends BaseIconFactory { * will include the workprofile indicator on the badge if appropriate. */ BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) { - ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize); - Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize); - if (userBadgedAppIcon instanceof AdaptiveIconDrawable) { - userBadgedBitmap = Bitmap.createScaledBitmap( - getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */ - userBadgedAppIcon.getIntrinsicWidth()), - mIconBitmapSize, mIconBitmapSize, /* filter */ true); + AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon; + userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground()); + } + if (isImportantConversation) { + userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon); + } + Bitmap userBadgedBitmap = createIconBitmap( + userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW); + return createIconBitmap(userBadgedBitmap); + } + + private class CircularRingDrawable extends CircularAdaptiveIcon { + + final int mImportantConversationColor; + final Rect mTempBounds = new Rect(); + + final Drawable mDr; + + CircularRingDrawable(Drawable dr) { + super(null, null); + mDr = dr; + mImportantConversationColor = mContext.getResources().getColor( + R.color.important_conversation, null); } - if (isImportantConversation) { - final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize( + @Override + public void draw(Canvas canvas) { + int save = canvas.save(); + canvas.clipPath(getIconMask()); + canvas.drawColor(mImportantConversationColor); + int ringStrokeWidth = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.importance_ring_stroke_width); - final int importantConversationColor = mContext.getResources().getColor( - R.color.important_conversation, null); - Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(), - userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig()); - Canvas c = new Canvas(badgeAndRing); - - Paint ringPaint = new Paint(); - ringPaint.setStyle(Paint.Style.FILL); - ringPaint.setColor(importantConversationColor); - ringPaint.setAntiAlias(true); - c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint); - - final int bitmapTop = (int) ringStrokeWidth; - final int bitmapLeft = (int) ringStrokeWidth; - final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth; - final int bitmapHeight = c.getHeight() - 2 * (int) ringStrokeWidth; - - Bitmap scaledBitmap = Bitmap.createScaledBitmap(userBadgedBitmap, bitmapWidth, - bitmapHeight, /* filter */ true); - c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null); - - shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c); - return createIconBitmap(badgeAndRing); - } else { - Canvas c = new Canvas(); - c.setBitmap(userBadgedBitmap); - shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c); - return createIconBitmap(userBadgedBitmap); + mTempBounds.set(getBounds()); + mTempBounds.inset(ringStrokeWidth, ringStrokeWidth); + mDr.setBounds(mTempBounds); + mDr.draw(canvas); + canvas.restoreToCount(save); } } - private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) { - Drawable foreground = icon.getForeground(); - Drawable background = icon.getBackground(); - Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(); - canvas.setBitmap(bitmap); + private static class CircularAdaptiveIcon extends AdaptiveIconDrawable { - // Clip canvas to circle. - Path circlePath = new Path(); - circlePath.addCircle(/* x */ size / 2f, - /* y */ size / 2f, - /* radius */ size / 2f, - Path.Direction.CW); - canvas.clipPath(circlePath); + final Path mPath = new Path(); - // Draw background. - background.setBounds(0, 0, size, size); - background.draw(canvas); + CircularAdaptiveIcon(Drawable bg, Drawable fg) { + super(bg, fg); + } - // Draw foreground. The foreground and background drawables are derived from adaptive icons - // Some icon shapes fill more space than others, so adaptive icons are normalized to about - // the same size. This size is smaller than the original bounds, so we estimate - // the difference in this offset. - int offset = size / 5; - foreground.setBounds(-offset, -offset, size + offset, size + offset); - foreground.draw(canvas); + @Override + public Path getIconMask() { + mPath.reset(); + Rect bounds = getBounds(); + mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW); + return mPath; + } - canvas.setBitmap(null); - return bitmap; + @Override + public void draw(Canvas canvas) { + int save = canvas.save(); + canvas.clipPath(getIconMask()); + + canvas.drawColor(Color.BLACK); + Drawable d; + if ((d = getBackground()) != null) { + d.draw(canvas); + } + if ((d = getForeground()) != null) { + d.draw(canvas); + } + canvas.restoreToCount(save); + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java index 9d3bf34895d31..5dab8a071f76e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; +import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; @@ -65,4 +66,19 @@ public class BubbleIconFactory extends BaseIconFactory { return null; } } + + /** + * Creates the bitmap for the provided drawable and returns the scale used for + * drawing the actual drawable. + */ + public Bitmap createIconBitmap(@NonNull Drawable icon, float[] outScale) { + if (outScale == null) { + outScale = new float[1]; + } + icon = normalizeAndWrapToAdaptiveIcon(icon, + true /* shrinkNonAdaptiveIcons */, + null /* outscale */, + outScale); + return createIconBitmap(icon, outScale[0], BITMAP_GENERATION_MODE_WITH_SHADOW); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index 69762c9bc06a1..f437553337efe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -195,15 +195,18 @@ public class BubbleViewInfoTask extends AsyncTask