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 19dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.BroadcastReceiver; 20dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.Context; 21dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.Intent; 22dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.IntentFilter; 23dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.res.Resources; 24dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.content.res.TypedArray; 25dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Canvas; 26dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Paint; 27fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlockimport android.graphics.Path; 28fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlockimport android.graphics.PorterDuff; 29fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlockimport android.graphics.PorterDuffXfermode; 30dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Rect; 31dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.RectF; 32dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.graphics.Typeface; 33dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.os.BatteryManager; 343c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlockimport android.os.Bundle; 35dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.provider.Settings; 36dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.util.AttributeSet; 37dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandlerimport android.view.View; 38dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 393c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlockpublic class BatteryMeterView extends View implements DemoMode { 40dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final String TAG = BatteryMeterView.class.getSimpleName(); 41dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; 42dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 43dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final boolean ENABLE_PERCENT = true; 44dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final boolean SINGLE_DIGIT_PERCENT = false; 45dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final boolean SHOW_100_PERCENT = false; 46dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 47dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final int FULL = 96; 48dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public static final int EMPTY = 4; 49dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 50cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock public static final float SUBPIXEL = 0.4f; // inset rects for softer edges 51cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock 52dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int[] mColors; 53dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 54dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler boolean mShowPercent = true; 55fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint; 56dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int mButtonHeight; 57dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private float mTextHeight, mWarningTextHeight; 58dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 59dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private int mHeight; 60dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private int mWidth; 61dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private String mWarningString; 62e189f662df446effc77560a64136652b16d9d54bJohn Spurlock private final int mChargeColor; 63fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final float[] mBoltPoints; 64fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final Path mBoltPath = new Path(); 65fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock 66fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final RectF mFrame = new RectF(); 67fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final RectF mButtonFrame = new RectF(); 68fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private final RectF mClipFrame = new RectF(); 69d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock private final RectF mBoltFrame = new RectF(); 70dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 71dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private class BatteryTracker extends BroadcastReceiver { 7205021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler public static final int UNKNOWN_LEVEL = -1; 7305021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler 74dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler // current battery status 7505021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler int level = UNKNOWN_LEVEL; 76dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler String percentStr; 77dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int plugType; 78dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler boolean plugged; 79dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int health; 80dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int status; 81dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler String technology; 82dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int voltage; 83dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int temperature; 84dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler boolean testmode = false; 85dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 86dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 87dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public void onReceive(Context context, Intent intent) { 88dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final String action = intent.getAction(); 89dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 90dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (testmode && ! intent.getBooleanExtra("testmode", false)) return; 91dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 92dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler level = (int)(100f 93dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) 94dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); 95dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 96dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); 97dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler plugged = plugType != 0; 98dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, 99dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler BatteryManager.BATTERY_HEALTH_UNKNOWN); 100dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 101dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler BatteryManager.BATTERY_STATUS_UNKNOWN); 102dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY); 103dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); 104dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); 105dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 106dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler setContentDescription( 107dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler context.getString(R.string.accessibility_battery_level, level)); 108dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler postInvalidate(); 109dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } else if (action.equals(ACTION_LEVEL_TEST)) { 110dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler testmode = true; 111dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler post(new Runnable() { 112dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int curLevel = 0; 113dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int incr = 1; 114dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int saveLevel = level; 115dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int savePlugged = plugType; 116dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); 117dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 118dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public void run() { 119dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (curLevel < 0) { 120dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler testmode = false; 121dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler dummy.putExtra("level", saveLevel); 122dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler dummy.putExtra("plugged", savePlugged); 123dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler dummy.putExtra("testmode", false); 124dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } else { 125dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler dummy.putExtra("level", curLevel); 126dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC : 0); 127dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler dummy.putExtra("testmode", true); 128dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 129dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler getContext().sendBroadcast(dummy); 130dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 131dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (!testmode) return; 132dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 133dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler curLevel += incr; 134dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (curLevel == 100) { 135dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler incr *= -1; 136dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 137dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler postDelayed(this, 200); 138dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 139dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler }); 140dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 141dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 142dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 143dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 144dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler BatteryTracker mTracker = new BatteryTracker(); 145dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 146dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 147dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public void onAttachedToWindow() { 148dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler super.onAttachedToWindow(); 149dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 150dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler IntentFilter filter = new IntentFilter(); 151dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler filter.addAction(Intent.ACTION_BATTERY_CHANGED); 152dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler filter.addAction(ACTION_LEVEL_TEST); 15305021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler final Intent sticky = getContext().registerReceiver(mTracker, filter); 15405021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler if (sticky != null) { 15505021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler // preload the battery level 15605021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler mTracker.onReceive(getContext(), sticky); 15705021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler } 158dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 159dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 160dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 161dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public void onDetachedFromWindow() { 162dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler super.onDetachedFromWindow(); 163dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 164dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler getContext().unregisterReceiver(mTracker); 165dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 166dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 167dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public BatteryMeterView(Context context) { 168dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler this(context, null, 0); 169dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 170dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 171dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public BatteryMeterView(Context context, AttributeSet attrs) { 172dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler this(context, attrs, 0); 173dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 174dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 175dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { 176dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler super(context, attrs, defStyle); 177dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 178dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final Resources res = context.getResources(); 179dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); 180dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); 181dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 182dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int N = levels.length(); 183dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mColors = new int[2*N]; 184dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler for (int i=0; i<N; i++) { 185dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mColors[2*i] = levels.getInt(i, 0); 186dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mColors[2*i+1] = colors.getColor(i, 0); 187dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 188fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock levels.recycle(); 189fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock colors.recycle(); 190dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mShowPercent = ENABLE_PERCENT && 0 != Settings.System.getInt( 191dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler context.getContentResolver(), "status_bar_show_battery_percent", 0); 192dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 193dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); 194dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 195dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 196dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mFramePaint.setColor(res.getColor(R.color.batterymeter_frame_color)); 197cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setDither(true); 198cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setStrokeWidth(0); 199cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); 200cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFramePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)); 201cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock 202dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 203cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBatteryPaint.setDither(true); 204cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBatteryPaint.setStrokeWidth(0); 205cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); 206dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 207dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 208dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint.setColor(0xFFFFFFFF); 209dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler Typeface font = Typeface.create("sans-serif-condensed", Typeface.NORMAL); 210dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint.setTypeface(font); 211dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint.setTextAlign(Paint.Align.CENTER); 212dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 213dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 214dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setColor(mColors[1]); 215dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler font = Typeface.create("sans-serif", Typeface.BOLD); 216dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setTypeface(font); 217dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setTextAlign(Paint.Align.CENTER); 218dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 219e189f662df446effc77560a64136652b16d9d54bJohn Spurlock mChargeColor = getResources().getColor(R.color.batterymeter_charge_color); 220fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock 221fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPaint = new Paint(); 222fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPaint.setAntiAlias(true); 223cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color)); 224fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPoints = loadBoltPoints(res); 225cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock setLayerType(View.LAYER_TYPE_SOFTWARE, null); 226fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 227fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock 228fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock private static float[] loadBoltPoints(Resources res) { 229fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); 230fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock int maxX = 0, maxY = 0; 231fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock for (int i = 0; i < pts.length; i += 2) { 232fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock maxX = Math.max(maxX, pts[i]); 233fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock maxY = Math.max(maxY, pts[i + 1]); 234fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 235fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock final float[] ptsF = new float[pts.length]; 236fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock for (int i = 0; i < pts.length; i += 2) { 237fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock ptsF[i] = (float)pts[i] / maxX; 238fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock ptsF[i + 1] = (float)pts[i + 1] / maxY; 239fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 240fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock return ptsF; 241dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 242dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 243dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 244dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler protected void onSizeChanged(int w, int h, int oldw, int oldh) { 245dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mHeight = h; 246dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWidth = w; 247dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextPaint.setTextSize(h * 0.75f); 248dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; 249dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 250dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 251dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler private int getColorForLevel(int percent) { 252dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int thresh, color = 0; 253dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler for (int i=0; i<mColors.length; i+=2) { 254dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler thresh = mColors[i]; 255dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler color = mColors[i+1]; 256dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (percent <= thresh) return color; 257dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 258dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler return color; 259dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 260dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 261dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler @Override 262dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler public void draw(Canvas c) { 2633c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker; 2643c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock final int level = tracker.level; 26505021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler 26605021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler if (level == BatteryTracker.UNKNOWN_LEVEL) return; 26705021e5e47132799efc3f8312fbca7cb20e6fc71Daniel Sandler 268dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler float drawFrac = (float) level / 100f; 269dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pt = getPaddingTop(); 270dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pl = getPaddingLeft(); 271dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pr = getPaddingRight(); 272dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final int pb = getPaddingBottom(); 273dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int height = mHeight - pt - pb; 274dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler int width = mWidth - pl - pr; 275dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 276dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mButtonHeight = (int) (height * 0.12f); 277dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 278fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.set(0, 0, width, height); 279fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.offset(pl, pt); 280dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 281fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mButtonFrame.set( 282fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.left + width * 0.25f, 283fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.top, 284fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.right - width * 0.25f, 285cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFrame.top + mButtonHeight + 5 /*cover frame border of intersecting area*/); 286cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock 287cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mButtonFrame.top += SUBPIXEL; 288cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mButtonFrame.left += SUBPIXEL; 289cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mButtonFrame.right -= SUBPIXEL; 290dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 291fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mFrame.top += mButtonHeight; 292cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFrame.left += SUBPIXEL; 293cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFrame.top += SUBPIXEL; 294cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFrame.right -= SUBPIXEL; 295cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock mFrame.bottom -= SUBPIXEL; 296dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 297dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler // first, draw the battery shape 298fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock c.drawRect(mFrame, mFramePaint); 299dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 300dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler // fill 'er up 301cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock final int color = tracker.plugged ? mChargeColor : getColorForLevel(level); 302dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mBatteryPaint.setColor(color); 303dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 304dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler if (level >= FULL) { 305dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler drawFrac = 1f; 306dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } else if (level <= EMPTY) { 307dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler drawFrac = 0f; 308dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 309dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 310fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock c.drawRect(mButtonFrame, drawFrac == 1f ? mBatteryPaint : mFramePaint); 311dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 312fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mClipFrame.set(mFrame); 313fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mClipFrame.top += (mFrame.height() * (1f - drawFrac)); 314dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 315dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler c.save(Canvas.CLIP_SAVE_FLAG); 316fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock c.clipRect(mClipFrame); 317fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock c.drawRect(mFrame, mBatteryPaint); 318dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler c.restore(); 319dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 320d19877f8a3557702d87bc9ed8c4be947e947b8b7John Spurlock if (tracker.plugged) { 321fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock // draw the bolt 322d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float bl = mFrame.left + mFrame.width() / 4.5f; 323d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float bt = mFrame.top + mFrame.height() / 6f; 324d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float br = mFrame.right - mFrame.width() / 7f; 325d8595fd8feca567d48c4e271070a75c576a7dfbfJohn Spurlock final float bb = mFrame.bottom - mFrame.height() / 10f; 326fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock if (mBoltFrame.left != bl || mBoltFrame.top != bt 327fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock || mBoltFrame.right != br || mBoltFrame.bottom != bb) { 328fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.set(bl, bt, br, bb); 329fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.reset(); 330fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.moveTo( 331fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 332fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 333fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock for (int i = 2; i < mBoltPoints.length; i += 2) { 334fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.lineTo( 335fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), 336fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); 337fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 338fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltPath.lineTo( 339fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 340fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 341fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock } 342fceb7edddeda6962212377cb88391d9affe5967aJohn Spurlock c.drawPath(mBoltPath, mBoltPaint); 343d19877f8a3557702d87bc9ed8c4be947e947b8b7John Spurlock } else if (level <= EMPTY) { 344d19877f8a3557702d87bc9ed8c4be947e947b8b7John Spurlock final float x = mWidth * 0.5f; 345d19877f8a3557702d87bc9ed8c4be947e947b8b7John Spurlock final float y = (mHeight + mWarningTextHeight) * 0.48f; 346d19877f8a3557702d87bc9ed8c4be947e947b8b7John Spurlock c.drawText(mWarningString, x, y, mWarningTextPaint); 3473c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } else if (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT)) { 348dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint.setTextSize(height * 349dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler (SINGLE_DIGIT_PERCENT ? 0.75f 3503c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock : (tracker.level == 100 ? 0.38f : 0.5f))); 351dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextHeight = -mTextPaint.getFontMetrics().ascent; 352dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler 353cfab99005360819294c65280d8b695ab50c1f0b3John Spurlock final String str = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); 354dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final float x = mWidth * 0.5f; 355dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler final float y = (mHeight + mTextHeight) * 0.47f; 356dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler c.drawText(str, 357dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler x, 358dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler y, 359dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler mTextPaint); 360dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 361dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler } 3623c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock 3633c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock private boolean mDemoMode; 3643c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock private BatteryTracker mDemoTracker = new BatteryTracker(); 3653c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock 3663c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock @Override 3673c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock public void dispatchDemoCommand(String command, Bundle args) { 3683c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock if (!mDemoMode && command.equals(COMMAND_ENTER)) { 3693c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoMode = true; 3703c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.level = mTracker.level; 3713c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.plugged = mTracker.plugged; 3723c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } else if (mDemoMode && command.equals(COMMAND_EXIT)) { 3733c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoMode = false; 3743c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock postInvalidate(); 3753c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } else if (mDemoMode && command.equals(COMMAND_BATTERY)) { 3763c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock String level = args.getString("level"); 3773c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock String plugged = args.getString("plugged"); 3783c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock if (level != null) { 3793c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100); 3803c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 3813c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock if (plugged != null) { 3823c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock mDemoTracker.plugged = Boolean.parseBoolean(plugged); 3833c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 3843c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock postInvalidate(); 3853c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 3863c87566c115e1fce3fdc09a6fe40488bcdc04cdeJohn Spurlock } 387dfaf3bdeeb21c8421074c70d82642612bcdd8e98Daniel Sandler} 388