1 /*
2  * Copyright (C) 2021 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.settings.accessibility;
18 
19 import android.content.Context;
20 import android.graphics.drawable.Drawable;
21 import android.graphics.drawable.LayerDrawable;
22 
23 import androidx.annotation.NonNull;
24 import androidx.annotation.VisibleForTesting;
25 
26 import com.android.settings.R;
27 
28 import java.util.Objects;
29 
30 /** LayerDrawable that contains device icon as background and given icon as foreground. */
31 public class AccessibilityLayerDrawable extends LayerDrawable {
32 
33     private AccessibilityLayerDrawableState mState;
34 
35     /**
36      * Creates a new layer drawable with the list of specified layers.
37      *
38      * @param layers a list of drawables to use as layers in this new drawable,
39      *               must be non-null
40      */
AccessibilityLayerDrawable(@onNull Drawable[] layers)41     private AccessibilityLayerDrawable(@NonNull Drawable[] layers) {
42         super(layers);
43     }
44 
45     /**
46      * Create the {@link LayerDrawable} that contains device icon as background and given menu icon
47      * with given {@code opacity} value as foreground.
48      *
49      * @param context the valid context used to get the icon
50      * @param resId the resource ID of the given icon
51      * @param opacity the opacity to apply to the given icon
52      * @return the drawable that combines the device icon and the given icon
53      */
createLayerDrawable(Context context, int resId, int opacity)54     public static AccessibilityLayerDrawable createLayerDrawable(Context context, int resId,
55             int opacity) {
56         final Drawable bg = context.getDrawable(R.drawable.accessibility_button_preview_base);
57         final AccessibilityLayerDrawable basicDrawable = new AccessibilityLayerDrawable(
58                 new Drawable[]{bg, null});
59 
60         basicDrawable.updateLayerDrawable(context, resId, opacity);
61         return basicDrawable;
62     }
63 
64     /**
65      * Update the drawable  with given {@code resId} drawable and {@code opacity}(alpha)
66      * value at index 1 layer.
67      *
68      * @param context the valid context used to get the icon
69      * @param resId the resource ID of the given icon
70      * @param opacity the opacity to apply to the given icon
71      */
updateLayerDrawable(Context context, int resId, int opacity)72     public void updateLayerDrawable(Context context, int resId, int opacity) {
73         final Drawable icon = context.getDrawable(resId);
74         icon.setAlpha(opacity);
75         this.setDrawable(/* index= */ 1, icon);
76         this.setConstantState(context, resId, opacity);
77     }
78 
79     @Override
getConstantState()80     public ConstantState getConstantState() {
81         return mState;
82     }
83 
84     /** Stores the constant state and data to the given drawable. */
setConstantState(Context context, int resId, int opacity)85     private void setConstantState(Context context, int resId, int opacity) {
86         mState = new AccessibilityLayerDrawableState(context, resId, opacity);
87     }
88 
89     /** {@link ConstantState} to store the data of {@link AccessibilityLayerDrawable}. */
90     @VisibleForTesting
91     static class AccessibilityLayerDrawableState extends ConstantState {
92 
93         private final Context mContext;
94         private final int mResId;
95         private final int mOpacity;
96 
AccessibilityLayerDrawableState(Context context, int resId, int opacity)97         AccessibilityLayerDrawableState(Context context, int resId, int opacity) {
98             mContext = context;
99             mResId = resId;
100             mOpacity = opacity;
101         }
102 
103         @NonNull
104         @Override
newDrawable()105         public Drawable newDrawable() {
106             return createLayerDrawable(mContext, mResId, mOpacity);
107         }
108 
109         @Override
getChangingConfigurations()110         public int getChangingConfigurations() {
111             return 0;
112         }
113 
114         @Override
equals(Object o)115         public boolean equals(Object o) {
116             if (this == o) {
117                 return true;
118             }
119             if (o == null || getClass() != o.getClass()) {
120                 return false;
121             }
122             final AccessibilityLayerDrawableState that = (AccessibilityLayerDrawableState) o;
123             return mResId == that.mResId
124                     && mOpacity == that.mOpacity
125                     && Objects.equals(mContext, that.mContext);
126         }
127 
128         @Override
hashCode()129         public int hashCode() {
130             return Objects.hash(mContext, mResId, mOpacity);
131         }
132     }
133 }
134