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:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user