1dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler/* 2dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * Copyright (C) 2013 The Android Open Source Project 3dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * 4dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 5dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * you may not use this file except in compliance with the License. 6dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * You may obtain a copy of the License at 7dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * 8dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 9dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * 10dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * Unless required by applicable law or agreed to in writing, software 11dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 12dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * See the License for the specific language governing permissions and 14dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * limitations under the License. 15dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler */ 16dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 17dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerpackage com.android.systemui; 18dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 195443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggiimport android.animation.ArgbEvaluator; 20dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.BroadcastReceiver; 21dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.Context; 22dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.Intent; 23dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.IntentFilter; 24dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.res.Resources; 25dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.res.TypedArray; 26f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlockimport android.database.ContentObserver; 27dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Canvas; 28dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggiimport android.graphics.Color; 29dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Paint; 30fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlockimport android.graphics.Path; 31dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.RectF; 32dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Typeface; 33f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlockimport android.net.Uri; 34dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.os.BatteryManager; 353c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlockimport android.os.Bundle; 36f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlockimport android.os.Handler; 37dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.provider.Settings; 38dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.util.AttributeSet; 39dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.view.View; 40dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 41708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggiimport com.android.systemui.statusbar.policy.BatteryController; 42708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi 43708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggipublic class BatteryMeterView extends View implements DemoMode, 44708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi BatteryController.BatteryStateChangeCallback { 45dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final String TAG = BatteryMeterView.class.getSimpleName(); 46dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; 47f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; 48dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 494b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private static final boolean SINGLE_DIGIT_PERCENT = false; 50dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 514b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private static final int FULL = 96; 52dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 534b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction 54cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock 554b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private final int[] mColors; 56dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 57f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock private boolean mShowPercent; 585172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi private float mButtonHeightFraction; 59a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi private float mSubpixelSmoothingLeft; 60a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi private float mSubpixelSmoothingRight; 614b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint; 62dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private float mTextHeight, mWarningTextHeight; 63dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi private int mIconTint = Color.WHITE; 64dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 65dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private int mHeight; 66dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private int mWidth; 67dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private String mWarningString; 683332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final int mCriticalLevel; 69dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi private int mChargeColor; 70fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final float[] mBoltPoints; 71fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final Path mBoltPath = new Path(); 72fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock 73fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final RectF mFrame = new RectF(); 74fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final RectF mButtonFrame = new RectF(); 75d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock private final RectF mBoltFrame = new RectF(); 76dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 774b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private final Path mShapePath = new Path(); 784b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock private final Path mClipPath = new Path(); 791fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock private final Path mTextPath = new Path(); 804b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock 81708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi private BatteryController mBatteryController; 82708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi private boolean mPowerSaveEnabled; 83708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi 845443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int mDarkModeBackgroundColor; 855443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int mDarkModeFillColor; 865443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi 875443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int mLightModeBackgroundColor; 885443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int mLightModeFillColor; 895443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi 90f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock private BatteryTracker mTracker = new BatteryTracker(); 91f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock private final SettingObserver mSettingObserver = new SettingObserver(); 92dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 93dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public BatteryMeterView(Context context) { 94dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler this(context, null, 0); 95dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 96dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 97dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public BatteryMeterView(Context context, AttributeSet attrs) { 98dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler this(context, attrs, 0); 99dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 100dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 101dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { 102dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler super(context, attrs, defStyle); 103dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 104dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final Resources res = context.getResources(); 10529786fc72d071335c49f7b768a25071846a968feJohn Spurlock TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView, 10629786fc72d071335c49f7b768a25071846a968feJohn Spurlock defStyle, 0); 10729786fc72d071335c49f7b768a25071846a968feJohn Spurlock final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor, 1084a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette context.getColor(R.color.batterymeter_frame_color)); 109dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); 110dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); 111dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 112dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int N = levels.length(); 113dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mColors = new int[2*N]; 114dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler for (int i=0; i<N; i++) { 115dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mColors[2*i] = levels.getInt(i, 0); 116dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mColors[2*i+1] = colors.getColor(i, 0); 117dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 118fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock levels.recycle(); 119fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock colors.recycle(); 12029786fc72d071335c49f7b768a25071846a968feJohn Spurlock atts.recycle(); 121f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock updateShowPercent(); 122dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); 1233332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mCriticalLevel = mContext.getResources().getInteger( 1243332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock com.android.internal.R.integer.config_criticalBatteryWarningLevel); 1255172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi mButtonHeightFraction = context.getResources().getFraction( 1265172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi R.fraction.battery_button_height_fraction, 1, 1); 127a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mSubpixelSmoothingLeft = context.getResources().getFraction( 128a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi R.fraction.battery_subpixel_smoothing_left, 1, 1); 129a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mSubpixelSmoothingRight = context.getResources().getFraction( 130a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi R.fraction.battery_subpixel_smoothing_right, 1, 1); 131dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 1326a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 13329786fc72d071335c49f7b768a25071846a968feJohn Spurlock mFramePaint.setColor(frameColor); 134cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setDither(true); 135cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setStrokeWidth(0); 136cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); 137cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock 1386a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 139cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBatteryPaint.setDither(true); 140cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBatteryPaint.setStrokeWidth(0); 141cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); 142dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 1436a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 1444b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); 145dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint.setTypeface(font); 146dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint.setTextAlign(Paint.Align.CENTER); 147dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 1486a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 149dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setColor(mColors[1]); 150dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler font = Typeface.create("sans-serif", Typeface.BOLD); 151dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setTypeface(font); 152dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setTextAlign(Paint.Align.CENTER); 153dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 1544a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette mChargeColor = context.getColor(R.color.batterymeter_charge_color); 155fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock 1566a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 1574a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color)); 158fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPoints = loadBoltPoints(res); 1595443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi 1605443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mDarkModeBackgroundColor = 1615443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi context.getColor(R.color.dark_mode_icon_color_dual_tone_background); 1625443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill); 1635443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mLightModeBackgroundColor = 1645443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi context.getColor(R.color.light_mode_icon_color_dual_tone_background); 1655443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill); 166fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 167fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock 168f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock @Override 169f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public void onAttachedToWindow() { 170f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock super.onAttachedToWindow(); 171f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 172f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock IntentFilter filter = new IntentFilter(); 173f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock filter.addAction(Intent.ACTION_BATTERY_CHANGED); 174f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock filter.addAction(ACTION_LEVEL_TEST); 175f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock final Intent sticky = getContext().registerReceiver(mTracker, filter); 176f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (sticky != null) { 177f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock // preload the battery level 178f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock mTracker.onReceive(getContext(), sticky); 179f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 180f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock mBatteryController.addStateChangedCallback(this); 181f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock getContext().getContentResolver().registerContentObserver( 182f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); 183f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 184f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 185f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock @Override 186f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public void onDetachedFromWindow() { 187f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock super.onDetachedFromWindow(); 188f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 189f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock getContext().unregisterReceiver(mTracker); 190f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock mBatteryController.removeStateChangedCallback(this); 191f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock getContext().getContentResolver().unregisterContentObserver(mSettingObserver); 192f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 193f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 194708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi public void setBatteryController(BatteryController batteryController) { 195708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi mBatteryController = batteryController; 196708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi mPowerSaveEnabled = mBatteryController.isPowerSave(); 197708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi } 198708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi 199708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi @Override 200708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 201708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi // TODO: Use this callback instead of own broadcast receiver. 202708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi } 203708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi 204708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi @Override 205708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi public void onPowerSaveChanged() { 206708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi mPowerSaveEnabled = mBatteryController.isPowerSave(); 207708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi invalidate(); 208708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi } 209708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi 210fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private static float[] loadBoltPoints(Resources res) { 211fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); 212fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock int maxX = 0, maxY = 0; 213fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock for (int i = 0; i < pts.length; i += 2) { 214fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock maxX = Math.max(maxX, pts[i]); 215fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock maxY = Math.max(maxY, pts[i + 1]); 216fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 217fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock final float[] ptsF = new float[pts.length]; 218fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock for (int i = 0; i < pts.length; i += 2) { 219fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock ptsF[i] = (float)pts[i] / maxX; 220fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock ptsF[i + 1] = (float)pts[i + 1] / maxY; 221fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 222fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock return ptsF; 223dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 224dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 225dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 226dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler protected void onSizeChanged(int w, int h, int oldw, int oldh) { 227dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mHeight = h; 228dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWidth = w; 229dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setTextSize(h * 0.75f); 230dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; 231dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 232dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 233f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock private void updateShowPercent() { 234f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock mShowPercent = 0 != Settings.System.getInt(getContext().getContentResolver(), 235f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock SHOW_PERCENT_SETTING, 0); 236f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 237f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 238dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private int getColorForLevel(int percent) { 239708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi 240708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi // If we are in power save mode, always use the normal color. 241708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi if (mPowerSaveEnabled) { 242708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi return mColors[mColors.length-1]; 243708f7721e910d2c1fe984d2b8a6bf10565a00a61Jorim Jaggi } 244dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int thresh, color = 0; 245dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler for (int i=0; i<mColors.length; i+=2) { 246dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler thresh = mColors[i]; 247dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler color = mColors[i+1]; 248dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi if (percent <= thresh) { 249dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi 250dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi // Respect tinting for "normal" level 251dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi if (i == mColors.length-2) { 252dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi return mIconTint; 253dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi } else { 254dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi return color; 255dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi } 256dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi } 257dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 258dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler return color; 259dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 260dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 2615443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi public void setDarkIntensity(float darkIntensity) { 2625443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi int backgroundColor = getBackgroundColor(darkIntensity); 2635443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi int fillColor = getFillColor(darkIntensity); 2645443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mIconTint = fillColor; 2655443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mFramePaint.setColor(backgroundColor); 266b07ce17328be90d61cde67e5ed43dd23f0c2fdd3Xiyuan Xia mBoltPaint.setColor(fillColor); 2675443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi mChargeColor = fillColor; 268dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi invalidate(); 269dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi } 270dd0107a0dbe3084af8f5da005a4d96f8657f58a1Jorim Jaggi 2715443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int getBackgroundColor(float darkIntensity) { 2725443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi return getColorForDarkIntensity( 2735443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor); 2745443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi } 2755443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi 2765443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int getFillColor(float darkIntensity) { 2775443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi return getColorForDarkIntensity( 2785443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi darkIntensity, mLightModeFillColor, mDarkModeFillColor); 2795443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi } 2805443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi 2815443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) { 2825443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor); 2835443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi } 2845443cc563cf4581a8ea9ada3b27fac7107d72099Jorim Jaggi 285dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 286dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public void draw(Canvas c) { 2873c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker; 2883c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock final int level = tracker.level; 28905021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler 29005021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler if (level == BatteryTracker.UNKNOWN_LEVEL) return; 29105021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler 292dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler float drawFrac = (float) level / 100f; 293dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pt = getPaddingTop(); 294dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pl = getPaddingLeft(); 295dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pr = getPaddingRight(); 296dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pb = getPaddingBottom(); 2974b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock final int height = mHeight - pt - pb; 2984b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock final int width = mWidth - pl - pr; 299dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 3005172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi final int buttonHeight = (int) (height * mButtonHeightFraction); 301dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 302fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.set(0, 0, width, height); 303fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.offset(pl, pt); 304dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 3054b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // button-frame: area above the battery body 306fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mButtonFrame.set( 307a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mFrame.left + Math.round(width * 0.25f), 308fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.top, 309a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mFrame.right - Math.round(width * 0.25f), 3104b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mFrame.top + buttonHeight); 311cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock 312a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mButtonFrame.top += mSubpixelSmoothingLeft; 313a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mButtonFrame.left += mSubpixelSmoothingLeft; 314a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mButtonFrame.right -= mSubpixelSmoothingRight; 315dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 3164b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // frame: battery body area 3174b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mFrame.top += buttonHeight; 318a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mFrame.left += mSubpixelSmoothingLeft; 319a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mFrame.top += mSubpixelSmoothingLeft; 320a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mFrame.right -= mSubpixelSmoothingRight; 321a0221f3a9fb8014b24954a5a59e1e001e4a2619fJorim Jaggi mFrame.bottom -= mSubpixelSmoothingRight; 322dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 3234b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // set the battery charging color 3244b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level)); 325dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 326dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (level >= FULL) { 327dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler drawFrac = 1f; 3283332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } else if (level <= mCriticalLevel) { 329dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler drawFrac = 0f; 330dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 331dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 3324b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock final float levelTop = drawFrac == 1f ? mButtonFrame.top 3334b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock : (mFrame.top + (mFrame.height() * (1f - drawFrac))); 3344b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock 3354b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // define the battery shape 3364b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.reset(); 3374b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); 3384b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); 3394b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mButtonFrame.right, mFrame.top); 3404b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mFrame.right, mFrame.top); 3414b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mFrame.right, mFrame.bottom); 3424b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mFrame.left, mFrame.bottom); 3434b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mFrame.left, mFrame.top); 3444b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mButtonFrame.left, mFrame.top); 3454b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); 346dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 347d19877f8a3557702d87bc9ed8c4be947e947b8b7John Spurlock if (tracker.plugged) { 3484b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // define the bolt shape 349d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float bl = mFrame.left + mFrame.width() / 4.5f; 350d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float bt = mFrame.top + mFrame.height() / 6f; 351d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float br = mFrame.right - mFrame.width() / 7f; 352d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float bb = mFrame.bottom - mFrame.height() / 10f; 353fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock if (mBoltFrame.left != bl || mBoltFrame.top != bt 354fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock || mBoltFrame.right != br || mBoltFrame.bottom != bb) { 355fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.set(bl, bt, br, bb); 356fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.reset(); 357fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.moveTo( 358fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 359fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 360fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock for (int i = 2; i < mBoltPoints.length; i += 2) { 361fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.lineTo( 362fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), 363fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); 364fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 365fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.lineTo( 366fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 367fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 368fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 3694b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock 3704b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); 3714b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock boltPct = Math.min(Math.max(boltPct, 0), 1); 3724b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock if (boltPct <= BOLT_LEVEL_THRESHOLD) { 3734b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // draw the bolt if opaque 3744b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock c.drawPath(mBoltPath, mBoltPaint); 3754b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock } else { 3764b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // otherwise cut the bolt out of the overall shape 3774b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); 3784b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock } 3794b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock } 3804b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock 3811fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock // compute percentage text 3821fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock boolean pctOpaque = false; 3831fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock float pctX = 0, pctY = 0; 3841fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock String pctText = null; 385f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (!tracker.plugged && level > mCriticalLevel && mShowPercent) { 3861fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock mTextPaint.setColor(getColorForLevel(level)); 3871fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock mTextPaint.setTextSize(height * 3881fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock (SINGLE_DIGIT_PERCENT ? 0.75f 3891fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock : (tracker.level == 100 ? 0.38f : 0.5f))); 3901fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock mTextHeight = -mTextPaint.getFontMetrics().ascent; 3911fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); 3921fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock pctX = mWidth * 0.5f; 3931fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock pctY = (mHeight + mTextHeight) * 0.47f; 3941fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock pctOpaque = levelTop > pctY; 3951fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock if (!pctOpaque) { 3961fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock mTextPath.reset(); 3971fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); 3981fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock // cut the percentage text out of the overall shape 3991fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock mShapePath.op(mTextPath, Path.Op.DIFFERENCE); 4001fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock } 4011fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock } 4021fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock 4034b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // draw the battery shape background 4044b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock c.drawPath(mShapePath, mFramePaint); 4054b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock 4064b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // draw the battery shape, clipped to charging level 4074b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mFrame.top = levelTop; 4084b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mClipPath.reset(); 4094b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mClipPath.addRect(mFrame, Path.Direction.CCW); 4104b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock mShapePath.op(mClipPath, Path.Op.INTERSECT); 4114b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock c.drawPath(mShapePath, mBatteryPaint); 4124b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock 4134b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock if (!tracker.plugged) { 4143332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (level <= mCriticalLevel) { 4154b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // draw the warning text 4164b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock final float x = mWidth * 0.5f; 4174b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock final float y = (mHeight + mWarningTextHeight) * 0.48f; 4184b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock c.drawText(mWarningString, x, y, mWarningTextPaint); 4191fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock } else if (pctOpaque) { 4204b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock // draw the percentage text 4211fd0b933b86bbb20bad278de5c5c3fd268b4645bJohn Spurlock c.drawText(pctText, pctX, pctY, mTextPaint); 4224b786ff4b519b4537adb5da7113fb7797c67e385John Spurlock } 423dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 424dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 4253c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock 4260d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi @Override 4270d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi public boolean hasOverlappingRendering() { 4280d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi return false; 4290d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi } 4300d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi 4313c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock private boolean mDemoMode; 4323c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock private BatteryTracker mDemoTracker = new BatteryTracker(); 4333c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock 4343c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock @Override 4353c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock public void dispatchDemoCommand(String command, Bundle args) { 4363c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock if (!mDemoMode && command.equals(COMMAND_ENTER)) { 4373c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoMode = true; 4383c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.level = mTracker.level; 4393c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.plugged = mTracker.plugged; 4403c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } else if (mDemoMode && command.equals(COMMAND_EXIT)) { 4413c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoMode = false; 4423c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock postInvalidate(); 4433c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } else if (mDemoMode && command.equals(COMMAND_BATTERY)) { 4443c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock String level = args.getString("level"); 4453c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock String plugged = args.getString("plugged"); 4463c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock if (level != null) { 4473c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100); 4483c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 4493c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock if (plugged != null) { 4503c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.plugged = Boolean.parseBoolean(plugged); 4513c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 4523c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock postInvalidate(); 4533c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 4543c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 455f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 456f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock private final class BatteryTracker extends BroadcastReceiver { 457f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public static final int UNKNOWN_LEVEL = -1; 458f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 459f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock // current battery status 460f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int level = UNKNOWN_LEVEL; 461f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock String percentStr; 462f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int plugType; 463f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock boolean plugged; 464f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int health; 465f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int status; 466f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock String technology; 467f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int voltage; 468f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int temperature; 469f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock boolean testmode = false; 470f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 471f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock @Override 472f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public void onReceive(Context context, Intent intent) { 473f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock final String action = intent.getAction(); 474f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 475f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (testmode && ! intent.getBooleanExtra("testmode", false)) return; 476f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 477f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock level = (int)(100f 478f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) 479f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); 480f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 481f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); 482f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock plugged = plugType != 0; 483f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, 484f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock BatteryManager.BATTERY_HEALTH_UNKNOWN); 485f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 486f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock BatteryManager.BATTERY_STATUS_UNKNOWN); 487f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY); 488f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); 489f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); 490f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 491f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock setContentDescription( 492f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock context.getString(R.string.accessibility_battery_level, level)); 493f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock postInvalidate(); 494f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } else if (action.equals(ACTION_LEVEL_TEST)) { 495f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock testmode = true; 496f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock post(new Runnable() { 497f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int curLevel = 0; 498f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int incr = 1; 499f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int saveLevel = level; 500f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock int savePlugged = plugType; 501f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); 502f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock @Override 503f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public void run() { 504f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (curLevel < 0) { 505f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock testmode = false; 506f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock dummy.putExtra("level", saveLevel); 507f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock dummy.putExtra("plugged", savePlugged); 508f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock dummy.putExtra("testmode", false); 509f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } else { 510f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock dummy.putExtra("level", curLevel); 511f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC 512f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock : 0); 513f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock dummy.putExtra("testmode", true); 514f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 515f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock getContext().sendBroadcast(dummy); 516f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 517f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (!testmode) return; 518f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 519f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock curLevel += incr; 520f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock if (curLevel == 100) { 521f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock incr *= -1; 522f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 523f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock postDelayed(this, 200); 524f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 525f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock }); 526f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 527f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 528f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 529f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 530f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock private final class SettingObserver extends ContentObserver { 531f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public SettingObserver() { 532f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock super(new Handler()); 533f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 534f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 535f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock @Override 536f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock public void onChange(boolean selfChange, Uri uri) { 537f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock super.onChange(selfChange, uri); 538f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock updateShowPercent(); 539f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock postInvalidate(); 540f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 541f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock } 542f40d08f8a3094ac5d5478efc5de0b96f57d2c5dfJohn Spurlock 543dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler} 544