1abe1974a11364b577e94966ca87047d7889c8edfJason Monk/* 2abe1974a11364b577e94966ca87047d7889c8edfJason Monk * Copyright (C) 2015 The Android Open Source Project 3abe1974a11364b577e94966ca87047d7889c8edfJason Monk * 4abe1974a11364b577e94966ca87047d7889c8edfJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 5abe1974a11364b577e94966ca87047d7889c8edfJason Monk * you may not use this file except in compliance with the License. 6abe1974a11364b577e94966ca87047d7889c8edfJason Monk * You may obtain a copy of the License at 7abe1974a11364b577e94966ca87047d7889c8edfJason Monk * 8abe1974a11364b577e94966ca87047d7889c8edfJason Monk * http://www.apache.org/licenses/LICENSE-2.0 9abe1974a11364b577e94966ca87047d7889c8edfJason Monk * 10abe1974a11364b577e94966ca87047d7889c8edfJason Monk * Unless required by applicable law or agreed to in writing, software 11abe1974a11364b577e94966ca87047d7889c8edfJason Monk * distributed under the License is distributed on an "AS IS" BASIS, 12abe1974a11364b577e94966ca87047d7889c8edfJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13abe1974a11364b577e94966ca87047d7889c8edfJason Monk * See the License for the specific language governing permissions and 14abe1974a11364b577e94966ca87047d7889c8edfJason Monk * limitations under the License. 15abe1974a11364b577e94966ca87047d7889c8edfJason Monk */ 16abe1974a11364b577e94966ca87047d7889c8edfJason Monk 17abe1974a11364b577e94966ca87047d7889c8edfJason Monkpackage com.android.systemui; 18abe1974a11364b577e94966ca87047d7889c8edfJason Monk 19abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.animation.ArgbEvaluator; 20abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.annotation.Nullable; 21abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.content.Context; 22abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.content.res.Resources; 23abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.content.res.TypedArray; 24abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.database.ContentObserver; 25c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.Canvas; 26c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.Color; 27c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.ColorFilter; 28c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.Paint; 29c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.Path; 30c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.RectF; 31c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport android.graphics.Typeface; 32abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.graphics.drawable.Drawable; 33abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.net.Uri; 34abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.os.Bundle; 35abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.os.Handler; 36abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport android.provider.Settings; 37c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 38abe1974a11364b577e94966ca87047d7889c8edfJason Monkimport com.android.systemui.statusbar.policy.BatteryController; 39abe1974a11364b577e94966ca87047d7889c8edfJason Monk 4098d7c7a84d007d3de0c3394d8a93253a313eda27Jason Monkpublic class BatteryMeterDrawable extends Drawable implements 41abe1974a11364b577e94966ca87047d7889c8edfJason Monk BatteryController.BatteryStateChangeCallback { 42abe1974a11364b577e94966ca87047d7889c8edfJason Monk 43abe1974a11364b577e94966ca87047d7889c8edfJason Monk private static final float ASPECT_RATIO = 9.5f / 14.5f; 44abe1974a11364b577e94966ca87047d7889c8edfJason Monk public static final String TAG = BatteryMeterDrawable.class.getSimpleName(); 45abe1974a11364b577e94966ca87047d7889c8edfJason Monk public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; 46abe1974a11364b577e94966ca87047d7889c8edfJason Monk 47abe1974a11364b577e94966ca87047d7889c8edfJason Monk private static final boolean SINGLE_DIGIT_PERCENT = false; 48abe1974a11364b577e94966ca87047d7889c8edfJason Monk 49abe1974a11364b577e94966ca87047d7889c8edfJason Monk private static final int FULL = 96; 50abe1974a11364b577e94966ca87047d7889c8edfJason Monk 51abe1974a11364b577e94966ca87047d7889c8edfJason Monk private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction 52abe1974a11364b577e94966ca87047d7889c8edfJason Monk 53abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final int[] mColors; 54eae7c318864bcfd814c8be697315f829952ccc69Jason Monk private final int mIntrinsicWidth; 55eae7c318864bcfd814c8be697315f829952ccc69Jason Monk private final int mIntrinsicHeight; 56abe1974a11364b577e94966ca87047d7889c8edfJason Monk 57abe1974a11364b577e94966ca87047d7889c8edfJason Monk private boolean mShowPercent; 58abe1974a11364b577e94966ca87047d7889c8edfJason Monk private float mButtonHeightFraction; 59abe1974a11364b577e94966ca87047d7889c8edfJason Monk private float mSubpixelSmoothingLeft; 60abe1974a11364b577e94966ca87047d7889c8edfJason Monk private float mSubpixelSmoothingRight; 61c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint, 62c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPaint; 63abe1974a11364b577e94966ca87047d7889c8edfJason Monk private float mTextHeight, mWarningTextHeight; 64abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mIconTint = Color.WHITE; 6586905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi private float mOldDarkIntensity = 0f; 66abe1974a11364b577e94966ca87047d7889c8edfJason Monk 67abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mHeight; 68abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mWidth; 69abe1974a11364b577e94966ca87047d7889c8edfJason Monk private String mWarningString; 70abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final int mCriticalLevel; 71abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mChargeColor; 72abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final float[] mBoltPoints; 73abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final Path mBoltPath = new Path(); 74c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk private final float[] mPlusPoints; 75c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk private final Path mPlusPath = new Path(); 76abe1974a11364b577e94966ca87047d7889c8edfJason Monk 77abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final RectF mFrame = new RectF(); 78abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final RectF mButtonFrame = new RectF(); 79abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final RectF mBoltFrame = new RectF(); 80c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk private final RectF mPlusFrame = new RectF(); 81abe1974a11364b577e94966ca87047d7889c8edfJason Monk 82abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final Path mShapePath = new Path(); 83abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final Path mClipPath = new Path(); 84abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final Path mTextPath = new Path(); 85abe1974a11364b577e94966ca87047d7889c8edfJason Monk 86abe1974a11364b577e94966ca87047d7889c8edfJason Monk private BatteryController mBatteryController; 87abe1974a11364b577e94966ca87047d7889c8edfJason Monk private boolean mPowerSaveEnabled; 88abe1974a11364b577e94966ca87047d7889c8edfJason Monk 89abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mDarkModeBackgroundColor; 90abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mDarkModeFillColor; 91abe1974a11364b577e94966ca87047d7889c8edfJason Monk 92abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mLightModeBackgroundColor; 93abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mLightModeFillColor; 94abe1974a11364b577e94966ca87047d7889c8edfJason Monk 95abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final SettingObserver mSettingObserver = new SettingObserver(); 96abe1974a11364b577e94966ca87047d7889c8edfJason Monk 97abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final Context mContext; 98abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final Handler mHandler; 99abe1974a11364b577e94966ca87047d7889c8edfJason Monk 100abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int mLevel = -1; 101abe1974a11364b577e94966ca87047d7889c8edfJason Monk private boolean mPluggedIn; 102abe1974a11364b577e94966ca87047d7889c8edfJason Monk private boolean mListening; 103abe1974a11364b577e94966ca87047d7889c8edfJason Monk 104abe1974a11364b577e94966ca87047d7889c8edfJason Monk public BatteryMeterDrawable(Context context, Handler handler, int frameColor) { 105abe1974a11364b577e94966ca87047d7889c8edfJason Monk mContext = context; 106abe1974a11364b577e94966ca87047d7889c8edfJason Monk mHandler = handler; 107abe1974a11364b577e94966ca87047d7889c8edfJason Monk final Resources res = context.getResources(); 108abe1974a11364b577e94966ca87047d7889c8edfJason Monk TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); 109abe1974a11364b577e94966ca87047d7889c8edfJason Monk TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); 110abe1974a11364b577e94966ca87047d7889c8edfJason Monk 111abe1974a11364b577e94966ca87047d7889c8edfJason Monk final int N = levels.length(); 112abe1974a11364b577e94966ca87047d7889c8edfJason Monk mColors = new int[2*N]; 113abe1974a11364b577e94966ca87047d7889c8edfJason Monk for (int i=0; i<N; i++) { 114abe1974a11364b577e94966ca87047d7889c8edfJason Monk mColors[2*i] = levels.getInt(i, 0); 115abe1974a11364b577e94966ca87047d7889c8edfJason Monk mColors[2*i+1] = colors.getColor(i, 0); 116abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 117abe1974a11364b577e94966ca87047d7889c8edfJason Monk levels.recycle(); 118abe1974a11364b577e94966ca87047d7889c8edfJason Monk colors.recycle(); 119abe1974a11364b577e94966ca87047d7889c8edfJason Monk updateShowPercent(); 120abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); 121abe1974a11364b577e94966ca87047d7889c8edfJason Monk mCriticalLevel = mContext.getResources().getInteger( 122abe1974a11364b577e94966ca87047d7889c8edfJason Monk com.android.internal.R.integer.config_criticalBatteryWarningLevel); 123abe1974a11364b577e94966ca87047d7889c8edfJason Monk mButtonHeightFraction = context.getResources().getFraction( 124abe1974a11364b577e94966ca87047d7889c8edfJason Monk R.fraction.battery_button_height_fraction, 1, 1); 125abe1974a11364b577e94966ca87047d7889c8edfJason Monk mSubpixelSmoothingLeft = context.getResources().getFraction( 126abe1974a11364b577e94966ca87047d7889c8edfJason Monk R.fraction.battery_subpixel_smoothing_left, 1, 1); 127abe1974a11364b577e94966ca87047d7889c8edfJason Monk mSubpixelSmoothingRight = context.getResources().getFraction( 128abe1974a11364b577e94966ca87047d7889c8edfJason Monk R.fraction.battery_subpixel_smoothing_right, 1, 1); 129abe1974a11364b577e94966ca87047d7889c8edfJason Monk 130abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 131abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFramePaint.setColor(frameColor); 132abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFramePaint.setDither(true); 133abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFramePaint.setStrokeWidth(0); 134abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); 135abe1974a11364b577e94966ca87047d7889c8edfJason Monk 136abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 137abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryPaint.setDither(true); 138abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryPaint.setStrokeWidth(0); 139abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); 140abe1974a11364b577e94966ca87047d7889c8edfJason Monk 141abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 142abe1974a11364b577e94966ca87047d7889c8edfJason Monk Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); 143abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPaint.setTypeface(font); 144abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPaint.setTextAlign(Paint.Align.CENTER); 145abe1974a11364b577e94966ca87047d7889c8edfJason Monk 146abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 147abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningTextPaint.setColor(mColors[1]); 148abe1974a11364b577e94966ca87047d7889c8edfJason Monk font = Typeface.create("sans-serif", Typeface.BOLD); 149abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningTextPaint.setTypeface(font); 150abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningTextPaint.setTextAlign(Paint.Align.CENTER); 151abe1974a11364b577e94966ca87047d7889c8edfJason Monk 152abe1974a11364b577e94966ca87047d7889c8edfJason Monk mChargeColor = context.getColor(R.color.batterymeter_charge_color); 153abe1974a11364b577e94966ca87047d7889c8edfJason Monk 154abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 155abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color)); 156abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPoints = loadBoltPoints(res); 157abe1974a11364b577e94966ca87047d7889c8edfJason Monk 158c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPaint = new Paint(mBoltPaint); 159c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPoints = loadPlusPoints(res); 160c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk 161abe1974a11364b577e94966ca87047d7889c8edfJason Monk mDarkModeBackgroundColor = 162abe1974a11364b577e94966ca87047d7889c8edfJason Monk context.getColor(R.color.dark_mode_icon_color_dual_tone_background); 163abe1974a11364b577e94966ca87047d7889c8edfJason Monk mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill); 164abe1974a11364b577e94966ca87047d7889c8edfJason Monk mLightModeBackgroundColor = 165abe1974a11364b577e94966ca87047d7889c8edfJason Monk context.getColor(R.color.light_mode_icon_color_dual_tone_background); 166abe1974a11364b577e94966ca87047d7889c8edfJason Monk mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill); 167eae7c318864bcfd814c8be697315f829952ccc69Jason Monk 168eae7c318864bcfd814c8be697315f829952ccc69Jason Monk mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width); 169eae7c318864bcfd814c8be697315f829952ccc69Jason Monk mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height); 170eae7c318864bcfd814c8be697315f829952ccc69Jason Monk } 171eae7c318864bcfd814c8be697315f829952ccc69Jason Monk 172eae7c318864bcfd814c8be697315f829952ccc69Jason Monk @Override 173eae7c318864bcfd814c8be697315f829952ccc69Jason Monk public int getIntrinsicHeight() { 174eae7c318864bcfd814c8be697315f829952ccc69Jason Monk return mIntrinsicHeight; 175eae7c318864bcfd814c8be697315f829952ccc69Jason Monk } 176eae7c318864bcfd814c8be697315f829952ccc69Jason Monk 177eae7c318864bcfd814c8be697315f829952ccc69Jason Monk @Override 178eae7c318864bcfd814c8be697315f829952ccc69Jason Monk public int getIntrinsicWidth() { 179eae7c318864bcfd814c8be697315f829952ccc69Jason Monk return mIntrinsicWidth; 180abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 181abe1974a11364b577e94966ca87047d7889c8edfJason Monk 182abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void startListening() { 183abe1974a11364b577e94966ca87047d7889c8edfJason Monk mListening = true; 184abe1974a11364b577e94966ca87047d7889c8edfJason Monk mContext.getContentResolver().registerContentObserver( 185abe1974a11364b577e94966ca87047d7889c8edfJason Monk Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); 1865c404c8dc6c2a603030e840216fc3c6984009cd3Jason Monk updateShowPercent(); 187abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryController.addStateChangedCallback(this); 188abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 189abe1974a11364b577e94966ca87047d7889c8edfJason Monk 190abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void stopListening() { 191abe1974a11364b577e94966ca87047d7889c8edfJason Monk mListening = false; 192abe1974a11364b577e94966ca87047d7889c8edfJason Monk mContext.getContentResolver().unregisterContentObserver(mSettingObserver); 193abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryController.removeStateChangedCallback(this); 194abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 195abe1974a11364b577e94966ca87047d7889c8edfJason Monk 1965c404c8dc6c2a603030e840216fc3c6984009cd3Jason Monk public void disableShowPercent() { 1975c404c8dc6c2a603030e840216fc3c6984009cd3Jason Monk mShowPercent = false; 1985c404c8dc6c2a603030e840216fc3c6984009cd3Jason Monk postInvalidate(); 1995c404c8dc6c2a603030e840216fc3c6984009cd3Jason Monk } 2005c404c8dc6c2a603030e840216fc3c6984009cd3Jason Monk 201abe1974a11364b577e94966ca87047d7889c8edfJason Monk private void postInvalidate() { 202abe1974a11364b577e94966ca87047d7889c8edfJason Monk mHandler.post(new Runnable() { 203abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 204abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void run() { 205abe1974a11364b577e94966ca87047d7889c8edfJason Monk invalidateSelf(); 206abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 207abe1974a11364b577e94966ca87047d7889c8edfJason Monk }); 208abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 209abe1974a11364b577e94966ca87047d7889c8edfJason Monk 210abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void setBatteryController(BatteryController batteryController) { 211abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryController = batteryController; 212abe1974a11364b577e94966ca87047d7889c8edfJason Monk mPowerSaveEnabled = mBatteryController.isPowerSave(); 213abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 214abe1974a11364b577e94966ca87047d7889c8edfJason Monk 215abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 216abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 217abe1974a11364b577e94966ca87047d7889c8edfJason Monk mLevel = level; 218abe1974a11364b577e94966ca87047d7889c8edfJason Monk mPluggedIn = pluggedIn; 219abe1974a11364b577e94966ca87047d7889c8edfJason Monk 220abe1974a11364b577e94966ca87047d7889c8edfJason Monk postInvalidate(); 221abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 222abe1974a11364b577e94966ca87047d7889c8edfJason Monk 223abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 224c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk public void onPowerSaveChanged(boolean isPowerSave) { 225c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPowerSaveEnabled = isPowerSave; 226abe1974a11364b577e94966ca87047d7889c8edfJason Monk invalidateSelf(); 227abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 228abe1974a11364b577e94966ca87047d7889c8edfJason Monk 229abe1974a11364b577e94966ca87047d7889c8edfJason Monk private static float[] loadBoltPoints(Resources res) { 230abe1974a11364b577e94966ca87047d7889c8edfJason Monk final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); 231abe1974a11364b577e94966ca87047d7889c8edfJason Monk int maxX = 0, maxY = 0; 232abe1974a11364b577e94966ca87047d7889c8edfJason Monk for (int i = 0; i < pts.length; i += 2) { 233abe1974a11364b577e94966ca87047d7889c8edfJason Monk maxX = Math.max(maxX, pts[i]); 234abe1974a11364b577e94966ca87047d7889c8edfJason Monk maxY = Math.max(maxY, pts[i + 1]); 235abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 236abe1974a11364b577e94966ca87047d7889c8edfJason Monk final float[] ptsF = new float[pts.length]; 237abe1974a11364b577e94966ca87047d7889c8edfJason Monk for (int i = 0; i < pts.length; i += 2) { 238abe1974a11364b577e94966ca87047d7889c8edfJason Monk ptsF[i] = (float)pts[i] / maxX; 239abe1974a11364b577e94966ca87047d7889c8edfJason Monk ptsF[i + 1] = (float)pts[i + 1] / maxY; 240abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 241abe1974a11364b577e94966ca87047d7889c8edfJason Monk return ptsF; 242abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 243abe1974a11364b577e94966ca87047d7889c8edfJason Monk 244c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk private static float[] loadPlusPoints(Resources res) { 245c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final int[] pts = res.getIntArray(R.array.batterymeter_plus_points); 246c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk int maxX = 0, maxY = 0; 247c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk for (int i = 0; i < pts.length; i += 2) { 248c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk maxX = Math.max(maxX, pts[i]); 249c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk maxY = Math.max(maxY, pts[i + 1]); 250c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } 251c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float[] ptsF = new float[pts.length]; 252c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk for (int i = 0; i < pts.length; i += 2) { 253c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk ptsF[i] = (float)pts[i] / maxX; 254c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk ptsF[i + 1] = (float)pts[i + 1] / maxY; 255c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } 256c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk return ptsF; 257c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } 258c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk 259abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 260abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void setBounds(int left, int top, int right, int bottom) { 261abe1974a11364b577e94966ca87047d7889c8edfJason Monk super.setBounds(left, top, right, bottom); 262abe1974a11364b577e94966ca87047d7889c8edfJason Monk mHeight = bottom - top; 263abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWidth = right - left; 264abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningTextPaint.setTextSize(mHeight * 0.75f); 265abe1974a11364b577e94966ca87047d7889c8edfJason Monk mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; 266abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 267abe1974a11364b577e94966ca87047d7889c8edfJason Monk 268abe1974a11364b577e94966ca87047d7889c8edfJason Monk private void updateShowPercent() { 269abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShowPercent = 0 != Settings.System.getInt(mContext.getContentResolver(), 270abe1974a11364b577e94966ca87047d7889c8edfJason Monk SHOW_PERCENT_SETTING, 0); 271abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 272abe1974a11364b577e94966ca87047d7889c8edfJason Monk 273abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int getColorForLevel(int percent) { 274abe1974a11364b577e94966ca87047d7889c8edfJason Monk 275abe1974a11364b577e94966ca87047d7889c8edfJason Monk // If we are in power save mode, always use the normal color. 276abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (mPowerSaveEnabled) { 277abe1974a11364b577e94966ca87047d7889c8edfJason Monk return mColors[mColors.length-1]; 278abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 279abe1974a11364b577e94966ca87047d7889c8edfJason Monk int thresh, color = 0; 280abe1974a11364b577e94966ca87047d7889c8edfJason Monk for (int i=0; i<mColors.length; i+=2) { 281abe1974a11364b577e94966ca87047d7889c8edfJason Monk thresh = mColors[i]; 282abe1974a11364b577e94966ca87047d7889c8edfJason Monk color = mColors[i+1]; 283abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (percent <= thresh) { 284abe1974a11364b577e94966ca87047d7889c8edfJason Monk 285abe1974a11364b577e94966ca87047d7889c8edfJason Monk // Respect tinting for "normal" level 286abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (i == mColors.length-2) { 287abe1974a11364b577e94966ca87047d7889c8edfJason Monk return mIconTint; 288abe1974a11364b577e94966ca87047d7889c8edfJason Monk } else { 289abe1974a11364b577e94966ca87047d7889c8edfJason Monk return color; 290abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 291abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 292abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 293abe1974a11364b577e94966ca87047d7889c8edfJason Monk return color; 294abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 295abe1974a11364b577e94966ca87047d7889c8edfJason Monk 296abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void setDarkIntensity(float darkIntensity) { 29786905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi if (darkIntensity == mOldDarkIntensity) { 29886905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi return; 29986905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi } 300abe1974a11364b577e94966ca87047d7889c8edfJason Monk int backgroundColor = getBackgroundColor(darkIntensity); 301abe1974a11364b577e94966ca87047d7889c8edfJason Monk int fillColor = getFillColor(darkIntensity); 302abe1974a11364b577e94966ca87047d7889c8edfJason Monk mIconTint = fillColor; 303abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFramePaint.setColor(backgroundColor); 304abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPaint.setColor(fillColor); 305abe1974a11364b577e94966ca87047d7889c8edfJason Monk mChargeColor = fillColor; 306abe1974a11364b577e94966ca87047d7889c8edfJason Monk invalidateSelf(); 30786905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi mOldDarkIntensity = darkIntensity; 308abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 309abe1974a11364b577e94966ca87047d7889c8edfJason Monk 310abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int getBackgroundColor(float darkIntensity) { 311abe1974a11364b577e94966ca87047d7889c8edfJason Monk return getColorForDarkIntensity( 312abe1974a11364b577e94966ca87047d7889c8edfJason Monk darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor); 313abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 314abe1974a11364b577e94966ca87047d7889c8edfJason Monk 315abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int getFillColor(float darkIntensity) { 316abe1974a11364b577e94966ca87047d7889c8edfJason Monk return getColorForDarkIntensity( 317abe1974a11364b577e94966ca87047d7889c8edfJason Monk darkIntensity, mLightModeFillColor, mDarkModeFillColor); 318abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 319abe1974a11364b577e94966ca87047d7889c8edfJason Monk 320abe1974a11364b577e94966ca87047d7889c8edfJason Monk private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) { 321abe1974a11364b577e94966ca87047d7889c8edfJason Monk return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor); 322abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 323abe1974a11364b577e94966ca87047d7889c8edfJason Monk 324abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 325abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void draw(Canvas c) { 326abe1974a11364b577e94966ca87047d7889c8edfJason Monk final int level = mLevel; 327abe1974a11364b577e94966ca87047d7889c8edfJason Monk 328abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (level == -1) return; 329abe1974a11364b577e94966ca87047d7889c8edfJason Monk 330abe1974a11364b577e94966ca87047d7889c8edfJason Monk float drawFrac = (float) level / 100f; 331abe1974a11364b577e94966ca87047d7889c8edfJason Monk final int height = mHeight; 332abe1974a11364b577e94966ca87047d7889c8edfJason Monk final int width = (int) (ASPECT_RATIO * mHeight); 333abe1974a11364b577e94966ca87047d7889c8edfJason Monk int px = (mWidth - width) / 2; 334abe1974a11364b577e94966ca87047d7889c8edfJason Monk 335abe1974a11364b577e94966ca87047d7889c8edfJason Monk final int buttonHeight = (int) (height * mButtonHeightFraction); 336abe1974a11364b577e94966ca87047d7889c8edfJason Monk 337abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.set(0, 0, width, height); 338abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.offset(px, 0); 339abe1974a11364b577e94966ca87047d7889c8edfJason Monk 340abe1974a11364b577e94966ca87047d7889c8edfJason Monk // button-frame: area above the battery body 341abe1974a11364b577e94966ca87047d7889c8edfJason Monk mButtonFrame.set( 342abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.left + Math.round(width * 0.25f), 343abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.top, 344abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.right - Math.round(width * 0.25f), 345abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.top + buttonHeight); 346abe1974a11364b577e94966ca87047d7889c8edfJason Monk 347abe1974a11364b577e94966ca87047d7889c8edfJason Monk mButtonFrame.top += mSubpixelSmoothingLeft; 348abe1974a11364b577e94966ca87047d7889c8edfJason Monk mButtonFrame.left += mSubpixelSmoothingLeft; 349abe1974a11364b577e94966ca87047d7889c8edfJason Monk mButtonFrame.right -= mSubpixelSmoothingRight; 350abe1974a11364b577e94966ca87047d7889c8edfJason Monk 351abe1974a11364b577e94966ca87047d7889c8edfJason Monk // frame: battery body area 352abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.top += buttonHeight; 353abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.left += mSubpixelSmoothingLeft; 354abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.top += mSubpixelSmoothingLeft; 355abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.right -= mSubpixelSmoothingRight; 356abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.bottom -= mSubpixelSmoothingRight; 357abe1974a11364b577e94966ca87047d7889c8edfJason Monk 358abe1974a11364b577e94966ca87047d7889c8edfJason Monk // set the battery charging color 359abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level)); 360abe1974a11364b577e94966ca87047d7889c8edfJason Monk 361abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (level >= FULL) { 362abe1974a11364b577e94966ca87047d7889c8edfJason Monk drawFrac = 1f; 363abe1974a11364b577e94966ca87047d7889c8edfJason Monk } else if (level <= mCriticalLevel) { 364abe1974a11364b577e94966ca87047d7889c8edfJason Monk drawFrac = 0f; 365abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 366abe1974a11364b577e94966ca87047d7889c8edfJason Monk 367abe1974a11364b577e94966ca87047d7889c8edfJason Monk final float levelTop = drawFrac == 1f ? mButtonFrame.top 368abe1974a11364b577e94966ca87047d7889c8edfJason Monk : (mFrame.top + (mFrame.height() * (1f - drawFrac))); 369abe1974a11364b577e94966ca87047d7889c8edfJason Monk 370abe1974a11364b577e94966ca87047d7889c8edfJason Monk // define the battery shape 371abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.reset(); 372abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); 373abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); 374abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mButtonFrame.right, mFrame.top); 375abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mFrame.right, mFrame.top); 376abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mFrame.right, mFrame.bottom); 377abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mFrame.left, mFrame.bottom); 378abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mFrame.left, mFrame.top); 379abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mButtonFrame.left, mFrame.top); 380abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); 381abe1974a11364b577e94966ca87047d7889c8edfJason Monk 382abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (mPluggedIn) { 383abe1974a11364b577e94966ca87047d7889c8edfJason Monk // define the bolt shape 384c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float bl = mFrame.left + mFrame.width() / 4f; 385abe1974a11364b577e94966ca87047d7889c8edfJason Monk final float bt = mFrame.top + mFrame.height() / 6f; 386c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float br = mFrame.right - mFrame.width() / 4f; 387abe1974a11364b577e94966ca87047d7889c8edfJason Monk final float bb = mFrame.bottom - mFrame.height() / 10f; 388abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (mBoltFrame.left != bl || mBoltFrame.top != bt 389abe1974a11364b577e94966ca87047d7889c8edfJason Monk || mBoltFrame.right != br || mBoltFrame.bottom != bb) { 390abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.set(bl, bt, br, bb); 391abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPath.reset(); 392abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPath.moveTo( 393abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 394abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 395abe1974a11364b577e94966ca87047d7889c8edfJason Monk for (int i = 2; i < mBoltPoints.length; i += 2) { 396abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPath.lineTo( 397abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), 398abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); 399abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 400abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltPath.lineTo( 401abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 402abe1974a11364b577e94966ca87047d7889c8edfJason Monk mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 403abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 404abe1974a11364b577e94966ca87047d7889c8edfJason Monk 405abe1974a11364b577e94966ca87047d7889c8edfJason Monk float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); 406abe1974a11364b577e94966ca87047d7889c8edfJason Monk boltPct = Math.min(Math.max(boltPct, 0), 1); 407abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (boltPct <= BOLT_LEVEL_THRESHOLD) { 408abe1974a11364b577e94966ca87047d7889c8edfJason Monk // draw the bolt if opaque 409abe1974a11364b577e94966ca87047d7889c8edfJason Monk c.drawPath(mBoltPath, mBoltPaint); 410abe1974a11364b577e94966ca87047d7889c8edfJason Monk } else { 411abe1974a11364b577e94966ca87047d7889c8edfJason Monk // otherwise cut the bolt out of the overall shape 412abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); 413abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 414c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } else if (mPowerSaveEnabled) { 415c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk // define the plus shape 416c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float pw = mFrame.width() * 2 / 3; 417c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float pl = mFrame.left + (mFrame.width() - pw) / 2; 418c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float pt = mFrame.top + (mFrame.height() - pw) / 2; 419c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float pr = mFrame.right - (mFrame.width() - pw) / 2; 420c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk final float pb = mFrame.bottom - (mFrame.height() - pw) / 2; 421c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk if (mPlusFrame.left != pl || mPlusFrame.top != pt 422c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk || mPlusFrame.right != pr || mPlusFrame.bottom != pb) { 423c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.set(pl, pt, pr, pb); 424c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPath.reset(); 425c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPath.moveTo( 426c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), 427c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); 428c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk for (int i = 2; i < mPlusPoints.length; i += 2) { 429c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPath.lineTo( 430c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(), 431c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height()); 432c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } 433c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusPath.lineTo( 434c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), 435c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); 436c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } 437c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk 438c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top); 439c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk boltPct = Math.min(Math.max(boltPct, 0), 1); 440c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk if (boltPct <= BOLT_LEVEL_THRESHOLD) { 441c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk // draw the bolt if opaque 442c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk c.drawPath(mPlusPath, mPlusPaint); 443c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } else { 444c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk // otherwise cut the bolt out of the overall shape 445c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk mShapePath.op(mPlusPath, Path.Op.DIFFERENCE); 446c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk } 447abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 448abe1974a11364b577e94966ca87047d7889c8edfJason Monk 449abe1974a11364b577e94966ca87047d7889c8edfJason Monk // compute percentage text 450abe1974a11364b577e94966ca87047d7889c8edfJason Monk boolean pctOpaque = false; 451abe1974a11364b577e94966ca87047d7889c8edfJason Monk float pctX = 0, pctY = 0; 452abe1974a11364b577e94966ca87047d7889c8edfJason Monk String pctText = null; 45349573e9c89a279397288d5139deadb5ec27c9821Jason Monk if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) { 454abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPaint.setColor(getColorForLevel(level)); 455abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPaint.setTextSize(height * 456abe1974a11364b577e94966ca87047d7889c8edfJason Monk (SINGLE_DIGIT_PERCENT ? 0.75f 457abe1974a11364b577e94966ca87047d7889c8edfJason Monk : (mLevel == 100 ? 0.38f : 0.5f))); 458abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextHeight = -mTextPaint.getFontMetrics().ascent; 459abe1974a11364b577e94966ca87047d7889c8edfJason Monk pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); 460abe1974a11364b577e94966ca87047d7889c8edfJason Monk pctX = mWidth * 0.5f; 461abe1974a11364b577e94966ca87047d7889c8edfJason Monk pctY = (mHeight + mTextHeight) * 0.47f; 462abe1974a11364b577e94966ca87047d7889c8edfJason Monk pctOpaque = levelTop > pctY; 463abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (!pctOpaque) { 464abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPath.reset(); 465abe1974a11364b577e94966ca87047d7889c8edfJason Monk mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); 466abe1974a11364b577e94966ca87047d7889c8edfJason Monk // cut the percentage text out of the overall shape 467abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.op(mTextPath, Path.Op.DIFFERENCE); 468abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 469abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 470abe1974a11364b577e94966ca87047d7889c8edfJason Monk 471abe1974a11364b577e94966ca87047d7889c8edfJason Monk // draw the battery shape background 472abe1974a11364b577e94966ca87047d7889c8edfJason Monk c.drawPath(mShapePath, mFramePaint); 473abe1974a11364b577e94966ca87047d7889c8edfJason Monk 474abe1974a11364b577e94966ca87047d7889c8edfJason Monk // draw the battery shape, clipped to charging level 475abe1974a11364b577e94966ca87047d7889c8edfJason Monk mFrame.top = levelTop; 476abe1974a11364b577e94966ca87047d7889c8edfJason Monk mClipPath.reset(); 477abe1974a11364b577e94966ca87047d7889c8edfJason Monk mClipPath.addRect(mFrame, Path.Direction.CCW); 478abe1974a11364b577e94966ca87047d7889c8edfJason Monk mShapePath.op(mClipPath, Path.Op.INTERSECT); 479abe1974a11364b577e94966ca87047d7889c8edfJason Monk c.drawPath(mShapePath, mBatteryPaint); 480abe1974a11364b577e94966ca87047d7889c8edfJason Monk 48149573e9c89a279397288d5139deadb5ec27c9821Jason Monk if (!mPluggedIn && !mPowerSaveEnabled) { 482abe1974a11364b577e94966ca87047d7889c8edfJason Monk if (level <= mCriticalLevel) { 483abe1974a11364b577e94966ca87047d7889c8edfJason Monk // draw the warning text 484abe1974a11364b577e94966ca87047d7889c8edfJason Monk final float x = mWidth * 0.5f; 485abe1974a11364b577e94966ca87047d7889c8edfJason Monk final float y = (mHeight + mWarningTextHeight) * 0.48f; 486abe1974a11364b577e94966ca87047d7889c8edfJason Monk c.drawText(mWarningString, x, y, mWarningTextPaint); 487abe1974a11364b577e94966ca87047d7889c8edfJason Monk } else if (pctOpaque) { 488abe1974a11364b577e94966ca87047d7889c8edfJason Monk // draw the percentage text 489abe1974a11364b577e94966ca87047d7889c8edfJason Monk c.drawText(pctText, pctX, pctY, mTextPaint); 490abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 491abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 492abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 493abe1974a11364b577e94966ca87047d7889c8edfJason Monk 494abe1974a11364b577e94966ca87047d7889c8edfJason Monk // Some stuff required by Drawable. 495abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 496abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void setAlpha(int alpha) { 497abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 498abe1974a11364b577e94966ca87047d7889c8edfJason Monk 499abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 500abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void setColorFilter(@Nullable ColorFilter colorFilter) { 501abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 502abe1974a11364b577e94966ca87047d7889c8edfJason Monk 503abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 504abe1974a11364b577e94966ca87047d7889c8edfJason Monk public int getOpacity() { 505abe1974a11364b577e94966ca87047d7889c8edfJason Monk return 0; 506abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 507abe1974a11364b577e94966ca87047d7889c8edfJason Monk 508abe1974a11364b577e94966ca87047d7889c8edfJason Monk private final class SettingObserver extends ContentObserver { 509abe1974a11364b577e94966ca87047d7889c8edfJason Monk public SettingObserver() { 510abe1974a11364b577e94966ca87047d7889c8edfJason Monk super(new Handler()); 511abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 512abe1974a11364b577e94966ca87047d7889c8edfJason Monk 513abe1974a11364b577e94966ca87047d7889c8edfJason Monk @Override 514abe1974a11364b577e94966ca87047d7889c8edfJason Monk public void onChange(boolean selfChange, Uri uri) { 515abe1974a11364b577e94966ca87047d7889c8edfJason Monk super.onChange(selfChange, uri); 516abe1974a11364b577e94966ca87047d7889c8edfJason Monk updateShowPercent(); 517abe1974a11364b577e94966ca87047d7889c8edfJason Monk postInvalidate(); 518abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 519abe1974a11364b577e94966ca87047d7889c8edfJason Monk } 520abe1974a11364b577e94966ca87047d7889c8edfJason Monk 521abe1974a11364b577e94966ca87047d7889c8edfJason Monk} 522