blob: 7bdbd0a3337cfb9d588f35f149cba6628ec2a7f4 [file] [log] [blame]
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -04001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.res.Resources;
24import android.content.res.TypedArray;
25import android.graphics.Canvas;
26import android.graphics.Paint;
John Spurlockfceb7ed2013-09-07 12:39:49 -040027import android.graphics.Path;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040028import android.graphics.RectF;
29import android.graphics.Typeface;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040030import android.os.BatteryManager;
John Spurlock3c875662013-08-31 15:07:25 -040031import android.os.Bundle;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040032import android.provider.Settings;
33import android.util.AttributeSet;
34import android.view.View;
35
Jorim Jaggi708f7722014-08-20 17:30:38 +020036import com.android.systemui.statusbar.policy.BatteryController;
37
38public class BatteryMeterView extends View implements DemoMode,
39 BatteryController.BatteryStateChangeCallback {
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040040 public static final String TAG = BatteryMeterView.class.getSimpleName();
41 public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
42
John Spurlock4b786ff2013-12-17 15:19:16 -050043 private static final boolean ENABLE_PERCENT = true;
44 private static final boolean SINGLE_DIGIT_PERCENT = false;
45 private static final boolean SHOW_100_PERCENT = false;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040046
John Spurlock4b786ff2013-12-17 15:19:16 -050047 private static final int FULL = 96;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040048
John Spurlock4b786ff2013-12-17 15:19:16 -050049 private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction
John Spurlockcfab9902013-09-25 18:07:52 -040050
John Spurlock4b786ff2013-12-17 15:19:16 -050051 private final int[] mColors;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040052
53 boolean mShowPercent = true;
Jorim Jaggi5172dc22014-09-02 14:59:06 +020054 private float mButtonHeightFraction;
Jorim Jaggia0221f32014-09-03 16:29:39 +020055 private float mSubpixelSmoothingLeft;
56 private float mSubpixelSmoothingRight;
John Spurlock4b786ff2013-12-17 15:19:16 -050057 private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040058 private float mTextHeight, mWarningTextHeight;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040059
60 private int mHeight;
61 private int mWidth;
62 private String mWarningString;
John Spurlock3332ba52014-03-10 17:44:07 -040063 private final int mCriticalLevel;
John Spurlocke189f662013-08-25 10:38:32 -040064 private final int mChargeColor;
John Spurlockfceb7ed2013-09-07 12:39:49 -040065 private final float[] mBoltPoints;
66 private final Path mBoltPath = new Path();
67
68 private final RectF mFrame = new RectF();
69 private final RectF mButtonFrame = new RectF();
John Spurlockd8595fd2013-11-05 11:55:04 -050070 private final RectF mBoltFrame = new RectF();
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040071
John Spurlock4b786ff2013-12-17 15:19:16 -050072 private final Path mShapePath = new Path();
73 private final Path mClipPath = new Path();
John Spurlock1fd0b932014-02-05 11:56:17 -050074 private final Path mTextPath = new Path();
John Spurlock4b786ff2013-12-17 15:19:16 -050075
Jorim Jaggi708f7722014-08-20 17:30:38 +020076 private BatteryController mBatteryController;
77 private boolean mPowerSaveEnabled;
78
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040079 private class BatteryTracker extends BroadcastReceiver {
Daniel Sandler05021e52013-10-14 10:27:45 -040080 public static final int UNKNOWN_LEVEL = -1;
81
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040082 // current battery status
Daniel Sandler05021e52013-10-14 10:27:45 -040083 int level = UNKNOWN_LEVEL;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040084 String percentStr;
85 int plugType;
86 boolean plugged;
87 int health;
88 int status;
89 String technology;
90 int voltage;
91 int temperature;
92 boolean testmode = false;
93
94 @Override
95 public void onReceive(Context context, Intent intent) {
96 final String action = intent.getAction();
97 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
98 if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
99
100 level = (int)(100f
101 * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
102 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
103
104 plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
105 plugged = plugType != 0;
106 health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH,
107 BatteryManager.BATTERY_HEALTH_UNKNOWN);
108 status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
109 BatteryManager.BATTERY_STATUS_UNKNOWN);
110 technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
111 voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
112 temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
113
114 setContentDescription(
115 context.getString(R.string.accessibility_battery_level, level));
116 postInvalidate();
117 } else if (action.equals(ACTION_LEVEL_TEST)) {
118 testmode = true;
119 post(new Runnable() {
120 int curLevel = 0;
121 int incr = 1;
122 int saveLevel = level;
123 int savePlugged = plugType;
124 Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
125 @Override
126 public void run() {
127 if (curLevel < 0) {
128 testmode = false;
129 dummy.putExtra("level", saveLevel);
130 dummy.putExtra("plugged", savePlugged);
131 dummy.putExtra("testmode", false);
132 } else {
133 dummy.putExtra("level", curLevel);
134 dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC : 0);
135 dummy.putExtra("testmode", true);
136 }
137 getContext().sendBroadcast(dummy);
138
139 if (!testmode) return;
140
141 curLevel += incr;
142 if (curLevel == 100) {
143 incr *= -1;
144 }
145 postDelayed(this, 200);
146 }
147 });
148 }
149 }
150 }
151
152 BatteryTracker mTracker = new BatteryTracker();
153
154 @Override
155 public void onAttachedToWindow() {
156 super.onAttachedToWindow();
157
158 IntentFilter filter = new IntentFilter();
159 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
160 filter.addAction(ACTION_LEVEL_TEST);
Daniel Sandler05021e52013-10-14 10:27:45 -0400161 final Intent sticky = getContext().registerReceiver(mTracker, filter);
162 if (sticky != null) {
163 // preload the battery level
164 mTracker.onReceive(getContext(), sticky);
165 }
Jorim Jaggi708f7722014-08-20 17:30:38 +0200166 mBatteryController.addStateChangedCallback(this);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400167 }
168
169 @Override
170 public void onDetachedFromWindow() {
171 super.onDetachedFromWindow();
172
173 getContext().unregisterReceiver(mTracker);
Jorim Jaggi708f7722014-08-20 17:30:38 +0200174 mBatteryController.removeStateChangedCallback(this);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400175 }
176
177 public BatteryMeterView(Context context) {
178 this(context, null, 0);
179 }
180
181 public BatteryMeterView(Context context, AttributeSet attrs) {
182 this(context, attrs, 0);
183 }
184
185 public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
186 super(context, attrs, defStyle);
187
188 final Resources res = context.getResources();
John Spurlock29786fc2014-02-04 17:55:47 -0500189 TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView,
190 defStyle, 0);
191 final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
192 res.getColor(R.color.batterymeter_frame_color));
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400193 TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
194 TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
195
196 final int N = levels.length();
197 mColors = new int[2*N];
198 for (int i=0; i<N; i++) {
199 mColors[2*i] = levels.getInt(i, 0);
200 mColors[2*i+1] = colors.getColor(i, 0);
201 }
John Spurlockfceb7ed2013-09-07 12:39:49 -0400202 levels.recycle();
203 colors.recycle();
John Spurlock29786fc2014-02-04 17:55:47 -0500204 atts.recycle();
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400205 mShowPercent = ENABLE_PERCENT && 0 != Settings.System.getInt(
206 context.getContentResolver(), "status_bar_show_battery_percent", 0);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400207 mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
John Spurlock3332ba52014-03-10 17:44:07 -0400208 mCriticalLevel = mContext.getResources().getInteger(
209 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
Jorim Jaggi5172dc22014-09-02 14:59:06 +0200210 mButtonHeightFraction = context.getResources().getFraction(
211 R.fraction.battery_button_height_fraction, 1, 1);
Jorim Jaggia0221f32014-09-03 16:29:39 +0200212 mSubpixelSmoothingLeft = context.getResources().getFraction(
213 R.fraction.battery_subpixel_smoothing_left, 1, 1);
214 mSubpixelSmoothingRight = context.getResources().getFraction(
215 R.fraction.battery_subpixel_smoothing_right, 1, 1);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400216
217 mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
John Spurlock29786fc2014-02-04 17:55:47 -0500218 mFramePaint.setColor(frameColor);
John Spurlockcfab9902013-09-25 18:07:52 -0400219 mFramePaint.setDither(true);
220 mFramePaint.setStrokeWidth(0);
221 mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
John Spurlockcfab9902013-09-25 18:07:52 -0400222
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400223 mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
John Spurlockcfab9902013-09-25 18:07:52 -0400224 mBatteryPaint.setDither(true);
225 mBatteryPaint.setStrokeWidth(0);
226 mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400227
228 mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
John Spurlock4b786ff2013-12-17 15:19:16 -0500229 Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400230 mTextPaint.setTypeface(font);
231 mTextPaint.setTextAlign(Paint.Align.CENTER);
232
233 mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
234 mWarningTextPaint.setColor(mColors[1]);
235 font = Typeface.create("sans-serif", Typeface.BOLD);
236 mWarningTextPaint.setTypeface(font);
237 mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
238
John Spurlocke189f662013-08-25 10:38:32 -0400239 mChargeColor = getResources().getColor(R.color.batterymeter_charge_color);
John Spurlockfceb7ed2013-09-07 12:39:49 -0400240
John Spurlock4b786ff2013-12-17 15:19:16 -0500241 mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
John Spurlockcfab9902013-09-25 18:07:52 -0400242 mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color));
John Spurlockfceb7ed2013-09-07 12:39:49 -0400243 mBoltPoints = loadBoltPoints(res);
244 }
245
Jorim Jaggi708f7722014-08-20 17:30:38 +0200246 public void setBatteryController(BatteryController batteryController) {
247 mBatteryController = batteryController;
248 mPowerSaveEnabled = mBatteryController.isPowerSave();
249 }
250
251 @Override
252 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
253 // TODO: Use this callback instead of own broadcast receiver.
254 }
255
256 @Override
257 public void onPowerSaveChanged() {
258 mPowerSaveEnabled = mBatteryController.isPowerSave();
259 invalidate();
260 }
261
John Spurlockfceb7ed2013-09-07 12:39:49 -0400262 private static float[] loadBoltPoints(Resources res) {
263 final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
264 int maxX = 0, maxY = 0;
265 for (int i = 0; i < pts.length; i += 2) {
266 maxX = Math.max(maxX, pts[i]);
267 maxY = Math.max(maxY, pts[i + 1]);
268 }
269 final float[] ptsF = new float[pts.length];
270 for (int i = 0; i < pts.length; i += 2) {
271 ptsF[i] = (float)pts[i] / maxX;
272 ptsF[i + 1] = (float)pts[i + 1] / maxY;
273 }
274 return ptsF;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400275 }
276
277 @Override
278 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
279 mHeight = h;
280 mWidth = w;
281 mWarningTextPaint.setTextSize(h * 0.75f);
282 mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
283 }
284
285 private int getColorForLevel(int percent) {
Jorim Jaggi708f7722014-08-20 17:30:38 +0200286
287 // If we are in power save mode, always use the normal color.
288 if (mPowerSaveEnabled) {
289 return mColors[mColors.length-1];
290 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400291 int thresh, color = 0;
292 for (int i=0; i<mColors.length; i+=2) {
293 thresh = mColors[i];
294 color = mColors[i+1];
295 if (percent <= thresh) return color;
296 }
297 return color;
298 }
299
300 @Override
301 public void draw(Canvas c) {
John Spurlock3c875662013-08-31 15:07:25 -0400302 BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
303 final int level = tracker.level;
Daniel Sandler05021e52013-10-14 10:27:45 -0400304
305 if (level == BatteryTracker.UNKNOWN_LEVEL) return;
306
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400307 float drawFrac = (float) level / 100f;
308 final int pt = getPaddingTop();
309 final int pl = getPaddingLeft();
310 final int pr = getPaddingRight();
311 final int pb = getPaddingBottom();
John Spurlock4b786ff2013-12-17 15:19:16 -0500312 final int height = mHeight - pt - pb;
313 final int width = mWidth - pl - pr;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400314
Jorim Jaggi5172dc22014-09-02 14:59:06 +0200315 final int buttonHeight = (int) (height * mButtonHeightFraction);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400316
John Spurlockfceb7ed2013-09-07 12:39:49 -0400317 mFrame.set(0, 0, width, height);
318 mFrame.offset(pl, pt);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400319
John Spurlock4b786ff2013-12-17 15:19:16 -0500320 // button-frame: area above the battery body
John Spurlockfceb7ed2013-09-07 12:39:49 -0400321 mButtonFrame.set(
Jorim Jaggia0221f32014-09-03 16:29:39 +0200322 mFrame.left + Math.round(width * 0.25f),
John Spurlockfceb7ed2013-09-07 12:39:49 -0400323 mFrame.top,
Jorim Jaggia0221f32014-09-03 16:29:39 +0200324 mFrame.right - Math.round(width * 0.25f),
John Spurlock4b786ff2013-12-17 15:19:16 -0500325 mFrame.top + buttonHeight);
John Spurlockcfab9902013-09-25 18:07:52 -0400326
Jorim Jaggia0221f32014-09-03 16:29:39 +0200327 mButtonFrame.top += mSubpixelSmoothingLeft;
328 mButtonFrame.left += mSubpixelSmoothingLeft;
329 mButtonFrame.right -= mSubpixelSmoothingRight;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400330
John Spurlock4b786ff2013-12-17 15:19:16 -0500331 // frame: battery body area
332 mFrame.top += buttonHeight;
Jorim Jaggia0221f32014-09-03 16:29:39 +0200333 mFrame.left += mSubpixelSmoothingLeft;
334 mFrame.top += mSubpixelSmoothingLeft;
335 mFrame.right -= mSubpixelSmoothingRight;
336 mFrame.bottom -= mSubpixelSmoothingRight;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400337
John Spurlock4b786ff2013-12-17 15:19:16 -0500338 // set the battery charging color
339 mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level));
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400340
341 if (level >= FULL) {
342 drawFrac = 1f;
John Spurlock3332ba52014-03-10 17:44:07 -0400343 } else if (level <= mCriticalLevel) {
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400344 drawFrac = 0f;
345 }
346
John Spurlock4b786ff2013-12-17 15:19:16 -0500347 final float levelTop = drawFrac == 1f ? mButtonFrame.top
348 : (mFrame.top + (mFrame.height() * (1f - drawFrac)));
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400349
John Spurlock4b786ff2013-12-17 15:19:16 -0500350 // define the battery shape
351 mShapePath.reset();
352 mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
353 mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
354 mShapePath.lineTo(mButtonFrame.right, mFrame.top);
355 mShapePath.lineTo(mFrame.right, mFrame.top);
356 mShapePath.lineTo(mFrame.right, mFrame.bottom);
357 mShapePath.lineTo(mFrame.left, mFrame.bottom);
358 mShapePath.lineTo(mFrame.left, mFrame.top);
359 mShapePath.lineTo(mButtonFrame.left, mFrame.top);
360 mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400361
John Spurlockd19877f2013-09-17 11:03:03 -0400362 if (tracker.plugged) {
John Spurlock4b786ff2013-12-17 15:19:16 -0500363 // define the bolt shape
John Spurlockd8595fd2013-11-05 11:55:04 -0500364 final float bl = mFrame.left + mFrame.width() / 4.5f;
365 final float bt = mFrame.top + mFrame.height() / 6f;
366 final float br = mFrame.right - mFrame.width() / 7f;
367 final float bb = mFrame.bottom - mFrame.height() / 10f;
John Spurlockfceb7ed2013-09-07 12:39:49 -0400368 if (mBoltFrame.left != bl || mBoltFrame.top != bt
369 || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
370 mBoltFrame.set(bl, bt, br, bb);
371 mBoltPath.reset();
372 mBoltPath.moveTo(
373 mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
374 mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
375 for (int i = 2; i < mBoltPoints.length; i += 2) {
376 mBoltPath.lineTo(
377 mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
378 mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
379 }
380 mBoltPath.lineTo(
381 mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
382 mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
383 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400384
John Spurlock4b786ff2013-12-17 15:19:16 -0500385 float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
386 boltPct = Math.min(Math.max(boltPct, 0), 1);
387 if (boltPct <= BOLT_LEVEL_THRESHOLD) {
388 // draw the bolt if opaque
389 c.drawPath(mBoltPath, mBoltPaint);
390 } else {
391 // otherwise cut the bolt out of the overall shape
392 mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
393 }
394 }
395
John Spurlock1fd0b932014-02-05 11:56:17 -0500396 // compute percentage text
397 boolean pctOpaque = false;
398 float pctX = 0, pctY = 0;
399 String pctText = null;
John Spurlock3332ba52014-03-10 17:44:07 -0400400 if (!tracker.plugged && level > mCriticalLevel && mShowPercent
John Spurlock1fd0b932014-02-05 11:56:17 -0500401 && !(tracker.level == 100 && !SHOW_100_PERCENT)) {
402 mTextPaint.setColor(getColorForLevel(level));
403 mTextPaint.setTextSize(height *
404 (SINGLE_DIGIT_PERCENT ? 0.75f
405 : (tracker.level == 100 ? 0.38f : 0.5f)));
406 mTextHeight = -mTextPaint.getFontMetrics().ascent;
407 pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
408 pctX = mWidth * 0.5f;
409 pctY = (mHeight + mTextHeight) * 0.47f;
410 pctOpaque = levelTop > pctY;
411 if (!pctOpaque) {
412 mTextPath.reset();
413 mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath);
414 // cut the percentage text out of the overall shape
415 mShapePath.op(mTextPath, Path.Op.DIFFERENCE);
416 }
417 }
418
John Spurlock4b786ff2013-12-17 15:19:16 -0500419 // draw the battery shape background
420 c.drawPath(mShapePath, mFramePaint);
421
422 // draw the battery shape, clipped to charging level
423 mFrame.top = levelTop;
424 mClipPath.reset();
425 mClipPath.addRect(mFrame, Path.Direction.CCW);
426 mShapePath.op(mClipPath, Path.Op.INTERSECT);
427 c.drawPath(mShapePath, mBatteryPaint);
428
429 if (!tracker.plugged) {
John Spurlock3332ba52014-03-10 17:44:07 -0400430 if (level <= mCriticalLevel) {
John Spurlock4b786ff2013-12-17 15:19:16 -0500431 // draw the warning text
432 final float x = mWidth * 0.5f;
433 final float y = (mHeight + mWarningTextHeight) * 0.48f;
434 c.drawText(mWarningString, x, y, mWarningTextPaint);
John Spurlock1fd0b932014-02-05 11:56:17 -0500435 } else if (pctOpaque) {
John Spurlock4b786ff2013-12-17 15:19:16 -0500436 // draw the percentage text
John Spurlock1fd0b932014-02-05 11:56:17 -0500437 c.drawText(pctText, pctX, pctY, mTextPaint);
John Spurlock4b786ff2013-12-17 15:19:16 -0500438 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400439 }
440 }
John Spurlock3c875662013-08-31 15:07:25 -0400441
Jorim Jaggi0d266892014-07-28 14:49:13 +0200442 @Override
443 public boolean hasOverlappingRendering() {
444 return false;
445 }
446
John Spurlock3c875662013-08-31 15:07:25 -0400447 private boolean mDemoMode;
448 private BatteryTracker mDemoTracker = new BatteryTracker();
449
450 @Override
451 public void dispatchDemoCommand(String command, Bundle args) {
452 if (!mDemoMode && command.equals(COMMAND_ENTER)) {
453 mDemoMode = true;
454 mDemoTracker.level = mTracker.level;
455 mDemoTracker.plugged = mTracker.plugged;
456 } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
457 mDemoMode = false;
458 postInvalidate();
459 } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
460 String level = args.getString("level");
461 String plugged = args.getString("plugged");
462 if (level != null) {
463 mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100);
464 }
465 if (plugged != null) {
466 mDemoTracker.plugged = Boolean.parseBoolean(plugged);
467 }
468 postInvalidate();
469 }
470 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400471}