• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.bubbles;
18 
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import android.graphics.Path;
23 import android.graphics.Rect;
24 import android.graphics.drawable.AdaptiveIconDrawable;
25 import android.graphics.drawable.Drawable;
26 
27 import com.android.launcher3.icons.BaseIconFactory;
28 import com.android.launcher3.icons.BitmapInfo;
29 import com.android.wm.shell.R;
30 
31 /**
32  * Factory for creating app badge icons that are shown on bubbles.
33  */
34 public class BubbleBadgeIconFactory extends BaseIconFactory {
35 
BubbleBadgeIconFactory(Context context)36     public BubbleBadgeIconFactory(Context context) {
37         super(context, context.getResources().getConfiguration().densityDpi,
38                 context.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size));
39     }
40 
41     /**
42      * Returns a {@link BitmapInfo} for the app-badge that is shown on top of each bubble. This
43      * will include the workprofile indicator on the badge if appropriate.
44      */
getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation)45     BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
46         if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
47             AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon;
48             userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground());
49         }
50         if (isImportantConversation) {
51             userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon);
52         }
53         Bitmap userBadgedBitmap = createIconBitmap(
54                 userBadgedAppIcon, 1, MODE_WITH_SHADOW);
55         return createIconBitmap(userBadgedBitmap);
56     }
57 
58     private class CircularRingDrawable extends CircularAdaptiveIcon {
59 
60         final int mImportantConversationColor;
61         final int mRingWidth;
62         final Rect mInnerBounds = new Rect();
63 
64         final Drawable mDr;
65 
CircularRingDrawable(Drawable dr)66         CircularRingDrawable(Drawable dr) {
67             super(null, null);
68             mDr = dr;
69             mImportantConversationColor = mContext.getResources().getColor(
70                     R.color.important_conversation, null);
71             mRingWidth = mContext.getResources().getDimensionPixelSize(
72                     com.android.internal.R.dimen.importance_ring_stroke_width);
73         }
74 
75         @Override
draw(Canvas canvas)76         public void draw(Canvas canvas) {
77             int save = canvas.save();
78             canvas.clipPath(getIconMask());
79             canvas.drawColor(mImportantConversationColor);
80             mInnerBounds.set(getBounds());
81             mInnerBounds.inset(mRingWidth, mRingWidth);
82             canvas.translate(mInnerBounds.left, mInnerBounds.top);
83             mDr.setBounds(0, 0, mInnerBounds.width(), mInnerBounds.height());
84             mDr.draw(canvas);
85             canvas.restoreToCount(save);
86         }
87     }
88 
89     private static class CircularAdaptiveIcon extends AdaptiveIconDrawable {
90 
91         final Path mPath = new Path();
92 
CircularAdaptiveIcon(Drawable bg, Drawable fg)93         CircularAdaptiveIcon(Drawable bg, Drawable fg) {
94             super(bg, fg);
95         }
96 
97         @Override
getIconMask()98         public Path getIconMask() {
99             mPath.reset();
100             Rect bounds = getBounds();
101             mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW);
102             return mPath;
103         }
104 
105         @Override
draw(Canvas canvas)106         public void draw(Canvas canvas) {
107             int save = canvas.save();
108             canvas.clipPath(getIconMask());
109 
110             Drawable d;
111             if ((d = getBackground()) != null) {
112                 d.draw(canvas);
113             }
114             if ((d = getForeground()) != null) {
115                 d.draw(canvas);
116             }
117             canvas.restoreToCount(save);
118         }
119     }
120 }
121