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.systemui.dreams;
18 
19 import android.annotation.ColorInt;
20 import android.content.Context;
21 import android.content.res.TypedArray;
22 import android.graphics.Bitmap;
23 import android.graphics.Canvas;
24 import android.graphics.Color;
25 import android.graphics.ColorFilter;
26 import android.graphics.Paint;
27 import android.graphics.Rect;
28 import android.graphics.drawable.Drawable;
29 import android.util.AttributeSet;
30 
31 import androidx.annotation.NonNull;
32 import androidx.annotation.Nullable;
33 
34 import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarView;
35 import com.android.systemui.res.R;
36 import com.android.systemui.statusbar.AlphaOptimizedImageView;
37 
38 /**
39  * An {@link AlphaOptimizedImageView} that is responsible for rendering a dot. Used by
40  * {@link AmbientStatusBarView}.
41  */
42 public class DreamOverlayDotImageView extends AlphaOptimizedImageView {
43     private final @ColorInt int mDotColor;
44 
DreamOverlayDotImageView(Context context)45     public DreamOverlayDotImageView(Context context) {
46         this(context, null);
47     }
48 
DreamOverlayDotImageView(Context context, AttributeSet attrs)49     public DreamOverlayDotImageView(Context context, AttributeSet attrs) {
50         this(context, attrs, 0);
51     }
52 
DreamOverlayDotImageView(Context context, AttributeSet attrs, int defStyleAttr)53     public DreamOverlayDotImageView(Context context, AttributeSet attrs, int defStyleAttr) {
54         this(context, attrs, defStyleAttr, 0);
55     }
56 
DreamOverlayDotImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)57     public DreamOverlayDotImageView(Context context, AttributeSet attrs, int defStyleAttr,
58             int defStyleRes) {
59         super(context, attrs, defStyleAttr, defStyleRes);
60         TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
61                 R.styleable.DreamOverlayDotImageView, 0, 0);
62 
63         try {
64             mDotColor = a.getColor(R.styleable.DreamOverlayDotImageView_dotColor, Color.WHITE);
65         } finally {
66             a.recycle();
67         }
68     }
69 
70     @Override
onFinishInflate()71     protected void onFinishInflate() {
72         super.onFinishInflate();
73         setImageDrawable(new DotDrawable(mDotColor));
74     }
75 
76     private static class DotDrawable extends Drawable {
77         private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
78         private Bitmap mDotBitmap;
79         private final Rect mBounds = new Rect();
80         private final @ColorInt int mDotColor;
81 
DotDrawable(@olorInt int color)82         DotDrawable(@ColorInt int color) {
83             mDotColor = color;
84         }
85 
86         @Override
draw(@onNull Canvas canvas)87         public void draw(@NonNull Canvas canvas) {
88             if (mBounds.isEmpty()) {
89                 return;
90             }
91 
92             if (mDotBitmap == null) {
93                 mDotBitmap = createBitmap(mBounds.width(), mBounds.height());
94             }
95 
96             canvas.drawBitmap(mDotBitmap, null, mBounds, mPaint);
97         }
98 
99         @Override
onBoundsChange(Rect bounds)100         protected void onBoundsChange(Rect bounds) {
101             super.onBoundsChange(bounds);
102             mBounds.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
103             // Make sure to regenerate the dot bitmap when the bounds change.
104             mDotBitmap = null;
105         }
106 
107         @Override
setAlpha(int alpha)108         public void setAlpha(int alpha) {
109         }
110 
111         @Override
setColorFilter(@ullable ColorFilter colorFilter)112         public void setColorFilter(@Nullable ColorFilter colorFilter) {
113         }
114 
115         @Override
getOpacity()116         public int getOpacity() {
117             return 0;
118         }
119 
createBitmap(int width, int height)120         private Bitmap createBitmap(int width, int height) {
121             Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
122             Canvas canvas = new Canvas(bitmap);
123             Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
124             paint.setColor(mDotColor);
125             canvas.drawCircle(width / 2.f, height / 2.f, Math.min(width, height) / 2.f, paint);
126             return bitmap;
127         }
128     }
129 }
130