1 /*
2  * Copyright (C) 2017 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.settingslib.graph;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.graphics.PorterDuff;
23 import android.graphics.PorterDuffColorFilter;
24 import android.graphics.drawable.Drawable;
25 import android.graphics.drawable.LayerDrawable;
26 import android.view.Gravity;
27 
28 import androidx.annotation.VisibleForTesting;
29 
30 import com.android.settingslib.R;
31 import com.android.settingslib.Utils;
32 
33 /**
34  * LayerDrawable contains the bluetooth device icon and battery gauge icon
35  */
36 public class BluetoothDeviceLayerDrawable extends LayerDrawable {
37 
38     private BluetoothDeviceLayerDrawableState mState;
39 
BluetoothDeviceLayerDrawable(@onNull Drawable[] layers)40     private BluetoothDeviceLayerDrawable(@NonNull Drawable[] layers) {
41         super(layers);
42     }
43 
44     /**
45      * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon.
46      * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end.
47      *
48      * @param context      used to get the spec for icon
49      * @param resId        represents the bluetooth device drawable
50      * @param batteryLevel the battery level for bluetooth device
51      */
createLayerDrawable(Context context, int resId, int batteryLevel)52     public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId,
53             int batteryLevel) {
54         return createLayerDrawable(context, resId, batteryLevel, 1 /*iconScale*/);
55     }
56 
57     /**
58      * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon.
59      * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end.
60      *
61      * @param context      used to get the spec for icon
62      * @param resId        represents the bluetooth device drawable
63      * @param batteryLevel the battery level for bluetooth device
64      * @param iconScale    the ratio of height between battery icon and bluetooth icon
65      */
createLayerDrawable(Context context, int resId, int batteryLevel, float iconScale)66     public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId,
67             int batteryLevel, float iconScale) {
68         final Drawable deviceDrawable = context.getDrawable(resId);
69 
70         final BatteryMeterDrawable batteryDrawable = new BatteryMeterDrawable(context,
71                 context.getColor(R.color.meter_background_color), batteryLevel);
72         final int pad = context.getResources().getDimensionPixelSize(R.dimen.bt_battery_padding);
73         batteryDrawable.setPadding(pad, pad, pad, pad);
74 
75         final BluetoothDeviceLayerDrawable drawable = new BluetoothDeviceLayerDrawable(
76                 new Drawable[]{deviceDrawable, batteryDrawable});
77         // Set the bluetooth icon at the left
78         drawable.setLayerGravity(0 /* index of deviceDrawable */, Gravity.START);
79         // Set battery icon to the right of the bluetooth icon
80         drawable.setLayerInsetStart(1 /* index of batteryDrawable */,
81                 deviceDrawable.getIntrinsicWidth());
82         drawable.setLayerInsetTop(1 /* index of batteryDrawable */,
83                 (int) (deviceDrawable.getIntrinsicHeight() * (1 - iconScale)));
84 
85         drawable.setConstantState(context, resId, batteryLevel, iconScale);
86 
87         return drawable;
88     }
89 
setConstantState(Context context, int resId, int batteryLevel, float iconScale)90     public void setConstantState(Context context, int resId, int batteryLevel, float iconScale) {
91         mState = new BluetoothDeviceLayerDrawableState(context, resId, batteryLevel, iconScale);
92     }
93 
94     @Override
getConstantState()95     public ConstantState getConstantState() {
96         return mState;
97     }
98 
99     /**
100      * Battery gauge icon with new spec.
101      */
102     @VisibleForTesting
103     static class BatteryMeterDrawable extends BatteryMeterDrawableBase {
104         private final float mAspectRatio;
105         @VisibleForTesting
106         int mFrameColor;
107 
BatteryMeterDrawable(Context context, int frameColor, int batteryLevel)108         public BatteryMeterDrawable(Context context, int frameColor, int batteryLevel) {
109             super(context, frameColor);
110             final Resources resources = context.getResources();
111             mButtonHeightFraction = resources.getFraction(
112                     R.fraction.bt_battery_button_height_fraction, 1, 1);
113             mAspectRatio = resources.getFraction(R.fraction.bt_battery_ratio_fraction, 1, 1);
114 
115             final int tintColor = Utils.getColorAttrDefaultColor(context,
116                     android.R.attr.colorControlNormal);
117             setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
118             setBatteryLevel(batteryLevel);
119             mFrameColor = frameColor;
120         }
121 
122         @Override
getAspectRatio()123         protected float getAspectRatio() {
124             return mAspectRatio;
125         }
126 
127         @Override
getRadiusRatio()128         protected float getRadiusRatio() {
129             // Remove the round edge
130             return 0;
131         }
132     }
133 
134     /**
135      * {@link ConstantState} to restore the {@link BluetoothDeviceLayerDrawable}
136      */
137     private static class BluetoothDeviceLayerDrawableState extends ConstantState {
138         Context context;
139         int resId;
140         int batteryLevel;
141         float iconScale;
142 
BluetoothDeviceLayerDrawableState(Context context, int resId, int batteryLevel, float iconScale)143         public BluetoothDeviceLayerDrawableState(Context context, int resId,
144                 int batteryLevel, float iconScale) {
145             this.context = context;
146             this.resId = resId;
147             this.batteryLevel = batteryLevel;
148             this.iconScale = iconScale;
149         }
150 
151         @Override
newDrawable()152         public Drawable newDrawable() {
153             return createLayerDrawable(context, resId, batteryLevel, iconScale);
154         }
155 
156         @Override
getChangingConfigurations()157         public int getChangingConfigurations() {
158             return 0;
159         }
160     }
161 }
162