More battery level improvements.

Take into account durations when there is no data due to
a reboot.  Also show times when charging and screen is on.

Change-Id: I84e75efb3339b0596bea3bbca9dbea6d9f864537
This commit is contained in:
Dianne Hackborn
2010-06-22 16:08:50 -07:00
parent f4cf7de672
commit 12fd447d6f

View File

@@ -33,6 +33,8 @@ import android.util.AttributeSet;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View; import android.view.View;
import java.util.ArrayList;
public class BatteryHistoryChart extends View { public class BatteryHistoryChart extends View {
static final int SANS = 1; static final int SANS = 1;
static final int SERIF = 2; static final int SERIF = 2;
@@ -45,14 +47,27 @@ public class BatteryHistoryChart extends View {
final Paint mBatteryGoodPaint = new Paint(Paint.ANTI_ALIAS_FLAG); final Paint mBatteryGoodPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final Paint mBatteryWarnPaint = new Paint(Paint.ANTI_ALIAS_FLAG); final Paint mBatteryWarnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final Paint mBatteryCriticalPaint = new Paint(Paint.ANTI_ALIAS_FLAG); final Paint mBatteryCriticalPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final Paint mChargingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final Paint mScreenOnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
final Path mBatLevelPath = new Path();
final Path mBatGoodPath = new Path();
final Path mBatWarnPath = new Path();
final Path mBatCriticalPath = new Path();
final Path mChargingPath = new Path();
final Path mScreenOnPath = new Path();
int mFontSize; int mFontSize;
BatteryStats mStats; BatteryStats mStats;
long mStatsPeriod; long mStatsPeriod;
String mDurationString; String mDurationString;
int mChargingOffset;
int mScreenOnOffset;
int mLevelOffset;
int mTextAscent; int mTextAscent;
int mTextDescent; int mTextDescent;
int mDurationStringWidth; int mDurationStringWidth;
@@ -64,12 +79,6 @@ public class BatteryHistoryChart extends View {
int mBatLow; int mBatLow;
int mBatHigh; int mBatHigh;
final Path mBatLevelPath = new Path();
int[] mBatLevelX;
int[] mBatLevelY;
byte[] mBatLevelValue;
int mNumBatLevel;
public BatteryHistoryChart(Context context, AttributeSet attrs) { public BatteryHistoryChart(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
@@ -80,10 +89,23 @@ public class BatteryHistoryChart extends View {
2, getResources().getDisplayMetrics()); 2, getResources().getDisplayMetrics());
if (lineWidth <= 0) lineWidth = 1; if (lineWidth <= 0) lineWidth = 1;
mBatteryGoodPaint.setStrokeWidth(lineWidth); mBatteryGoodPaint.setStrokeWidth(lineWidth);
mBatteryGoodPaint.setStyle(Paint.Style.STROKE);
mBatteryWarnPaint.setARGB(128, 255, 255, 0); mBatteryWarnPaint.setARGB(128, 255, 255, 0);
mBatteryWarnPaint.setStrokeWidth(lineWidth); mBatteryWarnPaint.setStrokeWidth(lineWidth);
mBatteryWarnPaint.setStyle(Paint.Style.STROKE);
mBatteryCriticalPaint.setARGB(192, 255, 0, 0); mBatteryCriticalPaint.setARGB(192, 255, 0, 0);
mBatteryCriticalPaint.setStrokeWidth(lineWidth); mBatteryCriticalPaint.setStrokeWidth(lineWidth);
mBatteryCriticalPaint.setStyle(Paint.Style.STROKE);
mChargingPaint.setARGB(255, 0, 128, 0);
mChargingPaint.setStrokeWidth(lineWidth);
mChargingPaint.setStyle(Paint.Style.STROKE);
mScreenOnPaint.setARGB(255, 0, 0, 255);
mScreenOnPaint.setStrokeWidth(lineWidth);
mScreenOnPaint.setStyle(Paint.Style.STROKE);
mScreenOnOffset = lineWidth;
mChargingOffset = lineWidth*2;
mLevelOffset = lineWidth*3;
mTextPaint.density = getResources().getDisplayMetrics().density; mTextPaint.density = getResources().getDisplayMetrics().density;
mTextPaint.setCompatibilityScaling( mTextPaint.setCompatibilityScaling(
@@ -265,15 +287,38 @@ public class BatteryHistoryChart extends View {
mTextDescent = (int)mTextPaint.descent(); mTextDescent = (int)mTextPaint.descent();
} }
void finishPaths(int w, int h, int levelh, int startX, int y, Path curLevelPath,
int lastBatX, boolean lastCharging, boolean lastScreenOn, Path lastPath) {
if (curLevelPath != null) {
if (lastBatX >= 0) {
if (lastPath != null) {
lastPath.lineTo(w, y);
}
curLevelPath.lineTo(w, y);
}
curLevelPath.lineTo(w, levelh);
curLevelPath.lineTo(startX, levelh);
curLevelPath.close();
}
if (lastCharging) {
mChargingPath.lineTo(w, h-mChargingOffset);
}
if (lastScreenOn) {
mScreenOnPath.lineTo(w, h-mScreenOnOffset);
}
}
@Override @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) { protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh); super.onSizeChanged(w, h, oldw, oldh);
mBatLevelPath.reset(); mBatLevelPath.reset();
mBatLevelX = new int[w+5]; mBatGoodPath.reset();
mBatLevelY = new int[w+5]; mBatWarnPath.reset();
mBatLevelValue = new byte[w+5]; mBatCriticalPath.reset();
mNumBatLevel = 0; mScreenOnPath.reset();
mChargingPath.reset();
final long timeStart = mHistStart; final long timeStart = mHistStart;
final long timeChange = mHistEnd-mHistStart; final long timeChange = mHistEnd-mHistStart;
@@ -281,61 +326,93 @@ public class BatteryHistoryChart extends View {
final int batLow = mBatLow; final int batLow = mBatLow;
final int batChange = mBatHigh-mBatLow; final int batChange = mBatHigh-mBatLow;
final int levelh = h - mLevelOffset;
BatteryStats.HistoryItem rec = mHistFirst; BatteryStats.HistoryItem rec = mHistFirst;
int x = 0, y = 0, lastX = -1, lastY = -1, lastBatX = -1, lastBatY = -1; int x = 0, y = 0, startX = 0, lastX = -1, lastY = -1, lastBatX = -1;
byte lastBatValue = 0; int i = 0;
int i = 0, num = 0; Path curLevelPath = null;
boolean first = true; Path lastLinePath = null;
boolean lastCharging = false, lastScreenOn = false;
final int N = mNumHist; final int N = mNumHist;
while (rec != null && i < N) { while (rec != null && i < N) {
if (rec.cmd == BatteryStats.HistoryItem.CMD_UPDATE) { if (rec.cmd == BatteryStats.HistoryItem.CMD_UPDATE) {
x = (int)(((rec.time-timeStart)*w)/timeChange); x = (int)(((rec.time-timeStart)*w)/timeChange);
y = h-1 - ((rec.batteryLevel-batLow)*(h-3))/batChange; y = levelh - ((rec.batteryLevel-batLow)*(levelh-1))/batChange;
if (first) {
first = false; if (lastX != x) {
mBatLevelPath.moveTo(x, y); // We have moved by at least a pixel.
mBatLevelX[mNumBatLevel] = x; if (lastY == y) {
mBatLevelY[mNumBatLevel] = y; // Battery level is still the same; don't plot,
mBatLevelValue[mNumBatLevel] = lastBatValue = rec.batteryLevel; // but remember it.
mNumBatLevel++; lastBatX = x;
lastX = lastBatX = x; } else {
lastY = lastBatY = y; Path path;
} else { byte value = rec.batteryLevel;
if (lastX != x) { if (value <= BATTERY_CRITICAL) path = mBatCriticalPath;
// We have moved by at least a pixel. else if (value <= BATTERY_WARN) path = mBatWarnPath;
if (lastY == y) { else path = mBatGoodPath;
// Battery level is still the same; don't plot,
// but remember it. if (path != lastLinePath) {
lastBatX = x; if (lastLinePath != null) {
lastBatY = y; lastLinePath.lineTo(x, y);
}
path.moveTo(x, y);
lastLinePath = path;
} else { } else {
mBatLevelPath.lineTo(x, y); path.lineTo(x, y);
mBatLevelX[mNumBatLevel] = x; }
mBatLevelY[mNumBatLevel] = y;
mBatLevelValue[mNumBatLevel] = lastBatValue = rec.batteryLevel; if (curLevelPath == null) {
mNumBatLevel++; curLevelPath = mBatLevelPath;
num++; curLevelPath.moveTo(x, y);
lastX = x; startX = x;
lastY = y; } else {
lastBatX = -1; curLevelPath.lineTo(x, y);
}
lastX = x;
lastY = y;
lastBatX = -1;
final boolean charging =
(rec.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0;
if (charging != lastCharging) {
if (charging) {
mChargingPath.moveTo(x, h-mChargingOffset);
} else {
mChargingPath.lineTo(x, h-mChargingOffset);
}
lastCharging = charging;
}
final boolean screenOn =
(rec.states&HistoryItem.STATE_SCREEN_ON_FLAG) != 0;
if (screenOn != lastScreenOn) {
if (screenOn) {
mScreenOnPath.moveTo(x, h-mScreenOnOffset);
} else {
mScreenOnPath.lineTo(x, h-mScreenOnOffset);
}
lastScreenOn = screenOn;
} }
} }
} }
} else if (curLevelPath != null) {
finishPaths(x+1, h, levelh, startX, lastY, curLevelPath, lastBatX,
lastCharging, lastScreenOn, lastLinePath);
lastX = lastY = lastBatX = -1;
curLevelPath = null;
lastLinePath = null;
lastCharging = lastScreenOn = false;
} }
rec = rec.next; rec = rec.next;
i++; i++;
} }
if (num == 0 || lastBatX >= 0) { finishPaths(w, h, levelh, startX, lastY, curLevelPath, lastBatX,
mBatLevelPath.lineTo(w, y); lastCharging, lastScreenOn, lastLinePath);
mBatLevelX[mNumBatLevel] = w;
mBatLevelY[mNumBatLevel] = y;
mBatLevelValue[mNumBatLevel] = lastBatValue;
mNumBatLevel++;
}
mBatLevelPath.lineTo(w, h);
mBatLevelPath.lineTo(0, h);
mBatLevelPath.close();
} }
@Override @Override
@@ -348,20 +425,20 @@ public class BatteryHistoryChart extends View {
canvas.drawPath(mBatLevelPath, mBatteryBackgroundPaint); canvas.drawPath(mBatLevelPath, mBatteryBackgroundPaint);
canvas.drawText(mDurationString, (width/2) - (mDurationStringWidth/2), canvas.drawText(mDurationString, (width/2) - (mDurationStringWidth/2),
(height/2) - ((mTextDescent-mTextAscent)/2) - mTextAscent, mTextPaint); (height/2) - ((mTextDescent-mTextAscent)/2) - mTextAscent, mTextPaint);
if (!mBatGoodPath.isEmpty()) {
int lastX = mBatLevelX[0]; canvas.drawPath(mBatGoodPath, mBatteryGoodPaint);
int lastY = mBatLevelY[0]; }
for (int i=1; i<mNumBatLevel; i++) { if (!mBatWarnPath.isEmpty()) {
int x = mBatLevelX[i]; canvas.drawPath(mBatWarnPath, mBatteryWarnPaint);
int y = mBatLevelY[i]; }
Paint paint; if (!mBatCriticalPath.isEmpty()) {
byte value = mBatLevelValue[i]; canvas.drawPath(mBatCriticalPath, mBatteryCriticalPaint);
if (value <= BATTERY_CRITICAL) paint = mBatteryCriticalPaint; }
else if (value <= BATTERY_WARN) paint = mBatteryWarnPaint; if (!mChargingPath.isEmpty()) {
else paint = mBatteryGoodPaint; canvas.drawPath(mChargingPath, mChargingPaint);
canvas.drawLine(lastX, lastY, x, y, paint); }
lastX = x; if (!mScreenOnPath.isEmpty()) {
lastY = y; canvas.drawPath(mScreenOnPath, mScreenOnPaint);
} }
} }
} }