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