BatteryMeterDrawableBase.java revision d866b8aa0341e960399c425b021b4a6aedfa5b9e
1597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei/*
2597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * Copyright (C) 2017 The Android Open Source Project
3597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei *
4597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * Licensed under the Apache License, Version 2.0 (the "License");
5597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * you may not use this file except in compliance with the License.
6597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * You may obtain a copy of the License at
7597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei *
8597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei *      http://www.apache.org/licenses/LICENSE-2.0
9597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei *
10597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * Unless required by applicable law or agreed to in writing, software
11597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * distributed under the License is distributed on an "AS IS" BASIS,
12597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * See the License for the specific language governing permissions and
14597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * limitations under the License.
15597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei */
16597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
17597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleipackage com.android.settingslib.graph;
18597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
19597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.animation.ArgbEvaluator;
20597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.annotation.Nullable;
21597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.content.Context;
22597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.content.res.Resources;
23597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.content.res.TypedArray;
24597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Canvas;
25597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Color;
26597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.ColorFilter;
27597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Paint;
28597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Path;
29597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.RectF;
30597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Typeface;
31597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.drawable.Drawable;
3258be7a675b7aa505255f0c91fee755f8290e8363Jason Monkimport android.util.TypedValue;
3358be7a675b7aa505255f0c91fee755f8290e8363Jason Monk
34597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport com.android.settingslib.R;
35597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport com.android.settingslib.Utils;
36597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
37597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleipublic class BatteryMeterDrawableBase extends Drawable {
38597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
39597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private static final float ASPECT_RATIO = 9.5f / 14.5f;
40597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName();
41597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
42597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    protected final Context mContext;
43597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
446aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    private int mLevel = -1;
456aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    private boolean mPluggedIn;
466aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    private boolean mPowerSaveEnabled;
476aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    private boolean mShowPercent;
48597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
49597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private static final boolean SINGLE_DIGIT_PERCENT = false;
50597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
51597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private static final int FULL = 96;
52597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
53597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private static final float BOLT_LEVEL_THRESHOLD = 0.3f;  // opaque bolt below this fraction
54597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
55597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final int[] mColors;
56597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final int mIntrinsicWidth;
57597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final int mIntrinsicHeight;
58597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
59597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private float mButtonHeightFraction;
60597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private float mSubpixelSmoothingLeft;
61597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private float mSubpixelSmoothingRight;
62597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
63597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            mPlusPaint;
64597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private float mTextHeight, mWarningTextHeight;
65597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mIconTint = Color.WHITE;
66d866b8aa0341e960399c425b021b4a6aedfa5b9eJason Monk    private float mOldDarkIntensity = -1f;
67597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
68597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mHeight;
69597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mWidth;
70597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private String mWarningString;
71597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final int mCriticalLevel;
72597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mChargeColor;
73597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final float[] mBoltPoints;
74597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final Path mBoltPath = new Path();
75597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final float[] mPlusPoints;
76597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final Path mPlusPath = new Path();
77597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
78597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final RectF mFrame = new RectF();
79597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final RectF mButtonFrame = new RectF();
80597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final RectF mBoltFrame = new RectF();
81597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final RectF mPlusFrame = new RectF();
82597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
83597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final Path mShapePath = new Path();
84597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final Path mClipPath = new Path();
85597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private final Path mTextPath = new Path();
86597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
87597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mDarkModeBackgroundColor;
88597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mDarkModeFillColor;
89597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
90597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mLightModeBackgroundColor;
91597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int mLightModeFillColor;
92597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
93597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public BatteryMeterDrawableBase(Context context, int frameColor) {
94597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mContext = context;
95597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final Resources res = context.getResources();
96597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
97597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
98597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
99597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final int N = levels.length();
100597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mColors = new int[2 * N];
10158be7a675b7aa505255f0c91fee755f8290e8363Jason Monk        for (int i=0; i < N; i++) {
102597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            mColors[2 * i] = levels.getInt(i, 0);
10358be7a675b7aa505255f0c91fee755f8290e8363Jason Monk            if (colors.getType(i) == TypedValue.TYPE_ATTRIBUTE) {
1047c8564e6adb259ddf8c5626c8f59079e2e32cb79Jason Monk                mColors[2 * i + 1] = Utils.getColorAttr(context, colors.getThemeAttributeId(i, 0));
10558be7a675b7aa505255f0c91fee755f8290e8363Jason Monk            } else {
10658be7a675b7aa505255f0c91fee755f8290e8363Jason Monk                mColors[2 * i + 1] = colors.getColor(i, 0);
10758be7a675b7aa505255f0c91fee755f8290e8363Jason Monk            }
108597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
109597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        levels.recycle();
110597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        colors.recycle();
1116aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler
112597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
113597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mCriticalLevel = mContext.getResources().getInteger(
114597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
115597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mButtonHeightFraction = context.getResources().getFraction(
116597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                R.fraction.battery_button_height_fraction, 1, 1);
117597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mSubpixelSmoothingLeft = context.getResources().getFraction(
118597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                R.fraction.battery_subpixel_smoothing_left, 1, 1);
119597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mSubpixelSmoothingRight = context.getResources().getFraction(
120597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                R.fraction.battery_subpixel_smoothing_right, 1, 1);
121597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
122597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
123597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint.setColor(frameColor);
124597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint.setDither(true);
125597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint.setStrokeWidth(0);
126597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
127597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
128597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
129597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBatteryPaint.setDither(true);
130597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBatteryPaint.setStrokeWidth(0);
131597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
132597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
133597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
134597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
135597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mTextPaint.setTypeface(font);
136597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mTextPaint.setTextAlign(Paint.Align.CENTER);
137597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
138597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
139597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        font = Typeface.create("sans-serif", Typeface.BOLD);
140597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningTextPaint.setTypeface(font);
141597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
142597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (mColors.length > 1) {
143597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            mWarningTextPaint.setColor(mColors[1]);
144597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
145597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
146597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mChargeColor = Utils.getDefaultColor(mContext, R.color.batterymeter_charge_color);
147597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
148597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
149597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color));
1506aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        mBoltPoints = loadPoints(res, R.array.batterymeter_bolt_points);
151597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
152597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mPlusPaint = new Paint(mBoltPaint);
1536aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        mPlusPoints = loadPoints(res, R.array.batterymeter_plus_points);
154597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
155597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mDarkModeBackgroundColor =
156597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_background);
157597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mDarkModeFillColor =
158597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_fill);
159597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mLightModeBackgroundColor =
160597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                Utils.getDefaultColor(mContext, R.color.light_mode_icon_color_dual_tone_background);
161597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mLightModeFillColor =
162597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                Utils.getDefaultColor(mContext, R.color.light_mode_icon_color_dual_tone_fill);
163597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
164597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width);
165597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height);
166597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
167597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
168597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
169597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public int getIntrinsicHeight() {
170597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return mIntrinsicHeight;
171597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
172597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
173597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
174597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public int getIntrinsicWidth() {
175597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return mIntrinsicWidth;
176597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
177597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
1786aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    public void setShowPercent(boolean show) {
1796aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        mShowPercent = show;
180597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        postInvalidate();
181597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
182597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
1836aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    public void setPluggedIn(boolean val) {
1846aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        mPluggedIn = val;
1856aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        postInvalidate();
186597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
187597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
1886aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    public void setBatteryLevel(int val) {
1896aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        mLevel = val;
1906aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        postInvalidate();
1916aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    }
1926aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler
1936aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    public void setPowerSave(boolean val) {
1946aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        mPowerSaveEnabled = val;
1956aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        postInvalidate();
196597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
197597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
1986aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    // an approximation of View.postInvalidate()
1996aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    protected void postInvalidate() {
2006aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        unscheduleSelf(this::invalidateSelf);
2016aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        scheduleSelf(this::invalidateSelf, 0);
2026aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    }
2036aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler
2046aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler    private static float[] loadPoints(Resources res, int pointArrayRes) {
2056aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler        final int[] pts = res.getIntArray(pointArrayRes);
206597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        int maxX = 0, maxY = 0;
207597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        for (int i = 0; i < pts.length; i += 2) {
208597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            maxX = Math.max(maxX, pts[i]);
209597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            maxY = Math.max(maxY, pts[i + 1]);
210597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
211597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final float[] ptsF = new float[pts.length];
212597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        for (int i = 0; i < pts.length; i += 2) {
213597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            ptsF[i] = (float) pts[i] / maxX;
214597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            ptsF[i + 1] = (float) pts[i + 1] / maxY;
215597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
216597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return ptsF;
217597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
218597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
219597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
220597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public void setBounds(int left, int top, int right, int bottom) {
221597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        super.setBounds(left, top, right, bottom);
222597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mHeight = bottom - top;
223597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWidth = right - left;
224597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningTextPaint.setTextSize(mHeight * 0.75f);
225597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
226597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
227597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
228597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int getColorForLevel(int percent) {
229597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // If we are in power save mode, always use the normal color.
230597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (mPowerSaveEnabled) {
231597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            return mColors[mColors.length - 1];
232597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
233597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        int thresh, color = 0;
234597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        for (int i = 0; i < mColors.length; i += 2) {
235597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            thresh = mColors[i];
236597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            color = mColors[i + 1];
237597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (percent <= thresh) {
238597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
239597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // Respect tinting for "normal" level
240597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                if (i == mColors.length - 2) {
241597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    return mIconTint;
242597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                } else {
243597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    return color;
244597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                }
245597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
246597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
247597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return color;
248597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
249597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
250597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public void setDarkIntensity(float darkIntensity) {
251597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (darkIntensity == mOldDarkIntensity) {
252597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            return;
253597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
254597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        int backgroundColor = getBackgroundColor(darkIntensity);
255597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        int fillColor = getFillColor(darkIntensity);
256597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        setColors(fillColor, backgroundColor);
257597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mOldDarkIntensity = darkIntensity;
258597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
259597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
260597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public void setColors(int fillColor, int backgroundColor) {
261597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mIconTint = fillColor;
262597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint.setColor(backgroundColor);
263597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBoltPaint.setColor(fillColor);
264597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mChargeColor = fillColor;
265597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        invalidateSelf();
266597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
267597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
268597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int getBackgroundColor(float darkIntensity) {
269597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return getColorForDarkIntensity(
270597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
271597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
272597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
273597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int getFillColor(float darkIntensity) {
274597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return getColorForDarkIntensity(
275597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                darkIntensity, mLightModeFillColor, mDarkModeFillColor);
276597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
277597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
278597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
279597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
280597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
281597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
282597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
283597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public void draw(Canvas c) {
284597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final int level = mLevel;
285597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
286597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (level == -1) return;
287597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
288597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        float drawFrac = (float) level / 100f;
289597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final int height = mHeight;
290597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final int width = (int) (ASPECT_RATIO * mHeight);
291597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        int px = (mWidth - width) / 2;
292597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
293597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final int buttonHeight = (int) (height * mButtonHeightFraction);
294597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
295597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.set(0, 0, width, height);
296597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.offset(px, 0);
297597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
298597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // button-frame: area above the battery body
299597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mButtonFrame.set(
300597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mFrame.left + Math.round(width * 0.25f),
301597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mFrame.top,
302597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mFrame.right - Math.round(width * 0.25f),
303597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mFrame.top + buttonHeight);
304597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
305597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mButtonFrame.top += mSubpixelSmoothingLeft;
306597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mButtonFrame.left += mSubpixelSmoothingLeft;
307597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mButtonFrame.right -= mSubpixelSmoothingRight;
308597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
309597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // frame: battery body area
310597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.top += buttonHeight;
311597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.left += mSubpixelSmoothingLeft;
312597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.top += mSubpixelSmoothingLeft;
313597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.right -= mSubpixelSmoothingRight;
314597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.bottom -= mSubpixelSmoothingRight;
315597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
316597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // set the battery charging color
317597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level));
318597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
319597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (level >= FULL) {
320597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            drawFrac = 1f;
321597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        } else if (level <= mCriticalLevel) {
322597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            drawFrac = 0f;
323597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
324597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
325597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        final float levelTop = drawFrac == 1f ? mButtonFrame.top
326597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                : (mFrame.top + (mFrame.height() * (1f - drawFrac)));
327597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
328597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // define the battery shape
329597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.reset();
330597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
331597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
332597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mButtonFrame.right, mFrame.top);
333597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mFrame.right, mFrame.top);
334597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mFrame.right, mFrame.bottom);
335597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mFrame.left, mFrame.bottom);
336597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mFrame.left, mFrame.top);
337597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mButtonFrame.left, mFrame.top);
338597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
339597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
340597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (mPluggedIn) {
341597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            // define the bolt shape
342597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float bl = mFrame.left + mFrame.width() / 4f;
343597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float bt = mFrame.top + mFrame.height() / 6f;
344597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float br = mFrame.right - mFrame.width() / 4f;
345597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float bb = mFrame.bottom - mFrame.height() / 10f;
346597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (mBoltFrame.left != bl || mBoltFrame.top != bt
347597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
348597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mBoltFrame.set(bl, bt, br, bb);
349597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mBoltPath.reset();
350597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mBoltPath.moveTo(
351597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
352597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
353597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                for (int i = 2; i < mBoltPoints.length; i += 2) {
354597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    mBoltPath.lineTo(
355597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                            mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
356597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                            mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
357597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                }
358597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mBoltPath.lineTo(
359597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
360597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
361597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
362597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
363597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
364597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            boltPct = Math.min(Math.max(boltPct, 0), 1);
365597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (boltPct <= BOLT_LEVEL_THRESHOLD) {
366597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // draw the bolt if opaque
367597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                c.drawPath(mBoltPath, mBoltPaint);
368597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            } else {
369597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // otherwise cut the bolt out of the overall shape
370597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
371597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
372597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        } else if (mPowerSaveEnabled) {
373597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            // define the plus shape
374597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float pw = mFrame.width() * 2 / 3;
375597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float pl = mFrame.left + (mFrame.width() - pw) / 2;
376597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float pt = mFrame.top + (mFrame.height() - pw) / 2;
377597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float pr = mFrame.right - (mFrame.width() - pw) / 2;
378597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            final float pb = mFrame.bottom - (mFrame.height() - pw) / 2;
379597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (mPlusFrame.left != pl || mPlusFrame.top != pt
380597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    || mPlusFrame.right != pr || mPlusFrame.bottom != pb) {
381597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mPlusFrame.set(pl, pt, pr, pb);
382597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mPlusPath.reset();
383597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mPlusPath.moveTo(
384597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
385597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
386597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                for (int i = 2; i < mPlusPoints.length; i += 2) {
387597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    mPlusPath.lineTo(
388597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                            mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(),
389597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                            mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height());
390597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                }
391597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mPlusPath.lineTo(
392597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
393597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                        mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
394597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
395597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
396597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
397597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            boltPct = Math.min(Math.max(boltPct, 0), 1);
398597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (boltPct <= BOLT_LEVEL_THRESHOLD) {
399597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // draw the bolt if opaque
400597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                c.drawPath(mPlusPath, mPlusPaint);
401597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            } else {
402597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // otherwise cut the bolt out of the overall shape
403597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
404597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
405597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
406597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
407597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // compute percentage text
408597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        boolean pctOpaque = false;
409597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        float pctX = 0, pctY = 0;
410597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        String pctText = null;
411597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
412597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            mTextPaint.setColor(getColorForLevel(level));
413597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            mTextPaint.setTextSize(height *
414597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                    (SINGLE_DIGIT_PERCENT ? 0.75f
415597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                            : (mLevel == 100 ? 0.38f : 0.5f)));
416597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            mTextHeight = -mTextPaint.getFontMetrics().ascent;
417597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level / 10) : level);
418597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            pctX = mWidth * 0.5f;
419597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            pctY = (mHeight + mTextHeight) * 0.47f;
420597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            pctOpaque = levelTop > pctY;
421597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (!pctOpaque) {
422597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mTextPath.reset();
423597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath);
424597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // cut the percentage text out of the overall shape
425597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                mShapePath.op(mTextPath, Path.Op.DIFFERENCE);
426597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
427597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
428597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
429597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // draw the battery shape background
430597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        c.drawPath(mShapePath, mFramePaint);
431597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
432597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        // draw the battery shape, clipped to charging level
433597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFrame.top = levelTop;
434597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mClipPath.reset();
435597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mClipPath.addRect(mFrame, Path.Direction.CCW);
436597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mShapePath.op(mClipPath, Path.Op.INTERSECT);
437597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        c.drawPath(mShapePath, mBatteryPaint);
438597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
439597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        if (!mPluggedIn && !mPowerSaveEnabled) {
440597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            if (level <= mCriticalLevel) {
441597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // draw the warning text
442597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                final float x = mWidth * 0.5f;
443597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                final float y = (mHeight + mWarningTextHeight) * 0.48f;
444597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                c.drawText(mWarningString, x, y, mWarningTextPaint);
445597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            } else if (pctOpaque) {
446597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                // draw the percentage text
447597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei                c.drawText(pctText, pctX, pctY, mTextPaint);
448597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei            }
449597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        }
450597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
451597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
452597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    // Some stuff required by Drawable.
453597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
454597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public void setAlpha(int alpha) {
455597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
456597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
457597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
458597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public void setColorFilter(@Nullable ColorFilter colorFilter) {
459597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mFramePaint.setColorFilter(colorFilter);
460597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBatteryPaint.setColorFilter(colorFilter);
461597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mWarningTextPaint.setColorFilter(colorFilter);
462597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mBoltPaint.setColorFilter(colorFilter);
463597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        mPlusPaint.setColorFilter(colorFilter);
464597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
465597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei
466597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    @Override
467597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    public int getOpacity() {
468597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei        return 0;
469597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei    }
470597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei}
471